summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit356978ecce23e076e1b622d5d41dd8c04bf7bcf8 (patch)
tree8e1874cc32750e30b84b2561387d48424e076ae3
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
-rw-r--r--demos/qmediaplayer/images/screen.pngbin0 -> 4358 bytes
-rw-r--r--demos/qmediaplayer/main.cpp93
-rw-r--r--demos/qmediaplayer/mediaplayer.cpp994
-rw-r--r--demos/qmediaplayer/mediaplayer.h184
-rw-r--r--demos/qmediaplayer/mediaplayer.qrc5
-rw-r--r--demos/qmediaplayer/qmediaplayer.pro39
-rw-r--r--demos/qmediaplayer/settings.ui495
-rw-r--r--examples/examples.pro2
-rw-r--r--examples/phonon/README39
-rw-r--r--examples/phonon/capabilities/capabilities.pro17
-rw-r--r--examples/phonon/capabilities/main.cpp57
-rw-r--r--examples/phonon/capabilities/window.cpp165
-rw-r--r--examples/phonon/capabilities/window.h96
-rw-r--r--examples/phonon/phonon.pro15
-rw-r--r--examples/phonon/qmusicplayer/main.cpp56
-rw-r--r--examples/phonon/qmusicplayer/mainwindow.cpp354
-rw-r--r--examples/phonon/qmusicplayer/mainwindow.h111
-rw-r--r--examples/phonon/qmusicplayer/qmusicplayer.pro17
-rw-r--r--src/3rdparty/phonon/CMakeLists.txt281
-rw-r--r--src/3rdparty/phonon/COPYING.LIB510
-rw-r--r--src/3rdparty/phonon/ds9/CMakeLists.txt54
-rw-r--r--src/3rdparty/phonon/ds9/ConfigureChecks.cmake44
-rw-r--r--src/3rdparty/phonon/ds9/abstractvideorenderer.cpp118
-rw-r--r--src/3rdparty/phonon/ds9/abstractvideorenderer.h73
-rw-r--r--src/3rdparty/phonon/ds9/audiooutput.cpp111
-rw-r--r--src/3rdparty/phonon/ds9/audiooutput.h68
-rw-r--r--src/3rdparty/phonon/ds9/backend.cpp351
-rw-r--r--src/3rdparty/phonon/ds9/backend.h87
-rw-r--r--src/3rdparty/phonon/ds9/backendnode.cpp134
-rw-r--r--src/3rdparty/phonon/ds9/backendnode.h73
-rw-r--r--src/3rdparty/phonon/ds9/compointer.h114
-rw-r--r--src/3rdparty/phonon/ds9/ds9.desktop93
-rw-r--r--src/3rdparty/phonon/ds9/effect.cpp152
-rw-r--r--src/3rdparty/phonon/ds9/effect.h59
-rw-r--r--src/3rdparty/phonon/ds9/fakesource.cpp144
-rw-r--r--src/3rdparty/phonon/ds9/fakesource.h54
-rw-r--r--src/3rdparty/phonon/ds9/iodevicereader.cpp175
-rw-r--r--src/3rdparty/phonon/ds9/iodevicereader.h56
-rw-r--r--src/3rdparty/phonon/ds9/lgpl-2.1.txt504
-rw-r--r--src/3rdparty/phonon/ds9/lgpl-3.txt165
-rw-r--r--src/3rdparty/phonon/ds9/mediagraph.cpp1101
-rw-r--r--src/3rdparty/phonon/ds9/mediagraph.h148
-rw-r--r--src/3rdparty/phonon/ds9/mediaobject.cpp1181
-rw-r--r--src/3rdparty/phonon/ds9/mediaobject.h313
-rw-r--r--src/3rdparty/phonon/ds9/phononds9_namespace.h33
-rw-r--r--src/3rdparty/phonon/ds9/qasyncreader.cpp186
-rw-r--r--src/3rdparty/phonon/ds9/qasyncreader.h75
-rw-r--r--src/3rdparty/phonon/ds9/qaudiocdreader.cpp312
-rw-r--r--src/3rdparty/phonon/ds9/qaudiocdreader.h58
-rw-r--r--src/3rdparty/phonon/ds9/qbasefilter.cpp832
-rw-r--r--src/3rdparty/phonon/ds9/qbasefilter.h136
-rw-r--r--src/3rdparty/phonon/ds9/qevr9.h143
-rw-r--r--src/3rdparty/phonon/ds9/qmeminputpin.cpp316
-rw-r--r--src/3rdparty/phonon/ds9/qmeminputpin.h77
-rw-r--r--src/3rdparty/phonon/ds9/qpin.cpp632
-rw-r--r--src/3rdparty/phonon/ds9/qpin.h120
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_default.cpp153
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_default.h55
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_evr.cpp219
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_evr.h56
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_soft.cpp1008
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_soft.h68
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp222
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_vmr9.h55
-rw-r--r--src/3rdparty/phonon/ds9/videowidget.cpp437
-rw-r--r--src/3rdparty/phonon/ds9/videowidget.h96
-rw-r--r--src/3rdparty/phonon/ds9/volumeeffect.cpp285
-rw-r--r--src/3rdparty/phonon/ds9/volumeeffect.h71
-rw-r--r--src/3rdparty/phonon/gstreamer/CMakeLists.txt92
-rw-r--r--src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake38
-rw-r--r--src/3rdparty/phonon/gstreamer/Messages.sh5
-rw-r--r--src/3rdparty/phonon/gstreamer/abstractrenderer.cpp57
-rw-r--r--src/3rdparty/phonon/gstreamer/abstractrenderer.h63
-rw-r--r--src/3rdparty/phonon/gstreamer/alsasink2.c1756
-rw-r--r--src/3rdparty/phonon/gstreamer/alsasink2.h87
-rw-r--r--src/3rdparty/phonon/gstreamer/artssink.cpp278
-rw-r--r--src/3rdparty/phonon/gstreamer/artssink.h91
-rw-r--r--src/3rdparty/phonon/gstreamer/audiodataoutput.cpp149
-rw-r--r--src/3rdparty/phonon/gstreamer/audiodataoutput.h90
-rw-r--r--src/3rdparty/phonon/gstreamer/audioeffect.cpp79
-rw-r--r--src/3rdparty/phonon/gstreamer/audioeffect.h55
-rw-r--r--src/3rdparty/phonon/gstreamer/audiooutput.cpp256
-rw-r--r--src/3rdparty/phonon/gstreamer/audiooutput.h82
-rw-r--r--src/3rdparty/phonon/gstreamer/backend.cpp491
-rw-r--r--src/3rdparty/phonon/gstreamer/backend.h100
-rw-r--r--src/3rdparty/phonon/gstreamer/common.h51
-rw-r--r--src/3rdparty/phonon/gstreamer/devicemanager.cpp396
-rw-r--r--src/3rdparty/phonon/gstreamer/devicemanager.h84
-rw-r--r--src/3rdparty/phonon/gstreamer/effect.cpp246
-rw-r--r--src/3rdparty/phonon/gstreamer/effect.h64
-rw-r--r--src/3rdparty/phonon/gstreamer/effectmanager.cpp105
-rw-r--r--src/3rdparty/phonon/gstreamer/effectmanager.h91
-rw-r--r--src/3rdparty/phonon/gstreamer/glrenderer.cpp339
-rw-r--r--src/3rdparty/phonon/gstreamer/glrenderer.h101
-rw-r--r--src/3rdparty/phonon/gstreamer/gsthelper.cpp170
-rw-r--r--src/3rdparty/phonon/gstreamer/gsthelper.h49
-rw-r--r--src/3rdparty/phonon/gstreamer/gstreamer.desktop108
-rw-r--r--src/3rdparty/phonon/gstreamer/lgpl-2.1.txt504
-rw-r--r--src/3rdparty/phonon/gstreamer/lgpl-3.txt165
-rw-r--r--src/3rdparty/phonon/gstreamer/medianode.cpp456
-rw-r--r--src/3rdparty/phonon/gstreamer/medianode.h128
-rw-r--r--src/3rdparty/phonon/gstreamer/medianodeevent.cpp38
-rw-r--r--src/3rdparty/phonon/gstreamer/medianodeevent.h70
-rw-r--r--src/3rdparty/phonon/gstreamer/mediaobject.cpp1698
-rw-r--r--src/3rdparty/phonon/gstreamer/mediaobject.h294
-rw-r--r--src/3rdparty/phonon/gstreamer/message.cpp75
-rw-r--r--src/3rdparty/phonon/gstreamer/message.h58
-rw-r--r--src/3rdparty/phonon/gstreamer/phononsrc.cpp285
-rw-r--r--src/3rdparty/phonon/gstreamer/phononsrc.h71
-rw-r--r--src/3rdparty/phonon/gstreamer/qwidgetvideosink.cpp221
-rw-r--r--src/3rdparty/phonon/gstreamer/qwidgetvideosink.h98
-rw-r--r--src/3rdparty/phonon/gstreamer/streamreader.cpp54
-rw-r--r--src/3rdparty/phonon/gstreamer/streamreader.h100
-rw-r--r--src/3rdparty/phonon/gstreamer/videowidget.cpp393
-rw-r--r--src/3rdparty/phonon/gstreamer/videowidget.h108
-rw-r--r--src/3rdparty/phonon/gstreamer/volumefadereffect.cpp162
-rw-r--r--src/3rdparty/phonon/gstreamer/volumefadereffect.h70
-rw-r--r--src/3rdparty/phonon/gstreamer/widgetrenderer.cpp152
-rw-r--r--src/3rdparty/phonon/gstreamer/widgetrenderer.h64
-rw-r--r--src/3rdparty/phonon/gstreamer/x11renderer.cpp195
-rw-r--r--src/3rdparty/phonon/gstreamer/x11renderer.h64
-rw-r--r--src/3rdparty/phonon/includes/CMakeLists.txt49
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AbstractAudioOutput1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AbstractMediaStream1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AbstractVideoOutput1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AddonInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AudioDevice1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AudioDeviceEnumerator1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AudioOutput1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AudioOutputDevice1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AudioOutputDeviceModel1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/AudioOutputInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/BackendCapabilities1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/BackendInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Effect1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/EffectDescription1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/EffectDescriptionModel1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/EffectInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/EffectParameter1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/EffectWidget1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/AbstractVideoDataOutput1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/AudioDataOutput1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/SnapshotInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutput1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutputInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame21
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Experimental/Visualization1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Global1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/MediaController1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/MediaNode1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/MediaObject1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/MediaObjectInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/MediaSource1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/ObjectDescription1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/ObjectDescriptionModel1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/Path1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/PlatformPlugin1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/SeekSlider1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/StreamInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/VideoPlayer1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/VideoWidget1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/VideoWidgetInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/VolumeFaderEffect1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/VolumeFaderInterface1
-rw-r--r--src/3rdparty/phonon/includes/Phonon/VolumeSlider1
-rw-r--r--src/3rdparty/phonon/mmf/abstractaudioeffect.cpp195
-rw-r--r--src/3rdparty/phonon/mmf/abstractaudioeffect.h142
-rw-r--r--src/3rdparty/phonon/mmf/abstractmediaplayer.cpp707
-rw-r--r--src/3rdparty/phonon/mmf/abstractmediaplayer.h161
-rw-r--r--src/3rdparty/phonon/mmf/abstractplayer.cpp199
-rw-r--r--src/3rdparty/phonon/mmf/abstractplayer.h176
-rw-r--r--src/3rdparty/phonon/mmf/abstractvideooutput.cpp172
-rw-r--r--src/3rdparty/phonon/mmf/abstractvideooutput.h93
-rw-r--r--src/3rdparty/phonon/mmf/abstractvideoplayer.cpp518
-rw-r--r--src/3rdparty/phonon/mmf/abstractvideoplayer.h173
-rw-r--r--src/3rdparty/phonon/mmf/ancestormovemonitor.cpp179
-rw-r--r--src/3rdparty/phonon/mmf/ancestormovemonitor.h95
-rw-r--r--src/3rdparty/phonon/mmf/audioequalizer.cpp106
-rw-r--r--src/3rdparty/phonon/mmf/audioequalizer.h67
-rw-r--r--src/3rdparty/phonon/mmf/audiooutput.cpp114
-rw-r--r--src/3rdparty/phonon/mmf/audiooutput.h94
-rw-r--r--src/3rdparty/phonon/mmf/audioplayer.cpp293
-rw-r--r--src/3rdparty/phonon/mmf/audioplayer.h124
-rw-r--r--src/3rdparty/phonon/mmf/backend.cpp223
-rw-r--r--src/3rdparty/phonon/mmf/backend.h70
-rw-r--r--src/3rdparty/phonon/mmf/bassboost.cpp59
-rw-r--r--src/3rdparty/phonon/mmf/bassboost.h60
-rw-r--r--src/3rdparty/phonon/mmf/defs.h52
-rw-r--r--src/3rdparty/phonon/mmf/download.cpp199
-rw-r--r--src/3rdparty/phonon/mmf/download.h109
-rw-r--r--src/3rdparty/phonon/mmf/dummyplayer.cpp115
-rw-r--r--src/3rdparty/phonon/mmf/dummyplayer.h69
-rw-r--r--src/3rdparty/phonon/mmf/effectfactory.cpp215
-rw-r--r--src/3rdparty/phonon/mmf/effectfactory.h101
-rw-r--r--src/3rdparty/phonon/mmf/effectparameter.cpp71
-rw-r--r--src/3rdparty/phonon/mmf/effectparameter.h74
-rw-r--r--src/3rdparty/phonon/mmf/environmentalreverb.cpp212
-rw-r--r--src/3rdparty/phonon/mmf/environmentalreverb.h62
-rw-r--r--src/3rdparty/phonon/mmf/loudness.cpp59
-rw-r--r--src/3rdparty/phonon/mmf/loudness.h60
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.cpp561
-rw-r--r--src/3rdparty/phonon/mmf/mediaobject.h160
-rw-r--r--src/3rdparty/phonon/mmf/mmf_medianode.cpp152
-rw-r--r--src/3rdparty/phonon/mmf/mmf_medianode.h108
-rw-r--r--src/3rdparty/phonon/mmf/objectdump.cpp525
-rw-r--r--src/3rdparty/phonon/mmf/objectdump.h164
-rw-r--r--src/3rdparty/phonon/mmf/objectdump_symbian.cpp160
-rw-r--r--src/3rdparty/phonon/mmf/objectdump_symbian.h66
-rw-r--r--src/3rdparty/phonon/mmf/objecttree.cpp100
-rw-r--r--src/3rdparty/phonon/mmf/objecttree.h115
-rw-r--r--src/3rdparty/phonon/mmf/stereowidening.cpp93
-rw-r--r--src/3rdparty/phonon/mmf/stereowidening.h62
-rw-r--r--src/3rdparty/phonon/mmf/utils.cpp260
-rw-r--r--src/3rdparty/phonon/mmf/utils.h176
-rw-r--r--src/3rdparty/phonon/mmf/videooutput_dsa.cpp183
-rw-r--r--src/3rdparty/phonon/mmf/videooutput_dsa.h109
-rw-r--r--src/3rdparty/phonon/mmf/videooutput_surface.cpp87
-rw-r--r--src/3rdparty/phonon/mmf/videooutput_surface.h66
-rw-r--r--src/3rdparty/phonon/mmf/videoplayer_dsa.cpp317
-rw-r--r--src/3rdparty/phonon/mmf/videoplayer_dsa.h92
-rw-r--r--src/3rdparty/phonon/mmf/videoplayer_surface.cpp185
-rw-r--r--src/3rdparty/phonon/mmf/videoplayer_surface.h81
-rw-r--r--src/3rdparty/phonon/mmf/videowidget.cpp192
-rw-r--r--src/3rdparty/phonon/mmf/videowidget.h87
-rw-r--r--src/3rdparty/phonon/phonon.pc.cmake11
-rw-r--r--src/3rdparty/phonon/phonon/.krazy2
-rw-r--r--src/3rdparty/phonon/phonon/BUGS9
-rw-r--r--src/3rdparty/phonon/phonon/CMakeLists.txt139
-rw-r--r--src/3rdparty/phonon/phonon/IDEAS70
-rw-r--r--src/3rdparty/phonon/phonon/Messages.sh6
-rw-r--r--src/3rdparty/phonon/phonon/TODO31
-rw-r--r--src/3rdparty/phonon/phonon/abstractaudiooutput.cpp50
-rw-r--r--src/3rdparty/phonon/phonon/abstractaudiooutput.h57
-rw-r--r--src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp44
-rw-r--r--src/3rdparty/phonon/phonon/abstractaudiooutput_p.h50
-rw-r--r--src/3rdparty/phonon/phonon/abstractmediastream.cpp197
-rw-r--r--src/3rdparty/phonon/phonon/abstractmediastream.h227
-rw-r--r--src/3rdparty/phonon/phonon/abstractmediastream_p.h83
-rw-r--r--src/3rdparty/phonon/phonon/abstractvideooutput.cpp41
-rw-r--r--src/3rdparty/phonon/phonon/abstractvideooutput.h74
-rw-r--r--src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp41
-rw-r--r--src/3rdparty/phonon/phonon/abstractvideooutput_p.h48
-rw-r--r--src/3rdparty/phonon/phonon/addoninterface.h103
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutput.cpp72
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutput.h135
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutput_p.h54
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutputinterface.h50
-rw-r--r--src/3rdparty/phonon/phonon/audiooutput.cpp511
-rw-r--r--src/3rdparty/phonon/phonon/audiooutput.h180
-rw-r--r--src/3rdparty/phonon/phonon/audiooutput_p.h101
-rw-r--r--src/3rdparty/phonon/phonon/audiooutputadaptor.cpp101
-rw-r--r--src/3rdparty/phonon/phonon/audiooutputadaptor_p.h109
-rw-r--r--src/3rdparty/phonon/phonon/audiooutputinterface.cpp40
-rw-r--r--src/3rdparty/phonon/phonon/audiooutputinterface.h151
-rw-r--r--src/3rdparty/phonon/phonon/backend.dox107
-rw-r--r--src/3rdparty/phonon/phonon/backendcapabilities.cpp123
-rw-r--r--src/3rdparty/phonon/phonon/backendcapabilities.h212
-rw-r--r--src/3rdparty/phonon/phonon/backendcapabilities_p.h50
-rw-r--r--src/3rdparty/phonon/phonon/backendinterface.h287
-rw-r--r--src/3rdparty/phonon/phonon/effect.cpp138
-rw-r--r--src/3rdparty/phonon/phonon/effect.h119
-rw-r--r--src/3rdparty/phonon/phonon/effect_p.h61
-rw-r--r--src/3rdparty/phonon/phonon/effectinterface.h68
-rw-r--r--src/3rdparty/phonon/phonon/effectparameter.cpp142
-rw-r--r--src/3rdparty/phonon/phonon/effectparameter.h237
-rw-r--r--src/3rdparty/phonon/phonon/effectparameter_p.h56
-rw-r--r--src/3rdparty/phonon/phonon/effectwidget.cpp259
-rw-r--r--src/3rdparty/phonon/phonon/effectwidget.h76
-rw-r--r--src/3rdparty/phonon/phonon/effectwidget_p.h64
-rwxr-xr-xsrc/3rdparty/phonon/phonon/extractmethodcalls.rb527
-rw-r--r--src/3rdparty/phonon/phonon/factory.cpp474
-rw-r--r--src/3rdparty/phonon/phonon/factory_p.h203
-rw-r--r--src/3rdparty/phonon/phonon/frontendinterface_p.h68
-rw-r--r--src/3rdparty/phonon/phonon/globalconfig.cpp449
-rw-r--r--src/3rdparty/phonon/phonon/globalconfig.h71
-rw-r--r--src/3rdparty/phonon/phonon/globalconfig_p.h48
-rw-r--r--src/3rdparty/phonon/phonon/globalstatic_p.h293
-rw-r--r--src/3rdparty/phonon/phonon/iodevicestream.cpp100
-rw-r--r--src/3rdparty/phonon/phonon/iodevicestream_p.h58
-rw-r--r--src/3rdparty/phonon/phonon/mediacontroller.cpp239
-rw-r--r--src/3rdparty/phonon/phonon/mediacontroller.h188
-rw-r--r--src/3rdparty/phonon/phonon/medianode.cpp130
-rw-r--r--src/3rdparty/phonon/phonon/medianode.h69
-rw-r--r--src/3rdparty/phonon/phonon/medianode_p.h145
-rw-r--r--src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h62
-rw-r--r--src/3rdparty/phonon/phonon/mediaobject.cpp572
-rw-r--r--src/3rdparty/phonon/phonon/mediaobject.dox71
-rw-r--r--src/3rdparty/phonon/phonon/mediaobject.h623
-rw-r--r--src/3rdparty/phonon/phonon/mediaobject_p.h113
-rw-r--r--src/3rdparty/phonon/phonon/mediaobjectinterface.h242
-rw-r--r--src/3rdparty/phonon/phonon/mediasource.cpp237
-rw-r--r--src/3rdparty/phonon/phonon/mediasource.h279
-rw-r--r--src/3rdparty/phonon/phonon/mediasource_p.h89
-rw-r--r--src/3rdparty/phonon/phonon/objectdescription.cpp152
-rw-r--r--src/3rdparty/phonon/phonon/objectdescription.h342
-rw-r--r--src/3rdparty/phonon/phonon/objectdescription_p.h64
-rw-r--r--src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp387
-rw-r--r--src/3rdparty/phonon/phonon/objectdescriptionmodel.h388
-rw-r--r--src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h65
-rw-r--r--src/3rdparty/phonon/phonon/org.kde.Phonon.AudioOutput.xml32
-rw-r--r--src/3rdparty/phonon/phonon/path.cpp476
-rw-r--r--src/3rdparty/phonon/phonon/path.h243
-rw-r--r--src/3rdparty/phonon/phonon/path_p.h79
-rw-r--r--src/3rdparty/phonon/phonon/phonon_export.h62
-rw-r--r--src/3rdparty/phonon/phonon/phonondefs.h149
-rw-r--r--src/3rdparty/phonon/phonon/phonondefs_p.h369
-rw-r--r--src/3rdparty/phonon/phonon/phononnamespace.cpp92
-rw-r--r--src/3rdparty/phonon/phonon/phononnamespace.h311
-rw-r--r--src/3rdparty/phonon/phonon/phononnamespace.h.in306
-rw-r--r--src/3rdparty/phonon/phonon/phononnamespace_p.h38
-rw-r--r--src/3rdparty/phonon/phonon/platform.cpp144
-rw-r--r--src/3rdparty/phonon/phonon/platform_p.h62
-rw-r--r--src/3rdparty/phonon/phonon/platformplugin.h118
-rwxr-xr-xsrc/3rdparty/phonon/phonon/preprocessandextract.sh39
-rw-r--r--src/3rdparty/phonon/phonon/pulsesupport.cpp1038
-rw-r--r--src/3rdparty/phonon/phonon/pulsesupport.h78
-rw-r--r--src/3rdparty/phonon/phonon/qsettingsgroup_p.h94
-rw-r--r--src/3rdparty/phonon/phonon/seekslider.cpp263
-rw-r--r--src/3rdparty/phonon/phonon/seekslider.h157
-rw-r--r--src/3rdparty/phonon/phonon/seekslider_p.h101
-rw-r--r--src/3rdparty/phonon/phonon/stream-thoughts72
-rw-r--r--src/3rdparty/phonon/phonon/streaminterface.cpp114
-rw-r--r--src/3rdparty/phonon/phonon/streaminterface.h123
-rw-r--r--src/3rdparty/phonon/phonon/streaminterface_p.h59
-rw-r--r--src/3rdparty/phonon/phonon/swiftslider.cpp103
-rw-r--r--src/3rdparty/phonon/phonon/swiftslider_p.h68
-rw-r--r--src/3rdparty/phonon/phonon/videoplayer.cpp184
-rw-r--r--src/3rdparty/phonon/phonon/videoplayer.h207
-rw-r--r--src/3rdparty/phonon/phonon/videowidget.cpp195
-rw-r--r--src/3rdparty/phonon/phonon/videowidget.h220
-rw-r--r--src/3rdparty/phonon/phonon/videowidget_p.h84
-rw-r--r--src/3rdparty/phonon/phonon/videowidgetinterface.h78
-rw-r--r--src/3rdparty/phonon/phonon/volumefadereffect.cpp108
-rw-r--r--src/3rdparty/phonon/phonon/volumefadereffect.h178
-rw-r--r--src/3rdparty/phonon/phonon/volumefadereffect_p.h58
-rw-r--r--src/3rdparty/phonon/phonon/volumefaderinterface.h58
-rw-r--r--src/3rdparty/phonon/phonon/volumeslider.cpp262
-rw-r--r--src/3rdparty/phonon/phonon/volumeslider.h155
-rw-r--r--src/3rdparty/phonon/phonon/volumeslider_p.h101
-rw-r--r--src/3rdparty/phonon/qt7/CMakeLists.txt58
-rw-r--r--src/3rdparty/phonon/qt7/ConfigureChecks.cmake16
-rw-r--r--src/3rdparty/phonon/qt7/audioconnection.h84
-rw-r--r--src/3rdparty/phonon/qt7/audioconnection.mm152
-rw-r--r--src/3rdparty/phonon/qt7/audiodevice.h52
-rw-r--r--src/3rdparty/phonon/qt7/audiodevice.mm176
-rw-r--r--src/3rdparty/phonon/qt7/audioeffects.h80
-rw-r--r--src/3rdparty/phonon/qt7/audioeffects.mm254
-rw-r--r--src/3rdparty/phonon/qt7/audiograph.h86
-rw-r--r--src/3rdparty/phonon/qt7/audiograph.mm320
-rw-r--r--src/3rdparty/phonon/qt7/audiomixer.h91
-rw-r--r--src/3rdparty/phonon/qt7/audiomixer.mm181
-rw-r--r--src/3rdparty/phonon/qt7/audionode.h86
-rw-r--r--src/3rdparty/phonon/qt7/audionode.mm243
-rw-r--r--src/3rdparty/phonon/qt7/audiooutput.h88
-rw-r--r--src/3rdparty/phonon/qt7/audiooutput.mm168
-rw-r--r--src/3rdparty/phonon/qt7/audiopartoutput.h47
-rw-r--r--src/3rdparty/phonon/qt7/audiopartoutput.mm69
-rw-r--r--src/3rdparty/phonon/qt7/audiosplitter.h50
-rw-r--r--src/3rdparty/phonon/qt7/audiosplitter.mm52
-rw-r--r--src/3rdparty/phonon/qt7/backend.h61
-rw-r--r--src/3rdparty/phonon/qt7/backend.mm276
-rw-r--r--src/3rdparty/phonon/qt7/backendheader.h184
-rw-r--r--src/3rdparty/phonon/qt7/backendheader.mm127
-rw-r--r--src/3rdparty/phonon/qt7/backendinfo.h48
-rw-r--r--src/3rdparty/phonon/qt7/backendinfo.mm311
-rw-r--r--src/3rdparty/phonon/qt7/lgpl-2.1.txt504
-rw-r--r--src/3rdparty/phonon/qt7/lgpl-3.txt165
-rw-r--r--src/3rdparty/phonon/qt7/medianode.h85
-rw-r--r--src/3rdparty/phonon/qt7/medianode.mm261
-rw-r--r--src/3rdparty/phonon/qt7/medianodeevent.h71
-rw-r--r--src/3rdparty/phonon/qt7/medianodeevent.mm37
-rw-r--r--src/3rdparty/phonon/qt7/medianodevideopart.h42
-rw-r--r--src/3rdparty/phonon/qt7/medianodevideopart.mm37
-rw-r--r--src/3rdparty/phonon/qt7/mediaobject.h171
-rw-r--r--src/3rdparty/phonon/qt7/mediaobject.mm852
-rw-r--r--src/3rdparty/phonon/qt7/mediaobjectaudionode.h75
-rw-r--r--src/3rdparty/phonon/qt7/mediaobjectaudionode.mm209
-rw-r--r--src/3rdparty/phonon/qt7/quicktimeaudioplayer.h112
-rw-r--r--src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm493
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.h67
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.mm187
-rw-r--r--src/3rdparty/phonon/qt7/quicktimestreamreader.h71
-rw-r--r--src/3rdparty/phonon/qt7/quicktimestreamreader.mm137
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.h167
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.mm955
-rw-r--r--src/3rdparty/phonon/qt7/videoeffect.h63
-rw-r--r--src/3rdparty/phonon/qt7/videoeffect.mm76
-rw-r--r--src/3rdparty/phonon/qt7/videoframe.h98
-rw-r--r--src/3rdparty/phonon/qt7/videoframe.mm378
-rw-r--r--src/3rdparty/phonon/qt7/videowidget.h71
-rw-r--r--src/3rdparty/phonon/qt7/videowidget.mm885
-rw-r--r--src/3rdparty/phonon/waveout/audiooutput.cpp78
-rw-r--r--src/3rdparty/phonon/waveout/audiooutput.h65
-rw-r--r--src/3rdparty/phonon/waveout/backend.cpp131
-rw-r--r--src/3rdparty/phonon/waveout/backend.h69
-rw-r--r--src/3rdparty/phonon/waveout/mediaobject.cpp686
-rw-r--r--src/3rdparty/phonon/waveout/mediaobject.h162
-rw-r--r--src/phonon/phonon.pro145
-rw-r--r--src/plugins/phonon/ds9/ds9.pro66
-rw-r--r--src/plugins/phonon/gstreamer/gstreamer.pro69
-rw-r--r--src/plugins/phonon/mmf/mmf.pro146
-rw-r--r--src/plugins/phonon/phonon.pro14
-rw-r--r--src/plugins/phonon/qt7/qt7.pro76
-rw-r--r--src/plugins/phonon/waveout/waveout.pro23
-rw-r--r--tests/README18
-rw-r--r--tests/auto/bic/.gitignore2
-rw-r--r--tests/auto/bic/data/phonon.4.5.0.linux-gcc-amd64.txt1931
-rw-r--r--tests/auto/bic/data/phonon.4.5.0.linux-gcc-ia32.txt1930
-rw-r--r--tests/auto/bic/data/phonon.4.6.0.linux-gcc-amd64.txt1980
-rw-r--r--tests/auto/bic/data/phonon.4.6.0.linux-gcc-ia32.txt1980
-rw-r--r--tests/auto/bic/data/phonon.4.7.0.linux-gcc-ia32.txt2095
-rw-r--r--tests/auto/mediaobject/.gitignore1
-rw-r--r--tests/auto/mediaobject/dummy/README1
-rw-r--r--tests/auto/mediaobject/dummy/audiooutput.cpp94
-rw-r--r--tests/auto/mediaobject/dummy/audiooutput.h82
-rw-r--r--tests/auto/mediaobject/dummy/backend.cpp190
-rw-r--r--tests/auto/mediaobject/dummy/backend.h96
-rw-r--r--tests/auto/mediaobject/dummy/dummy.pro23
-rw-r--r--tests/auto/mediaobject/dummy/mediaobject.cpp438
-rw-r--r--tests/auto/mediaobject/dummy/mediaobject.h210
-rw-r--r--tests/auto/mediaobject/dummy/videowidget.cpp246
-rw-r--r--tests/auto/mediaobject/dummy/videowidget.h111
-rw-r--r--tests/auto/mediaobject/media/sax.mp3bin0 -> 417844 bytes
-rw-r--r--tests/auto/mediaobject/media/sax.oggbin0 -> 358374 bytes
-rw-r--r--tests/auto/mediaobject/media/sax.wavbin0 -> 756236 bytes
-rw-r--r--tests/auto/mediaobject/media/test.sdp32
-rwxr-xr-xtests/auto/mediaobject/mediaobject.pro24
-rw-r--r--tests/auto/mediaobject/mediaobject.qrc8
-rw-r--r--tests/auto/mediaobject/qtesthelper.h222
-rw-r--r--tests/auto/mediaobject/tst_mediaobject.cpp1220
-rw-r--r--tests/auto/mediaobject_wince_ds9/dummy.cpp44
-rw-r--r--tests/auto/mediaobject_wince_ds9/mediaobject_wince_ds9.pro18
-rw-r--r--tests/auto/phonon.pro5
-rw-r--r--tests/global/.gitignore2
435 files changed, 77829 insertions, 0 deletions
diff --git a/demos/qmediaplayer/images/screen.png b/demos/qmediaplayer/images/screen.png
new file mode 100644
index 0000000..a15df92
--- /dev/null
+++ b/demos/qmediaplayer/images/screen.png
Binary files differ
diff --git a/demos/qmediaplayer/main.cpp b/demos/qmediaplayer/main.cpp
new file mode 100644
index 0000000..af2a330
--- /dev/null
+++ b/demos/qmediaplayer/main.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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 demonstration applications 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 <QtGui>
+#include "mediaplayer.h"
+
+const qreal DefaultVolume = -1.0;
+
+int main (int argc, char *argv[])
+{
+ Q_INIT_RESOURCE(mediaplayer);
+ QApplication app(argc, argv);
+ app.setApplicationName("Media Player");
+ app.setOrganizationName("Qt");
+ app.setQuitOnLastWindowClosed(true);
+
+ QString fileName;
+ qreal volume = DefaultVolume;
+ bool smallScreen = false;
+#ifdef Q_OS_SYMBIAN
+ smallScreen = true;
+#endif
+
+ QStringList args(app.arguments());
+ args.removeFirst(); // remove name of executable
+ while (!args.empty()) {
+ const QString &arg = args.first();
+ if (QLatin1String("-small-screen") == arg || QLatin1String("--small-screen") == arg) {
+ smallScreen = true;
+ } else if (QLatin1String("-volume") == arg || QLatin1String("--volume") == arg) {
+ if (!args.empty()) {
+ args.removeFirst();
+ volume = qMax(qMin(args.first().toFloat(), float(1.0)), float(0.0));
+ }
+ } else if (fileName.isNull()) {
+ fileName = arg;
+ }
+ args.removeFirst();
+ }
+
+ MediaPlayer player;
+ player.setSmallScreen(smallScreen);
+ if (DefaultVolume != volume)
+ player.setVolume(volume);
+ if (!fileName.isNull())
+ player.setFile(fileName);
+
+ if (smallScreen)
+ player.showMaximized();
+ else
+ player.show();
+
+ return app.exec();
+}
+
diff --git a/demos/qmediaplayer/mediaplayer.cpp b/demos/qmediaplayer/mediaplayer.cpp
new file mode 100644
index 0000000..68752a0
--- /dev/null
+++ b/demos/qmediaplayer/mediaplayer.cpp
@@ -0,0 +1,994 @@
+/****************************************************************************
+**
+** 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 demonstration applications 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 <QtGui>
+
+#define SLIDER_RANGE 8
+
+#include "mediaplayer.h"
+#include "ui_settings.h"
+
+#ifdef Q_OS_SYMBIAN
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
+#endif
+
+MediaVideoWidget::MediaVideoWidget(MediaPlayer *player, QWidget *parent) :
+ Phonon::VideoWidget(parent), m_player(player), m_action(this)
+{
+ m_action.setCheckable(true);
+ m_action.setChecked(false);
+ m_action.setShortcut(QKeySequence( Qt::AltModifier + Qt::Key_Return));
+ m_action.setShortcutContext(Qt::WindowShortcut);
+ connect(&m_action, SIGNAL(toggled(bool)), SLOT(setFullScreen(bool)));
+ addAction(&m_action);
+ setAcceptDrops(true);
+}
+
+void MediaVideoWidget::setFullScreen(bool enabled)
+{
+ Phonon::VideoWidget::setFullScreen(enabled);
+ emit fullScreenChanged(enabled);
+}
+
+void MediaVideoWidget::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ Phonon::VideoWidget::mouseDoubleClickEvent(e);
+ setFullScreen(!isFullScreen());
+}
+
+void MediaVideoWidget::keyPressEvent(QKeyEvent *e)
+{
+ if(!e->modifiers()) {
+ // On non-QWERTY Symbian key-based devices, there is no space key.
+ // The zero key typically is marked with a space character.
+ if (e->key() == Qt::Key_Space || e->key() == Qt::Key_0) {
+ m_player->playPause();
+ e->accept();
+ return;
+ }
+
+ // On Symbian devices, there is no key which maps to Qt::Key_Escape
+ // On devices which lack a backspace key (i.e. non-QWERTY devices),
+ // the 'C' key maps to Qt::Key_Backspace
+ else if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Backspace) {
+ setFullScreen(false);
+ e->accept();
+ return;
+ }
+ }
+ Phonon::VideoWidget::keyPressEvent(e);
+}
+
+bool MediaVideoWidget::event(QEvent *e)
+{
+ switch(e->type())
+ {
+ case QEvent::Close:
+ //we just ignore the cose events on the video widget
+ //this prevents ALT+F4 from having an effect in fullscreen mode
+ e->ignore();
+ return true;
+ case QEvent::MouseMove:
+#ifndef QT_NO_CURSOR
+ unsetCursor();
+#endif
+ //fall through
+ case QEvent::WindowStateChange:
+ {
+ //we just update the state of the checkbox, in case it wasn't already
+ m_action.setChecked(windowState() & Qt::WindowFullScreen);
+ const Qt::WindowFlags flags = m_player->windowFlags();
+ if (windowState() & Qt::WindowFullScreen) {
+ m_timer.start(1000, this);
+ } else {
+ m_timer.stop();
+#ifndef QT_NO_CURSOR
+ unsetCursor();
+#endif
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return Phonon::VideoWidget::event(e);
+}
+
+void MediaVideoWidget::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == m_timer.timerId()) {
+ //let's store the cursor shape
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::BlankCursor);
+#endif
+ }
+ Phonon::VideoWidget::timerEvent(e);
+}
+
+void MediaVideoWidget::dropEvent(QDropEvent *e)
+{
+ m_player->handleDrop(e);
+}
+
+void MediaVideoWidget::dragEnterEvent(QDragEnterEvent *e) {
+ if (e->mimeData()->hasUrls())
+ e->acceptProposedAction();
+}
+
+
+MediaPlayer::MediaPlayer() :
+ playButton(0), nextEffect(0), settingsDialog(0), ui(0),
+ m_AudioOutput(Phonon::VideoCategory),
+ m_videoWidget(new MediaVideoWidget(this))
+{
+ setWindowTitle(tr("Media Player"));
+ setContextMenuPolicy(Qt::CustomContextMenu);
+ m_videoWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ QSize buttonSize(34, 28);
+
+ QPushButton *openButton = new QPushButton(this);
+
+ openButton->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
+ QPalette bpal;
+ QColor arrowcolor = bpal.buttonText().color();
+ if (arrowcolor == Qt::black)
+ arrowcolor = QColor(80, 80, 80);
+ bpal.setBrush(QPalette::ButtonText, arrowcolor);
+ openButton->setPalette(bpal);
+
+ rewindButton = new QPushButton(this);
+ rewindButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
+
+ forwardButton = new QPushButton(this);
+ forwardButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward));
+ forwardButton->setEnabled(false);
+
+ playButton = new QPushButton(this);
+ playIcon = style()->standardIcon(QStyle::SP_MediaPlay);
+ pauseIcon = style()->standardIcon(QStyle::SP_MediaPause);
+ playButton->setIcon(playIcon);
+
+ slider = new Phonon::SeekSlider(this);
+ slider->setMediaObject(&m_MediaObject);
+ volume = new Phonon::VolumeSlider(&m_AudioOutput);
+
+ QVBoxLayout *vLayout = new QVBoxLayout(this);
+ vLayout->setContentsMargins(8, 8, 8, 8);
+
+ QHBoxLayout *layout = new QHBoxLayout();
+
+ info = new QLabel(this);
+ info->setMinimumHeight(70);
+ info->setAcceptDrops(false);
+ info->setMargin(2);
+ info->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ info->setLineWidth(2);
+ info->setAutoFillBackground(true);
+
+ QPalette palette;
+ palette.setBrush(QPalette::WindowText, Qt::white);
+#ifndef Q_WS_MAC
+ openButton->setMinimumSize(54, buttonSize.height());
+ rewindButton->setMinimumSize(buttonSize);
+ forwardButton->setMinimumSize(buttonSize);
+ playButton->setMinimumSize(buttonSize);
+#endif
+ info->setStyleSheet("border-image:url(:/images/screen.png) ; border-width:3px");
+ info->setPalette(palette);
+ info->setText(tr("<center>No media</center>"));
+
+ volume->setFixedWidth(120);
+
+ layout->addWidget(openButton);
+ layout->addWidget(rewindButton);
+ layout->addWidget(playButton);
+ layout->addWidget(forwardButton);
+
+ layout->addStretch();
+ layout->addWidget(volume);
+
+ vLayout->addWidget(info);
+ initVideoWindow();
+ vLayout->addWidget(&m_videoWindow);
+ QVBoxLayout *buttonPanelLayout = new QVBoxLayout();
+ m_videoWindow.hide();
+ buttonPanelLayout->addLayout(layout);
+
+ timeLabel = new QLabel(this);
+ progressLabel = new QLabel(this);
+ QWidget *sliderPanel = new QWidget(this);
+ QHBoxLayout *sliderLayout = new QHBoxLayout();
+ sliderLayout->addWidget(slider);
+ sliderLayout->addWidget(timeLabel);
+ sliderLayout->addWidget(progressLabel);
+ sliderLayout->setContentsMargins(0, 0, 0, 0);
+ sliderPanel->setLayout(sliderLayout);
+
+ buttonPanelLayout->addWidget(sliderPanel);
+ buttonPanelLayout->setContentsMargins(0, 0, 0, 0);
+#ifdef Q_OS_MAC
+ layout->setSpacing(4);
+ buttonPanelLayout->setSpacing(0);
+ info->setMinimumHeight(100);
+ info->setFont(QFont("verdana", 15));
+ // QStyle *flatButtonStyle = new QWindowsStyle;
+ openButton->setFocusPolicy(Qt::NoFocus);
+ // openButton->setStyle(flatButtonStyle);
+ // playButton->setStyle(flatButtonStyle);
+ // rewindButton->setStyle(flatButtonStyle);
+ // forwardButton->setStyle(flatButtonStyle);
+ #endif
+ QWidget *buttonPanelWidget = new QWidget(this);
+ buttonPanelWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ buttonPanelWidget->setLayout(buttonPanelLayout);
+ vLayout->addWidget(buttonPanelWidget);
+
+ QHBoxLayout *labelLayout = new QHBoxLayout();
+
+ vLayout->addLayout(labelLayout);
+ setLayout(vLayout);
+
+ // Create menu bar:
+ fileMenu = new QMenu(this);
+ QAction *openFileAction = fileMenu->addAction(tr("Open &File..."));
+ QAction *openUrlAction = fileMenu->addAction(tr("Open &Location..."));
+#ifdef Q_OS_SYMBIAN
+ QAction *selectIAPAction = fileMenu->addAction(tr("Select &IAP..."));
+ connect(selectIAPAction, SIGNAL(triggered(bool)), this, SLOT(selectIAP()));
+#endif
+ QAction *const openLinkAction = fileMenu->addAction(tr("Open &RAM File..."));
+
+ connect(openLinkAction, SIGNAL(triggered(bool)), this, SLOT(openRamFile()));
+
+ fileMenu->addSeparator();
+ QMenu *aspectMenu = fileMenu->addMenu(tr("&Aspect ratio"));
+ QActionGroup *aspectGroup = new QActionGroup(aspectMenu);
+ connect(aspectGroup, SIGNAL(triggered(QAction*)), this, SLOT(aspectChanged(QAction*)));
+ aspectGroup->setExclusive(true);
+ QAction *aspectActionAuto = aspectMenu->addAction(tr("Auto"));
+ aspectActionAuto->setCheckable(true);
+ aspectActionAuto->setChecked(true);
+ aspectGroup->addAction(aspectActionAuto);
+ QAction *aspectActionScale = aspectMenu->addAction(tr("Scale"));
+ aspectActionScale->setCheckable(true);
+ aspectGroup->addAction(aspectActionScale);
+ QAction *aspectAction16_9 = aspectMenu->addAction(tr("16/9"));
+ aspectAction16_9->setCheckable(true);
+ aspectGroup->addAction(aspectAction16_9);
+ QAction *aspectAction4_3 = aspectMenu->addAction(tr("4/3"));
+ aspectAction4_3->setCheckable(true);
+ aspectGroup->addAction(aspectAction4_3);
+
+ QMenu *scaleMenu = fileMenu->addMenu(tr("&Scale mode"));
+ QActionGroup *scaleGroup = new QActionGroup(scaleMenu);
+ connect(scaleGroup, SIGNAL(triggered(QAction*)), this, SLOT(scaleChanged(QAction*)));
+ scaleGroup->setExclusive(true);
+ QAction *scaleActionFit = scaleMenu->addAction(tr("Fit in view"));
+ scaleActionFit->setCheckable(true);
+ scaleActionFit->setChecked(true);
+ scaleGroup->addAction(scaleActionFit);
+ QAction *scaleActionCrop = scaleMenu->addAction(tr("Scale and crop"));
+ scaleActionCrop->setCheckable(true);
+ scaleGroup->addAction(scaleActionCrop);
+
+ m_fullScreenAction = fileMenu->addAction(tr("Full screen video"));
+ m_fullScreenAction->setCheckable(true);
+ m_fullScreenAction->setEnabled(false); // enabled by hasVideoChanged
+ bool b = connect(m_fullScreenAction, SIGNAL(toggled(bool)), m_videoWidget, SLOT(setFullScreen(bool)));
+ Q_ASSERT(b);
+ b = connect(m_videoWidget, SIGNAL(fullScreenChanged(bool)), m_fullScreenAction, SLOT(setChecked(bool)));
+ Q_ASSERT(b);
+
+ fileMenu->addSeparator();
+ QAction *settingsAction = fileMenu->addAction(tr("&Settings..."));
+
+ // Setup signal connections:
+ connect(rewindButton, SIGNAL(clicked()), this, SLOT(rewind()));
+ //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
+ openButton->setMenu(fileMenu);
+
+ connect(playButton, SIGNAL(clicked()), this, SLOT(playPause()));
+ connect(forwardButton, SIGNAL(clicked()), this, SLOT(forward()));
+ //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
+ connect(settingsAction, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog()));
+ connect(openUrlAction, SIGNAL(triggered(bool)), this, SLOT(openUrl()));
+ connect(openFileAction, SIGNAL(triggered(bool)), this, SLOT(openFile()));
+
+ connect(m_videoWidget, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &)));
+ connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &)));
+ connect(&m_MediaObject, SIGNAL(metaDataChanged()), this, SLOT(updateInfo()));
+ connect(&m_MediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(updateTime()));
+ connect(&m_MediaObject, SIGNAL(tick(qint64)), this, SLOT(updateTime()));
+ connect(&m_MediaObject, SIGNAL(finished()), this, SLOT(finished()));
+ connect(&m_MediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(stateChanged(Phonon::State,Phonon::State)));
+ connect(&m_MediaObject, SIGNAL(bufferStatus(int)), this, SLOT(bufferStatus(int)));
+ connect(&m_MediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasVideoChanged(bool)));
+
+ rewindButton->setEnabled(false);
+ playButton->setEnabled(false);
+ setAcceptDrops(true);
+
+ m_audioOutputPath = Phonon::createPath(&m_MediaObject, &m_AudioOutput);
+ Phonon::createPath(&m_MediaObject, m_videoWidget);
+
+ resize(minimumSizeHint());
+}
+
+void MediaPlayer::stateChanged(Phonon::State newstate, Phonon::State oldstate)
+{
+ Q_UNUSED(oldstate);
+
+ if (oldstate == Phonon::LoadingState) {
+ QRect videoHintRect = QRect(QPoint(0, 0), m_videoWindow.sizeHint());
+ QRect newVideoRect = QApplication::desktop()->screenGeometry().intersected(videoHintRect);
+ if (!m_smallScreen) {
+ if (m_MediaObject.hasVideo()) {
+ // Flush event que so that sizeHint takes the
+ // recently shown/hidden m_videoWindow into account:
+ qApp->processEvents();
+ resize(sizeHint());
+ } else
+ resize(minimumSize());
+ }
+ }
+
+ switch (newstate) {
+ case Phonon::ErrorState:
+ if (m_MediaObject.errorType() == Phonon::FatalError) {
+ playButton->setEnabled(false);
+ rewindButton->setEnabled(false);
+ } else {
+ m_MediaObject.pause();
+ }
+ QMessageBox::warning(this, "Phonon Mediaplayer", m_MediaObject.errorString(), QMessageBox::Close);
+ break;
+
+ case Phonon::StoppedState:
+ m_videoWidget->setFullScreen(false);
+ // Fall through
+ case Phonon::PausedState:
+ playButton->setIcon(playIcon);
+ if (m_MediaObject.currentSource().type() != Phonon::MediaSource::Invalid){
+ playButton->setEnabled(true);
+ rewindButton->setEnabled(true);
+ } else {
+ playButton->setEnabled(false);
+ rewindButton->setEnabled(false);
+ }
+ break;
+ case Phonon::PlayingState:
+ playButton->setEnabled(true);
+ playButton->setIcon(pauseIcon);
+ if (m_MediaObject.hasVideo())
+ m_videoWindow.show();
+ // Fall through
+ case Phonon::BufferingState:
+ rewindButton->setEnabled(true);
+ break;
+ case Phonon::LoadingState:
+ rewindButton->setEnabled(false);
+ break;
+ }
+
+}
+
+void MediaPlayer::initSettingsDialog()
+{
+ settingsDialog = new QDialog(this);
+ ui = new Ui_settings();
+ ui->setupUi(settingsDialog);
+
+ connect(ui->brightnessSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrightness(int)));
+ connect(ui->hueSlider, SIGNAL(valueChanged(int)), this, SLOT(setHue(int)));
+ connect(ui->saturationSlider, SIGNAL(valueChanged(int)), this, SLOT(setSaturation(int)));
+ connect(ui->contrastSlider , SIGNAL(valueChanged(int)), this, SLOT(setContrast(int)));
+ connect(ui->aspectCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setAspect(int)));
+ connect(ui->scalemodeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setScale(int)));
+
+ ui->brightnessSlider->setValue(int(m_videoWidget->brightness() * SLIDER_RANGE));
+ ui->hueSlider->setValue(int(m_videoWidget->hue() * SLIDER_RANGE));
+ ui->saturationSlider->setValue(int(m_videoWidget->saturation() * SLIDER_RANGE));
+ ui->contrastSlider->setValue(int(m_videoWidget->contrast() * SLIDER_RANGE));
+ ui->aspectCombo->setCurrentIndex(m_videoWidget->aspectRatio());
+ ui->scalemodeCombo->setCurrentIndex(m_videoWidget->scaleMode());
+ connect(ui->effectButton, SIGNAL(clicked()), this, SLOT(configureEffect()));
+
+#ifdef Q_WS_X11
+ //Cross fading is not currently implemented in the GStreamer backend
+ ui->crossFadeSlider->setVisible(false);
+ ui->crossFadeLabel->setVisible(false);
+ ui->crossFadeLabel1->setVisible(false);
+ ui->crossFadeLabel2->setVisible(false);
+ ui->crossFadeLabel3->setVisible(false);
+#endif
+ ui->crossFadeSlider->setValue((int)(2 * m_MediaObject.transitionTime() / 1000.0f));
+
+ // Insert audio devices:
+ QList<Phonon::AudioOutputDevice> devices = Phonon::BackendCapabilities::availableAudioOutputDevices();
+ for (int i=0; i<devices.size(); i++){
+ QString itemText = devices[i].name();
+ if (!devices[i].description().isEmpty()) {
+ itemText += QString::fromLatin1(" (%1)").arg(devices[i].description());
+ }
+ ui->deviceCombo->addItem(itemText);
+ if (devices[i] == m_AudioOutput.outputDevice())
+ ui->deviceCombo->setCurrentIndex(i);
+ }
+
+ // Insert audio effects:
+ ui->audioEffectsCombo->addItem(tr("<no effect>"));
+ QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
+ Phonon::Effect *currEffect = currEffects.size() ? currEffects[0] : 0;
+ QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
+ for (int i=0; i<availableEffects.size(); i++){
+ ui->audioEffectsCombo->addItem(availableEffects[i].name());
+ if (currEffect && availableEffects[i] == currEffect->description())
+ ui->audioEffectsCombo->setCurrentIndex(i+1);
+ }
+ connect(ui->audioEffectsCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(effectChanged()));
+
+}
+
+void MediaPlayer::setVolume(qreal volume)
+{
+ m_AudioOutput.setVolume(volume);
+}
+
+void MediaPlayer::setSmallScreen(bool smallScreen)
+{
+ m_smallScreen = smallScreen;
+}
+
+void MediaPlayer::effectChanged()
+{
+ int currentIndex = ui->audioEffectsCombo->currentIndex();
+ if (currentIndex) {
+ QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
+ Phonon::EffectDescription chosenEffect = availableEffects[currentIndex - 1];
+
+ QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
+ Phonon::Effect *currentEffect = currEffects.size() ? currEffects[0] : 0;
+
+ // Deleting the running effect will stop playback, it is deleted when removed from path
+ if (nextEffect && !(currentEffect && (currentEffect->description().name() == nextEffect->description().name())))
+ delete nextEffect;
+
+ nextEffect = new Phonon::Effect(chosenEffect);
+ }
+ ui->effectButton->setEnabled(currentIndex);
+}
+
+void MediaPlayer::showSettingsDialog()
+{
+ const bool hasPausedForDialog = playPauseForDialog();
+
+ if (!settingsDialog)
+ initSettingsDialog();
+
+ float oldBrightness = m_videoWidget->brightness();
+ float oldHue = m_videoWidget->hue();
+ float oldSaturation = m_videoWidget->saturation();
+ float oldContrast = m_videoWidget->contrast();
+ Phonon::VideoWidget::AspectRatio oldAspect = m_videoWidget->aspectRatio();
+ Phonon::VideoWidget::ScaleMode oldScale = m_videoWidget->scaleMode();
+ int currentEffect = ui->audioEffectsCombo->currentIndex();
+ settingsDialog->exec();
+
+ if (settingsDialog->result() == QDialog::Accepted){
+ m_MediaObject.setTransitionTime((int)(1000 * float(ui->crossFadeSlider->value()) / 2.0f));
+ QList<Phonon::AudioOutputDevice> devices = Phonon::BackendCapabilities::availableAudioOutputDevices();
+ m_AudioOutput.setOutputDevice(devices[ui->deviceCombo->currentIndex()]);
+ QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
+ QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
+
+ if (ui->audioEffectsCombo->currentIndex() > 0){
+ Phonon::Effect *currentEffect = currEffects.size() ? currEffects[0] : 0;
+ if (!currentEffect || currentEffect->description() != nextEffect->description()){
+ foreach(Phonon::Effect *effect, currEffects) {
+ m_audioOutputPath.removeEffect(effect);
+ delete effect;
+ }
+ m_audioOutputPath.insertEffect(nextEffect);
+ }
+ } else {
+ foreach(Phonon::Effect *effect, currEffects) {
+ m_audioOutputPath.removeEffect(effect);
+ delete effect;
+ nextEffect = 0;
+ }
+ }
+ } else {
+ // Restore previous settings
+ m_videoWidget->setBrightness(oldBrightness);
+ m_videoWidget->setSaturation(oldSaturation);
+ m_videoWidget->setHue(oldHue);
+ m_videoWidget->setContrast(oldContrast);
+ m_videoWidget->setAspectRatio(oldAspect);
+ m_videoWidget->setScaleMode(oldScale);
+ ui->audioEffectsCombo->setCurrentIndex(currentEffect);
+ }
+
+ if (hasPausedForDialog)
+ m_MediaObject.play();
+}
+
+void MediaPlayer::initVideoWindow()
+{
+ QVBoxLayout *videoLayout = new QVBoxLayout();
+ videoLayout->addWidget(m_videoWidget);
+ videoLayout->setContentsMargins(0, 0, 0, 0);
+ m_videoWindow.setLayout(videoLayout);
+ m_videoWindow.setMinimumSize(100, 100);
+}
+
+
+void MediaPlayer::configureEffect()
+{
+ if (!nextEffect)
+ return;
+
+
+ QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
+ const QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
+ if (ui->audioEffectsCombo->currentIndex() > 0) {
+ Phonon::EffectDescription chosenEffect = availableEffects[ui->audioEffectsCombo->currentIndex() - 1];
+
+ QDialog effectDialog;
+ effectDialog.setWindowTitle(tr("Configure effect"));
+ QVBoxLayout *topLayout = new QVBoxLayout(&effectDialog);
+
+ QLabel *description = new QLabel("<b>Description:</b><br>" + chosenEffect.description(), &effectDialog);
+ description->setWordWrap(true);
+ topLayout->addWidget(description);
+
+ QScrollArea *scrollArea = new QScrollArea(&effectDialog);
+ topLayout->addWidget(scrollArea);
+
+ QVariantList savedParamValues;
+ foreach(Phonon::EffectParameter param, nextEffect->parameters()) {
+ savedParamValues << nextEffect->parameterValue(param);
+ }
+
+ QWidget *scrollWidget = new Phonon::EffectWidget(nextEffect);
+ scrollWidget->setMinimumWidth(320);
+ scrollWidget->setContentsMargins(10, 10, 10,10);
+ scrollArea->setWidget(scrollWidget);
+
+ QDialogButtonBox *bbox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &effectDialog);
+ connect(bbox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), &effectDialog, SLOT(accept()));
+ connect(bbox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), &effectDialog, SLOT(reject()));
+ topLayout->addWidget(bbox);
+
+ effectDialog.exec();
+
+ if (effectDialog.result() != QDialog::Accepted) {
+ //we need to restore the parameters values
+ int currentIndex = 0;
+ foreach(Phonon::EffectParameter param, nextEffect->parameters()) {
+ nextEffect->setParameterValue(param, savedParamValues.at(currentIndex++));
+ }
+
+ }
+ }
+}
+
+void MediaPlayer::handleDrop(QDropEvent *e)
+{
+ QList<QUrl> urls = e->mimeData()->urls();
+ if (e->proposedAction() == Qt::MoveAction){
+ // Just add to the queue:
+ for (int i=0; i<urls.size(); i++)
+ m_MediaObject.enqueue(Phonon::MediaSource(urls[i].toLocalFile()));
+ } else {
+ // Create new queue:
+ m_MediaObject.clearQueue();
+ if (urls.size() > 0) {
+ QString fileName = urls[0].toLocalFile();
+ QDir dir(fileName);
+ if (dir.exists()) {
+ dir.setFilter(QDir::Files);
+ QStringList entries = dir.entryList();
+ if (entries.size() > 0) {
+ setFile(fileName + QDir::separator() + entries[0]);
+ for (int i=1; i< entries.size(); ++i)
+ m_MediaObject.enqueue(fileName + QDir::separator() + entries[i]);
+ }
+ } else {
+ setFile(fileName);
+ for (int i=1; i<urls.size(); i++)
+ m_MediaObject.enqueue(Phonon::MediaSource(urls[i].toLocalFile()));
+ }
+ }
+ }
+ forwardButton->setEnabled(m_MediaObject.queue().size() > 0);
+ m_MediaObject.play();
+}
+
+void MediaPlayer::dropEvent(QDropEvent *e)
+{
+ if (e->mimeData()->hasUrls() && e->proposedAction() != Qt::LinkAction) {
+ e->acceptProposedAction();
+ handleDrop(e);
+ } else {
+ e->ignore();
+ }
+}
+
+void MediaPlayer::dragEnterEvent(QDragEnterEvent *e)
+{
+ dragMoveEvent(e);
+}
+
+void MediaPlayer::dragMoveEvent(QDragMoveEvent *e)
+{
+ if (e->mimeData()->hasUrls()) {
+ if (e->proposedAction() == Qt::CopyAction || e->proposedAction() == Qt::MoveAction){
+ e->acceptProposedAction();
+ }
+ }
+}
+
+void MediaPlayer::playPause()
+{
+ if (m_MediaObject.state() == Phonon::PlayingState)
+ m_MediaObject.pause();
+ else {
+ if (m_MediaObject.currentTime() == m_MediaObject.totalTime())
+ m_MediaObject.seek(0);
+ m_MediaObject.play();
+ }
+}
+
+void MediaPlayer::setFile(const QString &fileName)
+{
+ setWindowTitle(fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1));
+ m_MediaObject.setCurrentSource(Phonon::MediaSource(fileName));
+ m_MediaObject.play();
+}
+
+void MediaPlayer::setLocation(const QString& location)
+{
+ setWindowTitle(location.right(location.length() - location.lastIndexOf('/') - 1));
+ m_MediaObject.setCurrentSource(Phonon::MediaSource(QUrl::fromEncoded(location.toUtf8())));
+ m_MediaObject.play();
+}
+
+bool MediaPlayer::playPauseForDialog()
+{
+ // If we're running on a small screen, we want to pause the video when
+ // popping up dialogs. We neither want to tamper with the state if the
+ // user has paused.
+ if (m_smallScreen && m_MediaObject.hasVideo()) {
+ if (Phonon::PlayingState == m_MediaObject.state()) {
+ m_MediaObject.pause();
+ return true;
+ }
+ }
+ return false;
+}
+
+void MediaPlayer::openFile()
+{
+ const bool hasPausedForDialog = playPauseForDialog();
+
+ QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(),
+ QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
+
+ if (hasPausedForDialog)
+ m_MediaObject.play();
+
+ m_MediaObject.clearQueue();
+ if (fileNames.size() > 0) {
+ QString fileName = fileNames[0];
+ setFile(fileName);
+ for (int i=1; i<fileNames.size(); i++)
+ m_MediaObject.enqueue(Phonon::MediaSource(fileNames[i]));
+ }
+ forwardButton->setEnabled(m_MediaObject.queue().size() > 0);
+}
+
+void MediaPlayer::bufferStatus(int percent)
+{
+ if (percent == 100)
+ progressLabel->setText(QString());
+ else {
+ QString str = QString::fromLatin1("(%1%)").arg(percent);
+ progressLabel->setText(str);
+ }
+}
+
+void MediaPlayer::setSaturation(int val)
+{
+ m_videoWidget->setSaturation(val / qreal(SLIDER_RANGE));
+}
+
+void MediaPlayer::setHue(int val)
+{
+ m_videoWidget->setHue(val / qreal(SLIDER_RANGE));
+}
+
+void MediaPlayer::setAspect(int val)
+{
+ m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatio(val));
+}
+
+void MediaPlayer::setScale(int val)
+{
+ m_videoWidget->setScaleMode(Phonon::VideoWidget::ScaleMode(val));
+}
+
+void MediaPlayer::setBrightness(int val)
+{
+ m_videoWidget->setBrightness(val / qreal(SLIDER_RANGE));
+}
+
+void MediaPlayer::setContrast(int val)
+{
+ m_videoWidget->setContrast(val / qreal(SLIDER_RANGE));
+}
+
+void MediaPlayer::updateInfo()
+{
+ int maxLength = 30;
+ QString font = "<font color=#ffeeaa>";
+ QString fontmono = "<font family=\"monospace,courier new\" color=#ffeeaa>";
+
+ QMap <QString, QString> metaData = m_MediaObject.metaData();
+ QString trackArtist = metaData.value("ARTIST");
+ if (trackArtist.length() > maxLength)
+ trackArtist = trackArtist.left(maxLength) + "...";
+
+ QString trackTitle = metaData.value("TITLE");
+ int trackBitrate = metaData.value("BITRATE").toInt();
+
+ QString fileName;
+ if (m_MediaObject.currentSource().type() == Phonon::MediaSource::Url) {
+ fileName = m_MediaObject.currentSource().url().toString();
+ } else {
+ fileName = m_MediaObject.currentSource().fileName();
+ fileName = fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1);
+ if (fileName.length() > maxLength)
+ fileName = fileName.left(maxLength) + "...";
+ }
+
+ QString title;
+ if (!trackTitle.isEmpty()) {
+ if (trackTitle.length() > maxLength)
+ trackTitle = trackTitle.left(maxLength) + "...";
+ title = "Title: " + font + trackTitle + "<br></font>";
+ } else if (!fileName.isEmpty()) {
+ if (fileName.length() > maxLength)
+ fileName = fileName.left(maxLength) + "...";
+ title = font + fileName + "</font>";
+ if (m_MediaObject.currentSource().type() == Phonon::MediaSource::Url) {
+ title.prepend("Url: ");
+ } else {
+ title.prepend("File: ");
+ }
+ }
+
+ QString artist;
+ if (!trackArtist.isEmpty())
+ artist = "Artist: " + font + trackArtist + "</font>";
+
+ QString bitrate;
+ if (trackBitrate != 0)
+ bitrate = "<br>Bitrate: " + font + QString::number(trackBitrate/1000) + "kbit</font>";
+
+ info->setText(title + artist + bitrate);
+}
+
+void MediaPlayer::updateTime()
+{
+ long len = m_MediaObject.totalTime();
+ long pos = m_MediaObject.currentTime();
+ QString timeString;
+ if (pos || len)
+ {
+ int sec = pos/1000;
+ int min = sec/60;
+ int hour = min/60;
+ int msec = pos;
+
+ QTime playTime(hour%60, min%60, sec%60, msec%1000);
+ sec = len / 1000;
+ min = sec / 60;
+ hour = min / 60;
+ msec = len;
+
+ QTime stopTime(hour%60, min%60, sec%60, msec%1000);
+ QString timeFormat = "m:ss";
+ if (hour > 0)
+ timeFormat = "h:mm:ss";
+ timeString = playTime.toString(timeFormat);
+ if (len)
+ timeString += " / " + stopTime.toString(timeFormat);
+ }
+ timeLabel->setText(timeString);
+}
+
+void MediaPlayer::rewind()
+{
+ m_MediaObject.seek(0);
+}
+
+void MediaPlayer::forward()
+{
+ QList<Phonon::MediaSource> queue = m_MediaObject.queue();
+ if (queue.size() > 0) {
+ m_MediaObject.setCurrentSource(queue[0]);
+ forwardButton->setEnabled(queue.size() > 1);
+ m_MediaObject.play();
+ }
+}
+
+void MediaPlayer::openUrl()
+{
+ QSettings settings;
+ settings.beginGroup(QLatin1String("BrowserMainWindow"));
+ QString sourceURL = settings.value("location").toString();
+ bool ok = false;
+ sourceURL = QInputDialog::getText(this, tr("Open Location"), tr("Please enter a valid address here:"), QLineEdit::Normal, sourceURL, &ok);
+ if (ok && !sourceURL.isEmpty()) {
+ setLocation(sourceURL);
+ settings.setValue("location", sourceURL);
+ }
+}
+
+/*!
+ \since 4.6
+ */
+void MediaPlayer::openRamFile()
+{
+ QSettings settings;
+ settings.beginGroup(QLatin1String("BrowserMainWindow"));
+
+ const QStringList fileNameList(QFileDialog::getOpenFileNames(this,
+ QString(),
+ settings.value("openRamFile").toString(),
+ QLatin1String("RAM files (*.ram)")));
+
+ if (fileNameList.isEmpty())
+ return;
+
+ QFile linkFile;
+ QList<QUrl> list;
+ QByteArray sourceURL;
+ for (int i = 0; i < fileNameList.count(); i++ ) {
+ linkFile.setFileName(fileNameList[i]);
+ if (linkFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ while (!linkFile.atEnd()) {
+ sourceURL = linkFile.readLine().trimmed();
+ if (!sourceURL.isEmpty()) {
+ const QUrl url(QUrl::fromEncoded(sourceURL));
+ if (url.isValid())
+ list.append(url);
+ }
+ }
+ linkFile.close();
+ }
+ }
+
+ if (!list.isEmpty()) {
+ m_MediaObject.clearQueue();
+ setLocation(list[0].toString());
+ for (int i = 1; i < list.count(); i++)
+ m_MediaObject.enqueue(Phonon::MediaSource(list[i]));
+ m_MediaObject.play();
+ }
+
+ forwardButton->setEnabled(!m_MediaObject.queue().isEmpty());
+ settings.setValue("openRamFile", fileNameList[0]);
+}
+
+void MediaPlayer::finished()
+{
+}
+
+void MediaPlayer::showContextMenu(const QPoint &p)
+{
+ fileMenu->popup(m_videoWidget->isFullScreen() ? p : mapToGlobal(p));
+}
+
+void MediaPlayer::scaleChanged(QAction *act)
+{
+ if (act->text() == tr("Scale and crop"))
+ m_videoWidget->setScaleMode(Phonon::VideoWidget::ScaleAndCrop);
+ else
+ m_videoWidget->setScaleMode(Phonon::VideoWidget::FitInView);
+}
+
+void MediaPlayer::aspectChanged(QAction *act)
+{
+ if (act->text() == tr("16/9"))
+ m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatio16_9);
+ else if (act->text() == tr("Scale"))
+ m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatioWidget);
+ else if (act->text() == tr("4/3"))
+ m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatio4_3);
+ else
+ m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatioAuto);
+}
+
+void MediaPlayer::hasVideoChanged(bool bHasVideo)
+{
+ info->setVisible(!bHasVideo);
+ m_videoWindow.setVisible(bHasVideo);
+ m_fullScreenAction->setEnabled(bHasVideo);
+}
+
+#ifdef Q_OS_SYMBIAN
+void MediaPlayer::selectIAP()
+{
+ TRAPD(err, selectIAPL());
+ if (KErrNone != err)
+ QMessageBox::warning(this, "Phonon Mediaplayer", "Error selecting IAP", QMessageBox::Close);
+}
+
+void MediaPlayer::selectIAPL()
+{
+ QVariant currentIAPValue = m_MediaObject.property("InternetAccessPointName");
+ QString currentIAPString = currentIAPValue.toString();
+ bool ok = false;
+ CCommsDatabase *commsDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(commsDb);
+ commsDb->ShowHiddenRecords();
+ CCommsDbTableView* view = commsDb->OpenTableLC(TPtrC(IAP));
+ QStringList items;
+ TInt currentIAP = 0;
+ for (TInt l = view->GotoFirstRecord(), i = 0; l != KErrNotFound; l = view->GotoNextRecord(), i++) {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
+ QString iapString = QString::fromUtf16(iapName.Ptr(), iapName.Length());
+ items << iapString;
+ if (iapString == currentIAPString)
+ currentIAP = i;
+ }
+ currentIAPString = QInputDialog::getItem(this, tr("Select Access Point"), tr("Select Access Point"), items, currentIAP, false, &ok);
+ if (ok)
+ m_MediaObject.setProperty("InternetAccessPointName", currentIAPString);
+ CleanupStack::PopAndDestroy(2); //commsDB, view
+}
+#endif
diff --git a/demos/qmediaplayer/mediaplayer.h b/demos/qmediaplayer/mediaplayer.h
new file mode 100644
index 0000000..7ddb7ae
--- /dev/null
+++ b/demos/qmediaplayer/mediaplayer.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** 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 demonstration applications 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 MEDIALAYER_H
+#define MEDIAPLAYER_H
+
+#include <QtGui/QWidget>
+#include <QtGui/QApplication>
+#include <QtCore/QTimerEvent>
+#include <QtGui/QShowEvent>
+#include <QtGui/QIcon>
+#include <QtCore/QBasicTimer>
+#include <QtGui/QAction>
+
+#include <phonon/audiooutput.h>
+#include <phonon/backendcapabilities.h>
+#include <phonon/effect.h>
+#include <phonon/effectparameter.h>
+#include <phonon/effectwidget.h>
+#include <phonon/mediaobject.h>
+#include <phonon/seekslider.h>
+#include <phonon/videowidget.h>
+#include <phonon/volumeslider.h>
+
+QT_BEGIN_NAMESPACE
+class QPushButton;
+class QLabel;
+class QSlider;
+class QTextEdit;
+class QMenu;
+class Ui_settings;
+QT_END_NAMESPACE
+
+class MediaPlayer;
+
+class MediaVideoWidget : public Phonon::VideoWidget
+{
+ Q_OBJECT
+
+public:
+ MediaVideoWidget(MediaPlayer *player, QWidget *parent = 0);
+
+public slots:
+ // Over-riding non-virtual Phonon::VideoWidget slot
+ void setFullScreen(bool);
+
+signals:
+ void fullScreenChanged(bool);
+
+protected:
+ void mouseDoubleClickEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ bool event(QEvent *e);
+ void timerEvent(QTimerEvent *e);
+ void dropEvent(QDropEvent *e);
+ void dragEnterEvent(QDragEnterEvent *e);
+
+private:
+ MediaPlayer *m_player;
+ QBasicTimer m_timer;
+ QAction m_action;
+};
+
+class MediaPlayer :
+ public QWidget
+{
+ Q_OBJECT
+public:
+ MediaPlayer();
+
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dragMoveEvent(QDragMoveEvent *e);
+ void dropEvent(QDropEvent *e);
+ void handleDrop(QDropEvent *e);
+ void setFile(const QString &text);
+ void setLocation(const QString &location);
+ void initVideoWindow();
+ void initSettingsDialog();
+ void setVolume(qreal volume);
+ void setSmallScreen(bool smallScreen);
+
+public slots:
+ void openFile();
+ void rewind();
+ void forward();
+ void updateInfo();
+ void updateTime();
+ void finished();
+ void playPause();
+ void scaleChanged(QAction *);
+ void aspectChanged(QAction *);
+
+private slots:
+ void setAspect(int);
+ void setScale(int);
+ void setSaturation(int);
+ void setContrast(int);
+ void setHue(int);
+ void setBrightness(int);
+ void stateChanged(Phonon::State newstate, Phonon::State oldstate);
+ void effectChanged();
+ void showSettingsDialog();
+ void showContextMenu(const QPoint& point);
+ void bufferStatus(int percent);
+ void openUrl();
+#ifdef Q_OS_SYMBIAN
+ void selectIAP();
+#endif
+ void openRamFile();
+ void configureEffect();
+ void hasVideoChanged(bool);
+
+private:
+ bool playPauseForDialog();
+#ifdef Q_OS_SYMBIAN
+ void selectIAPL();
+#endif
+
+ QIcon playIcon;
+ QIcon pauseIcon;
+ QMenu *fileMenu;
+ QPushButton *playButton;
+ QPushButton *rewindButton;
+ QPushButton *forwardButton;
+ Phonon::SeekSlider *slider;
+ QLabel *timeLabel;
+ QLabel *progressLabel;
+ Phonon::VolumeSlider *volume;
+ QSlider *m_hueSlider;
+ QSlider *m_satSlider;
+ QSlider *m_contSlider;
+ QLabel *info;
+ Phonon::Effect *nextEffect;
+ QDialog *settingsDialog;
+ Ui_settings *ui;
+ QAction *m_fullScreenAction;
+
+ QWidget m_videoWindow;
+ Phonon::MediaObject m_MediaObject;
+ Phonon::AudioOutput m_AudioOutput;
+ MediaVideoWidget *m_videoWidget;
+ Phonon::Path m_audioOutputPath;
+ bool m_smallScreen;
+};
+
+#endif //MEDIAPLAYER_H
diff --git a/demos/qmediaplayer/mediaplayer.qrc b/demos/qmediaplayer/mediaplayer.qrc
new file mode 100644
index 0000000..bcdf404
--- /dev/null
+++ b/demos/qmediaplayer/mediaplayer.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/screen.png</file>
+</qresource>
+</RCC>
diff --git a/demos/qmediaplayer/qmediaplayer.pro b/demos/qmediaplayer/qmediaplayer.pro
new file mode 100644
index 0000000..ba81026
--- /dev/null
+++ b/demos/qmediaplayer/qmediaplayer.pro
@@ -0,0 +1,39 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Thu Aug 23 18:02:14 2007
+######################################################################
+
+TEMPLATE = app
+DEPENDPATH += . build src ui
+
+QT += phonon
+
+FORMS += settings.ui
+RESOURCES += mediaplayer.qrc
+
+!win32:CONFIG += CONSOLE
+
+SOURCES += main.cpp mediaplayer.cpp
+HEADERS += mediaplayer.h
+
+target.path = $$[QT_INSTALL_DEMOS]/qtphonon/qmediaplayer
+sources.files = $$SOURCES $$HEADERS $$FORMS $$RESOURCES *.pro *.html *.doc images
+sources.path = $$[QT_INSTALL_DEMOS]/qtphonon/qmediaplayer
+INSTALLS += target sources
+
+wince*{
+DEPLOYMENT_PLUGIN += phonon_ds9 phonon_waveout
+}
+
+symbian {
+ TARGET.UID3 = 0xA000C613
+
+ addFiles.files = ../embedded/desktopservices/data/sax.mp3
+ addFiles.path = /data/sounds/
+ DEPLOYMENT += addFiles
+
+ include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+
+ LIBS += -lcommdb
+
+ TARGET.CAPABILITY="NetworkServices"
+}
diff --git a/demos/qmediaplayer/settings.ui b/demos/qmediaplayer/settings.ui
new file mode 100644
index 0000000..03bd70e
--- /dev/null
+++ b/demos/qmediaplayer/settings.ui
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>settings</class>
+ <widget class="QDialog" name="settings">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>175</width>
+ <height>397</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Settings</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Video options:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="5" column="2">
+ <widget class="QComboBox" name="scalemodeCombo">
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string>Fit in view</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Scale and crop</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Contrast:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2">
+ <widget class="QSlider" name="contrastSlider">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="minimum">
+ <number>-8</number>
+ </property>
+ <property name="maximum">
+ <number>8</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Brightness:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2">
+ <widget class="QSlider" name="brightnessSlider">
+ <property name="minimum">
+ <number>-8</number>
+ </property>
+ <property name="maximum">
+ <number>8</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Saturation:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="2">
+ <widget class="QSlider" name="saturationSlider">
+ <property name="minimum">
+ <number>-8</number>
+ </property>
+ <property name="maximum">
+ <number>8</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Hue:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="2">
+ <widget class="QSlider" name="hueSlider">
+ <property name="minimum">
+ <number>-8</number>
+ </property>
+ <property name="maximum">
+ <number>8</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ <property name="tickInterval">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>Aspect ratio:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QComboBox" name="aspectCombo">
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
+ </property>
+ <item>
+ <property name="text">
+ <string>Auto</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Stretch</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4/3</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>16/9</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>Scale Mode:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ <zorder>scalemodeCombo</zorder>
+ <zorder>label_9</zorder>
+ <zorder>contrastSlider</zorder>
+ <zorder>label_8</zorder>
+ <zorder>brightnessSlider</zorder>
+ <zorder>label_7</zorder>
+ <zorder>saturationSlider</zorder>
+ <zorder>label_2</zorder>
+ <zorder>hueSlider</zorder>
+ <zorder>label_10</zorder>
+ <zorder>aspectCombo</zorder>
+ <zorder>label_11</zorder>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Audio options:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>10</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Audio device:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="deviceCombo">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>10</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToMinimumContentsLength</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>10</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Audio effect:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="audioEffectsCombo">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>10</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToMinimumContentsLength</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="effectButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Setup</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLabel" name="crossFadeLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>10</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Cross fade:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QSlider" name="crossFadeSlider">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>-20</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ <property name="singleStep">
+ <number>1</number>
+ </property>
+ <property name="pageStep">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::TicksBelow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLabel" name="crossFadeLabel1">
+ <property name="font">
+ <font>
+ <pointsize>9</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>-10 Sec</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="crossFadeLabel2">
+ <property name="font">
+ <font>
+ <pointsize>9</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="crossFadeLabel3">
+ <property name="font">
+ <font>
+ <pointsize>9</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>10 Sec </string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>settings</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>settings</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/examples.pro b/examples/examples.pro
new file mode 100644
index 0000000..87e3161
--- /dev/null
+++ b/examples/examples.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += phonon
diff --git a/examples/phonon/README b/examples/phonon/README
new file mode 100644
index 0000000..51213cb
--- /dev/null
+++ b/examples/phonon/README
@@ -0,0 +1,39 @@
+Qt uses the Phonon cross-platform multimedia framework to play common
+multimedia formats.
+
+Applications can be written to take advantage of the native multimedia
+technologies on each platform via a consistent cross-platform Qt API.
+
+
+Some of the examples in this directory can be run from the example launcher;
+others can only be used from within Qt Designer.
+
+Documentation for these examples can be found via the "Tutorial and Examples"
+link in the main Qt documentation.
+
+Finding the Qt Examples and Demos launcher
+==========================================
+
+On Windows:
+
+The launcher can be accessed via the Windows Start menu. Select the menu
+entry entitled "Qt Examples and Demos" entry in the submenu containing
+the Qt tools.
+
+On Mac OS X:
+
+For the binary distribution, the qtdemo executable is installed in the
+/Developer/Applications/Qt directory. For the source distribution, it is
+installed alongside the other Qt tools on the path specified when Qt is
+configured.
+
+On Unix/Linux:
+
+The qtdemo executable is installed alongside the other Qt tools on the path
+specified when Qt is configured.
+
+On all platforms:
+
+The source code for the launcher can be found in the demos/qtdemo directory
+in the Qt package. This example is built at the same time as the Qt libraries,
+tools, examples, and demonstrations.
diff --git a/examples/phonon/capabilities/capabilities.pro b/examples/phonon/capabilities/capabilities.pro
new file mode 100644
index 0000000..d05e5ec
--- /dev/null
+++ b/examples/phonon/capabilities/capabilities.pro
@@ -0,0 +1,17 @@
+QT += phonon
+
+HEADERS += window.h
+SOURCES += window.cpp \
+ main.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/phonon/capabilities
+sources.files = $$SOURCES $$HEADERS capabilities.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/phonon/capabilities
+INSTALLS += target sources
+
+wince*{
+DEPLOYMENT_PLUGIN += phonon_ds9 phonon_waveout
+}
+
+symbian:TARGET.UID3 = 0xA000CF69
diff --git a/examples/phonon/capabilities/main.cpp b/examples/phonon/capabilities/main.cpp
new file mode 100644
index 0000000..94e9cbc
--- /dev/null
+++ b/examples/phonon/capabilities/main.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "window.h"
+
+//! [everything]
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Phonon Capabilities Example");
+
+ Window window;
+ window.show();
+
+ return app.exec();
+}
+//! [everything]
+
diff --git a/examples/phonon/capabilities/window.cpp b/examples/phonon/capabilities/window.cpp
new file mode 100644
index 0000000..39ecf86
--- /dev/null
+++ b/examples/phonon/capabilities/window.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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "window.h"
+
+//! [constructor]
+Window::Window()
+{
+ setupUi();
+ updateWidgets();
+
+ connect(Phonon::BackendCapabilities::notifier(),
+ SIGNAL(capabilitiesChanged()), this, SLOT(updateWidgets()));
+ connect(Phonon::BackendCapabilities::notifier(),
+ SIGNAL(availableAudioOutputDevicesChanged()), SLOT(updateWidgets()));
+}
+//! [constructor]
+
+//! [outputDevices]
+void Window::updateWidgets()
+{
+ devicesListView->setModel(new QStandardItemModel());
+ Phonon::ObjectDescriptionModel<Phonon::AudioOutputDeviceType> *model =
+ new Phonon::ObjectDescriptionModel<Phonon::AudioOutputDeviceType>();
+ model->setModelData(Phonon::BackendCapabilities::availableAudioOutputDevices());
+ devicesListView->setModel(model);
+//! [outputDevices]
+
+//! [mimeTypes]
+ mimeListWidget->clear();
+ QStringList mimeTypes =
+ Phonon::BackendCapabilities::availableMimeTypes();
+ foreach (QString mimeType, mimeTypes) {
+ QListWidgetItem *item = new QListWidgetItem(mimeListWidget);
+ item->setText(mimeType);
+ }
+//! [mimeTypes]
+
+//! [effects]
+ effectsTreeWidget->clear();
+ QList<Phonon::EffectDescription> effects =
+ Phonon::BackendCapabilities::availableAudioEffects();
+ foreach (Phonon::EffectDescription effect, effects) {
+ QTreeWidgetItem *item = new QTreeWidgetItem(effectsTreeWidget);
+ item->setText(0, tr("Effect"));
+ item->setText(1, effect.name());
+ item->setText(2, effect.description());
+//! [effects]
+
+//! [effectsParameters]
+ Phonon::Effect *instance = new Phonon::Effect(effect, this);
+ QList<Phonon::EffectParameter> parameters = instance->parameters();
+ for (int i = 0; i < parameters.size(); ++i) {
+ Phonon::EffectParameter parameter = parameters.at(i);
+
+ QVariant defaultValue = parameter.defaultValue();
+ QVariant minimumValue = parameter.minimumValue();
+ QVariant maximumValue = parameter.maximumValue();
+
+ QString valueString = QString("%1 / %2 / %3")
+ .arg(defaultValue.toString()).arg(minimumValue.toString())
+ .arg(maximumValue.toString());
+
+ QTreeWidgetItem *parameterItem = new QTreeWidgetItem(item);
+ parameterItem->setText(0, tr("Parameter"));
+ parameterItem->setText(1, parameter.name());
+ parameterItem->setText(2, parameter.description());
+ parameterItem->setText(3, QVariant::typeToName(parameter.type()));
+ parameterItem->setText(4, valueString);
+ }
+ }
+//! [effectsParameters]
+ for (int i = 0; i < effectsTreeWidget->columnCount(); ++i) {
+ if (i == 0)
+ effectsTreeWidget->setColumnWidth(0, 150);
+ else if (i == 2)
+ effectsTreeWidget->setColumnWidth(2, 350);
+ else
+ effectsTreeWidget->resizeColumnToContents(i);
+ }
+}
+
+void Window::setupUi()
+{
+ setupBackendBox();
+
+ QLayout *layout = new QVBoxLayout;
+ layout->addWidget(backendBox);
+
+ setLayout(layout);
+ setWindowTitle(tr("Backend Capabilities Example"));
+}
+
+void Window::setupBackendBox()
+{
+ backendBox = new QGroupBox(tr("Backend Capabilities"));
+
+ devicesLabel = new QLabel(tr("Available Audio Devices:"));
+ devicesListView = new QListView;
+
+ mimeTypesLabel = new QLabel(tr("Supported MIME Types:"));
+ mimeListWidget = new QListWidget;
+
+ effectsLabel = new QLabel(tr("Available Audio Effects:"));
+
+ QStringList headerLabels;
+ headerLabels << tr("Type") << tr("Name") << tr("Description") <<
+ tr("Value Type") << tr("Default/Min/Max Values");
+
+ effectsTreeWidget = new QTreeWidget;
+ effectsTreeWidget->setHeaderLabels(headerLabels);
+ effectsTreeWidget->setColumnCount(5);
+
+ QGridLayout *layout = new QGridLayout;
+ layout->addWidget(devicesLabel, 0, 0);
+ layout->addWidget(devicesListView, 1, 0);
+ layout->addWidget(mimeTypesLabel, 0, 1);
+ layout->addWidget(mimeListWidget, 1, 1);
+ layout->addWidget(effectsLabel, 2, 0);
+ layout->addWidget(effectsTreeWidget, 3, 0, 2, 2);
+ layout->setRowStretch(3, 100);
+
+ backendBox = new QGroupBox(tr("Backend Capabilities"));
+ backendBox->setLayout(layout);
+}
+
diff --git a/examples/phonon/capabilities/window.h b/examples/phonon/capabilities/window.h
new file mode 100644
index 0000000..ce4e7d3
--- /dev/null
+++ b/examples/phonon/capabilities/window.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <QWidget>
+
+#include <phonon/audiooutput.h>
+#include <phonon/seekslider.h>
+#include <phonon/mediaobject.h>
+#include <phonon/volumeslider.h>
+#include <phonon/backendcapabilities.h>
+#include <phonon/effect.h>
+#include <phonon/effectparameter.h>
+#include <phonon/objectdescriptionmodel.h>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+class QGroupBox;
+class QPushButton;
+class QLabel;
+class QListWidget;
+class QListView;
+class QTextEdit;
+class QTreeWidget;
+QT_END_NAMESPACE
+
+
+class Window : public QWidget
+{
+ Q_OBJECT
+
+public:
+ Window();
+
+//! [windowMembers]
+private slots:
+ void updateWidgets();
+
+private:
+ void setupUi();
+ void setupBackendBox();
+
+ QGroupBox *backendBox;
+
+ QLabel *devicesLabel;
+ QLabel *mimeTypesLabel;
+ QLabel *effectsLabel;
+
+ QListWidget *mimeListWidget;
+ QListView *devicesListView;
+ QTreeWidget *effectsTreeWidget;
+//! [windowMembers]
+};
+
+#endif
+
diff --git a/examples/phonon/phonon.pro b/examples/phonon/phonon.pro
new file mode 100644
index 0000000..c6a0bff
--- /dev/null
+++ b/examples/phonon/phonon.pro
@@ -0,0 +1,15 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS = qmusicplayer \
+ capabilities
+
+# Disable capabilities example for symbian-gcce due to a bug in elf2e32.
+symbian-gcce:SUBDIRS -= capabilities
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/phonon
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS phonon.pro README
+sources.path = $$[QT_INSTALL_EXAMPLES]/phonon
+INSTALLS += target sources
+
+symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri)
diff --git a/examples/phonon/qmusicplayer/main.cpp b/examples/phonon/qmusicplayer/main.cpp
new file mode 100644
index 0000000..708135f
--- /dev/null
+++ b/examples/phonon/qmusicplayer/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtGui>
+
+#include "mainwindow.h"
+
+//![1]
+int main(int argv, char **args)
+{
+ QApplication app(argv, args);
+ app.setApplicationName("Music Player");
+ app.setQuitOnLastWindowClosed(true);
+
+ MainWindow window;
+ window.show();
+
+ return app.exec();
+}
+//![1]
diff --git a/examples/phonon/qmusicplayer/mainwindow.cpp b/examples/phonon/qmusicplayer/mainwindow.cpp
new file mode 100644
index 0000000..b804a72
--- /dev/null
+++ b/examples/phonon/qmusicplayer/mainwindow.cpp
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+***************************************************************************/
+
+#include <QtGui>
+
+#include "mainwindow.h"
+
+//![0]
+MainWindow::MainWindow()
+{
+ audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
+ mediaObject = new Phonon::MediaObject(this);
+ metaInformationResolver = new Phonon::MediaObject(this);
+
+ mediaObject->setTickInterval(1000);
+//![0]
+//![2]
+ connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
+ connect(mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
+ this, SLOT(stateChanged(Phonon::State,Phonon::State)));
+ connect(metaInformationResolver, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
+ this, SLOT(metaStateChanged(Phonon::State,Phonon::State)));
+ connect(mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),
+ this, SLOT(sourceChanged(Phonon::MediaSource)));
+ connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
+//![2]
+
+//![1]
+ Phonon::createPath(mediaObject, audioOutput);
+//![1]
+
+ setupActions();
+ setupMenus();
+ setupUi();
+ timeLcd->display("00:00");
+}
+
+//![6]
+void MainWindow::addFiles()
+{
+ QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Music Files"),
+ QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
+
+ if (files.isEmpty())
+ return;
+
+ int index = sources.size();
+ foreach (QString string, files) {
+ Phonon::MediaSource source(string);
+
+ sources.append(source);
+ }
+ if (!sources.isEmpty())
+ metaInformationResolver->setCurrentSource(sources.at(index));
+
+}
+//![6]
+
+void MainWindow::about()
+{
+ QMessageBox::information(this, tr("About Music Player"),
+ tr("The Music Player example shows how to use Phonon - the multimedia"
+ " framework that comes with Qt - to create a simple music player."));
+}
+
+//![9]
+void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */)
+{
+ switch (newState) {
+ case Phonon::ErrorState:
+ if (mediaObject->errorType() == Phonon::FatalError) {
+ QMessageBox::warning(this, tr("Fatal Error"),
+ mediaObject->errorString());
+ } else {
+ QMessageBox::warning(this, tr("Error"),
+ mediaObject->errorString());
+ }
+ break;
+//![9]
+//![10]
+ case Phonon::PlayingState:
+ playAction->setEnabled(false);
+ pauseAction->setEnabled(true);
+ stopAction->setEnabled(true);
+ break;
+ case Phonon::StoppedState:
+ stopAction->setEnabled(false);
+ playAction->setEnabled(true);
+ pauseAction->setEnabled(false);
+ timeLcd->display("00:00");
+ break;
+ case Phonon::PausedState:
+ pauseAction->setEnabled(false);
+ stopAction->setEnabled(true);
+ playAction->setEnabled(true);
+ break;
+//![10]
+ case Phonon::BufferingState:
+ break;
+ default:
+ ;
+ }
+}
+
+//![11]
+void MainWindow::tick(qint64 time)
+{
+ QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60);
+
+ timeLcd->display(displayTime.toString("mm:ss"));
+}
+//![11]
+
+//![12]
+void MainWindow::tableClicked(int row, int /* column */)
+{
+ bool wasPlaying = mediaObject->state() == Phonon::PlayingState;
+
+ mediaObject->stop();
+ mediaObject->clearQueue();
+
+ if (row >= sources.size())
+ return;
+
+ mediaObject->setCurrentSource(sources[row]);
+
+ if (wasPlaying)
+ mediaObject->play();
+ else
+ mediaObject->stop();
+}
+//![12]
+
+//![13]
+void MainWindow::sourceChanged(const Phonon::MediaSource &source)
+{
+ musicTable->selectRow(sources.indexOf(source));
+ timeLcd->display("00:00");
+}
+//![13]
+
+//![14]
+void MainWindow::metaStateChanged(Phonon::State newState, Phonon::State /* oldState */)
+{
+ if (newState == Phonon::ErrorState) {
+ QMessageBox::warning(this, tr("Error opening files"),
+ metaInformationResolver->errorString());
+ while (!sources.isEmpty() &&
+ !(sources.takeLast() == metaInformationResolver->currentSource())) {} /* loop */;
+ return;
+ }
+
+ if (newState != Phonon::StoppedState && newState != Phonon::PausedState)
+ return;
+
+ if (metaInformationResolver->currentSource().type() == Phonon::MediaSource::Invalid)
+ return;
+
+ QMap<QString, QString> metaData = metaInformationResolver->metaData();
+
+ QString title = metaData.value("TITLE");
+ if (title == "")
+ title = metaInformationResolver->currentSource().fileName();
+
+ QTableWidgetItem *titleItem = new QTableWidgetItem(title);
+ titleItem->setFlags(titleItem->flags() ^ Qt::ItemIsEditable);
+ QTableWidgetItem *artistItem = new QTableWidgetItem(metaData.value("ARTIST"));
+ artistItem->setFlags(artistItem->flags() ^ Qt::ItemIsEditable);
+ QTableWidgetItem *albumItem = new QTableWidgetItem(metaData.value("ALBUM"));
+ albumItem->setFlags(albumItem->flags() ^ Qt::ItemIsEditable);
+ QTableWidgetItem *yearItem = new QTableWidgetItem(metaData.value("DATE"));
+ yearItem->setFlags(yearItem->flags() ^ Qt::ItemIsEditable);
+//![14]
+
+ int currentRow = musicTable->rowCount();
+ musicTable->insertRow(currentRow);
+ musicTable->setItem(currentRow, 0, titleItem);
+ musicTable->setItem(currentRow, 1, artistItem);
+ musicTable->setItem(currentRow, 2, albumItem);
+ musicTable->setItem(currentRow, 3, yearItem);
+
+//![15]
+ if (musicTable->selectedItems().isEmpty()) {
+ musicTable->selectRow(0);
+ mediaObject->setCurrentSource(metaInformationResolver->currentSource());
+ }
+
+ Phonon::MediaSource source = metaInformationResolver->currentSource();
+ int index = sources.indexOf(metaInformationResolver->currentSource()) + 1;
+ if (sources.size() > index) {
+ metaInformationResolver->setCurrentSource(sources.at(index));
+ }
+ else {
+ musicTable->resizeColumnsToContents();
+ if (musicTable->columnWidth(0) > 300)
+ musicTable->setColumnWidth(0, 300);
+ }
+}
+//![15]
+
+//![16]
+void MainWindow::aboutToFinish()
+{
+ int index = sources.indexOf(mediaObject->currentSource()) + 1;
+ if (sources.size() > index) {
+ mediaObject->enqueue(sources.at(index));
+ }
+}
+//![16]
+
+void MainWindow::setupActions()
+{
+ playAction = new QAction(style()->standardIcon(QStyle::SP_MediaPlay), tr("Play"), this);
+ playAction->setShortcut(tr("Ctrl+P"));
+ playAction->setDisabled(true);
+ pauseAction = new QAction(style()->standardIcon(QStyle::SP_MediaPause), tr("Pause"), this);
+ pauseAction->setShortcut(tr("Ctrl+A"));
+ pauseAction->setDisabled(true);
+ stopAction = new QAction(style()->standardIcon(QStyle::SP_MediaStop), tr("Stop"), this);
+ stopAction->setShortcut(tr("Ctrl+S"));
+ stopAction->setDisabled(true);
+ nextAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipForward), tr("Next"), this);
+ nextAction->setShortcut(tr("Ctrl+N"));
+ previousAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipBackward), tr("Previous"), this);
+ previousAction->setShortcut(tr("Ctrl+R"));
+ addFilesAction = new QAction(tr("Add &Files"), this);
+ addFilesAction->setShortcut(tr("Ctrl+F"));
+ exitAction = new QAction(tr("E&xit"), this);
+ exitAction->setShortcuts(QKeySequence::Quit);
+ aboutAction = new QAction(tr("A&bout"), this);
+ aboutAction->setShortcut(tr("Ctrl+B"));
+ aboutQtAction = new QAction(tr("About &Qt"), this);
+ aboutQtAction->setShortcut(tr("Ctrl+Q"));
+
+//![5]
+ connect(playAction, SIGNAL(triggered()), mediaObject, SLOT(play()));
+ connect(pauseAction, SIGNAL(triggered()), mediaObject, SLOT(pause()) );
+ connect(stopAction, SIGNAL(triggered()), mediaObject, SLOT(stop()));
+//![5]
+ connect(addFilesAction, SIGNAL(triggered()), this, SLOT(addFiles()));
+ connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
+ connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
+ connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+}
+
+void MainWindow::setupMenus()
+{
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ fileMenu->addAction(addFilesAction);
+ fileMenu->addSeparator();
+ fileMenu->addAction(exitAction);
+
+ QMenu *aboutMenu = menuBar()->addMenu(tr("&Help"));
+ aboutMenu->addAction(aboutAction);
+ aboutMenu->addAction(aboutQtAction);
+}
+
+//![3]
+void MainWindow::setupUi()
+{
+//![3]
+ QToolBar *bar = new QToolBar;
+
+ bar->addAction(playAction);
+ bar->addAction(pauseAction);
+ bar->addAction(stopAction);
+
+//![4]
+ seekSlider = new Phonon::SeekSlider(this);
+ seekSlider->setMediaObject(mediaObject);
+
+ volumeSlider = new Phonon::VolumeSlider(this);
+ volumeSlider->setAudioOutput(audioOutput);
+//![4]
+ volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+
+ QLabel *volumeLabel = new QLabel;
+ volumeLabel->setPixmap(QPixmap("images/volume.png"));
+
+ QPalette palette;
+ palette.setBrush(QPalette::Light, Qt::darkGray);
+
+ timeLcd = new QLCDNumber;
+ timeLcd->setPalette(palette);
+
+ QStringList headers;
+ headers << tr("Title") << tr("Artist") << tr("Album") << tr("Year");
+
+ musicTable = new QTableWidget(0, 4);
+ musicTable->setHorizontalHeaderLabels(headers);
+ musicTable->setSelectionMode(QAbstractItemView::SingleSelection);
+ musicTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ connect(musicTable, SIGNAL(cellPressed(int,int)),
+ this, SLOT(tableClicked(int,int)));
+
+ QHBoxLayout *seekerLayout = new QHBoxLayout;
+ seekerLayout->addWidget(seekSlider);
+ seekerLayout->addWidget(timeLcd);
+
+ QHBoxLayout *playbackLayout = new QHBoxLayout;
+ playbackLayout->addWidget(bar);
+ playbackLayout->addStretch();
+ playbackLayout->addWidget(volumeLabel);
+ playbackLayout->addWidget(volumeSlider);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(musicTable);
+ mainLayout->addLayout(seekerLayout);
+ mainLayout->addLayout(playbackLayout);
+
+ QWidget *widget = new QWidget;
+ widget->setLayout(mainLayout);
+
+ setCentralWidget(widget);
+ setWindowTitle("Phonon Music Player");
+}
+
diff --git a/examples/phonon/qmusicplayer/mainwindow.h b/examples/phonon/qmusicplayer/mainwindow.h
new file mode 100644
index 0000000..a96f0c0
--- /dev/null
+++ b/examples/phonon/qmusicplayer/mainwindow.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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 examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <phonon/audiooutput.h>
+#include <phonon/seekslider.h>
+#include <phonon/mediaobject.h>
+#include <phonon/volumeslider.h>
+#include <phonon/backendcapabilities.h>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+class QTableWidget;
+class QLCDNumber;
+QT_END_NAMESPACE
+
+//![0]
+
+class MainWindow : public QMainWindow
+{
+//![0]
+ Q_OBJECT
+
+public:
+ MainWindow();
+
+ QSize sizeHint() const {
+ return QSize(500, 300);
+ }
+
+private slots:
+ void addFiles();
+ void about();
+//![1]
+ void stateChanged(Phonon::State newState, Phonon::State oldState);
+ void tick(qint64 time);
+ void sourceChanged(const Phonon::MediaSource &source);
+ void metaStateChanged(Phonon::State newState, Phonon::State oldState);
+ void aboutToFinish();
+ void tableClicked(int row, int column);
+//![1]
+
+private:
+ void setupActions();
+ void setupMenus();
+ void setupUi();
+
+//![2]
+ Phonon::SeekSlider *seekSlider;
+ Phonon::MediaObject *mediaObject;
+ Phonon::MediaObject *metaInformationResolver;
+ Phonon::AudioOutput *audioOutput;
+ Phonon::VolumeSlider *volumeSlider;
+ QList<Phonon::MediaSource> sources;
+//![2]
+
+ QAction *playAction;
+ QAction *pauseAction;
+ QAction *stopAction;
+ QAction *nextAction;
+ QAction *previousAction;
+ QAction *addFilesAction;
+ QAction *exitAction;
+ QAction *aboutAction;
+ QAction *aboutQtAction;
+ QLCDNumber *timeLcd;
+ QTableWidget *musicTable;
+};
+
+#endif
diff --git a/examples/phonon/qmusicplayer/qmusicplayer.pro b/examples/phonon/qmusicplayer/qmusicplayer.pro
new file mode 100644
index 0000000..25ab7eb
--- /dev/null
+++ b/examples/phonon/qmusicplayer/qmusicplayer.pro
@@ -0,0 +1,17 @@
+QT += phonon
+
+HEADERS += mainwindow.h
+SOURCES += main.cpp \
+ mainwindow.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/phonon/qmusicplayer
+sources.files = $$SOURCES $$HEADERS $$FORMS $$RESOURCES *.pro *.png images
+sources.path = $$[QT_INSTALL_EXAMPLES]/phonon/qmusicplayer
+INSTALLS += target sources
+
+wince*{
+DEPLOYMENT_PLUGIN += phonon_ds9 phonon_waveout
+}
+
+symbian:TARGET.UID3 = 0xA000CF6A
diff --git a/src/3rdparty/phonon/CMakeLists.txt b/src/3rdparty/phonon/CMakeLists.txt
new file mode 100644
index 0000000..fd6368c
--- /dev/null
+++ b/src/3rdparty/phonon/CMakeLists.txt
@@ -0,0 +1,281 @@
+project(Phonon)
+
+cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
+
+# CMP0002: we have multiple targets with the same name for the unit tests
+cmake_policy(SET CMP0002 OLD)
+
+# enable unit tests
+option(PHONON_BUILD_TESTS "Build the tests")
+option(PHONON_BUILD_EXAMPLES "Build the examples")
+
+if (PHONON_BUILD_TESTS)
+ enable_testing()
+endif (PHONON_BUILD_TESTS)
+
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+include(PhononMacros)
+
+include(MacroLogFeature)
+include(MacroOptionalFindPackage)
+
+set(QT_MIN_VERSION 4.4.0)
+find_package(Qt4 REQUIRED)
+if (NOT QT_QTDBUS_FOUND)
+ message(STATUS "Warning: Phonon won't be compiled with DBus support.")
+endif(NOT QT_QTDBUS_FOUND)
+
+find_package(Automoc4 REQUIRED)
+include (CheckCXXCompilerFlag)
+include (MacroEnsureVersion)
+
+if (NOT AUTOMOC4_VERSION)
+ set(AUTOMOC4_VERSION "0.9.83")
+endif (NOT AUTOMOC4_VERSION)
+macro_ensure_version("0.9.86" "${AUTOMOC4_VERSION}" _automoc4_version_ok)
+if (NOT _automoc4_version_ok)
+ message(FATAL_ERROR "Your version of automoc4 is too old. You have ${AUTOMOC4_VERSION}, you need at least 0.9.86")
+endif (NOT _automoc4_version_ok)
+
+if (CMAKE_COMPILER_IS_GNUCXX)
+ set (KDE4_ENABLE_EXCEPTIONS -fexceptions)
+ # Select flags.
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
+ set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG -DQT_NO_DEBUG")
+ set(CMAKE_CXX_FLAGS_DEBUG "-g -O2 -fno-reorder-blocks -fno-schedule-insns -fno-inline")
+ set(CMAKE_CXX_FLAGS_DEBUGFULL "-g3 -fno-inline")
+ set(CMAKE_CXX_FLAGS_PROFILE "-g3 -fno-inline -ftest-coverage -fprofile-arcs")
+ set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
+ set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG -DQT_NO_DEBUG")
+ set(CMAKE_C_FLAGS_DEBUG "-g -O2 -fno-reorder-blocks -fno-schedule-insns -fno-inline")
+ set(CMAKE_C_FLAGS_DEBUGFULL "-g3 -fno-inline")
+ set(CMAKE_C_FLAGS_PROFILE "-g3 -fno-inline -ftest-coverage -fprofile-arcs")
+
+ if (CMAKE_SYSTEM_NAME MATCHES Linux)
+ set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-long-long -std=iso9899:1990 -Wundef -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute -fno-common")
+ set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-exceptions -fno-check-new -fno-common")
+ add_definitions (-D_BSD_SOURCE -DQT_NO_EXCEPTIONS)
+ endif (CMAKE_SYSTEM_NAME MATCHES Linux)
+
+ # gcc under Windows
+ if (MINGW)
+ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--export-all-symbols -Wl,--disable-auto-import")
+ set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--export-all-symbols -Wl,--disable-auto-import")
+
+ # we always link against the release version of QT with mingw
+ # (even for debug builds). So we need to define QT_NO_DEBUG
+ # or else QPluginLoader rejects plugins because it thinks
+ # they're built against the wrong QT.
+ add_definitions(-DQT_NO_DEBUG)
+ endif (MINGW)
+
+ if (QT_USE_FRAMEWORKS)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F${QT_LIBRARY_DIR}")
+ endif (QT_USE_FRAMEWORKS)
+
+ check_cxx_compiler_flag(-fPIE HAVE_FPIE_SUPPORT)
+ if(KDE4_ENABLE_FPIE)
+ if(HAVE_FPIE_SUPPORT)
+ set (KDE4_CXX_FPIE_FLAGS "-fPIE")
+ set (KDE4_PIE_LDFLAGS "-pie")
+ else(HAVE_FPIE_SUPPORT)
+ message(STATUS "Your compiler doesn't support PIE flag")
+ endif(HAVE_FPIE_SUPPORT)
+ endif(KDE4_ENABLE_FPIE)
+
+ check_cxx_compiler_flag(-Woverloaded-virtual __KDE_HAVE_W_OVERLOADED_VIRTUAL)
+ if(__KDE_HAVE_W_OVERLOADED_VIRTUAL)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual")
+ endif(__KDE_HAVE_W_OVERLOADED_VIRTUAL)
+
+ # visibility support
+ check_cxx_compiler_flag(-fvisibility=hidden __KDE_HAVE_GCC_VISIBILITY)
+ set( __KDE_HAVE_GCC_VISIBILITY ${__KDE_HAVE_GCC_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
+
+ # get the gcc version
+ exec_program(${CMAKE_C_COMPILER} ARGS ${CMAKE_C_COMPILER_ARG1} --version OUTPUT_VARIABLE _gcc_version_info)
+
+ string (REGEX MATCH "[345]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}")
+ # gcc on mac just reports: "gcc (GCC) 3.3 20030304 ..." without the patch level, handle this here:
+ if (NOT _gcc_version)
+ string (REGEX REPLACE ".*\\(GCC\\).* ([34]\\.[0-9]) .*" "\\1.0" _gcc_version "${_gcc_version_info}")
+ endif (NOT _gcc_version)
+
+ macro_ensure_version("4.1.0" "${_gcc_version}" GCC_IS_NEWER_THAN_4_1)
+ macro_ensure_version("4.2.0" "${_gcc_version}" GCC_IS_NEWER_THAN_4_2)
+ macro_ensure_version("4.3.0" "${_gcc_version}" GCC_IS_NEWER_THAN_4_3)
+
+ # save a little by making local statics not threadsafe
+ # ### do not enable it for older compilers, see
+ # ### http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31806
+ if (GCC_IS_NEWER_THAN_4_3)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics")
+ endif (GCC_IS_NEWER_THAN_4_3)
+
+ set(_GCC_COMPILED_WITH_BAD_ALLOCATOR FALSE)
+ if (GCC_IS_NEWER_THAN_4_1)
+ exec_program(${CMAKE_C_COMPILER} ARGS -v OUTPUT_VARIABLE _gcc_alloc_info)
+ string(REGEX MATCH "(--enable-libstdcxx-allocator=mt)" _GCC_COMPILED_WITH_BAD_ALLOCATOR "${_gcc_alloc_info}")
+ endif (GCC_IS_NEWER_THAN_4_1)
+
+ if (__KDE_HAVE_GCC_VISIBILITY AND GCC_IS_NEWER_THAN_4_1 AND NOT _GCC_COMPILED_WITH_BAD_ALLOCATOR AND NOT WIN32)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
+ set (KDE4_C_FLAGS "-fvisibility=hidden")
+ # check that Qt defines Q_DECL_EXPORT as __attribute__ ((visibility("default")))
+ # if it doesn't and KDE compiles with hidden default visibiltiy plugins will break
+ set(_source "#include <QtCore/QtGlobal>\n int main()\n {\n #ifdef QT_VISIBILITY_AVAILABLE \n return 0;\n #else \n return 1; \n #endif \n }\n")
+ set(_source_file ${CMAKE_BINARY_DIR}/CMakeTmp/check_qt_visibility.cpp)
+ file(WRITE "${_source_file}" "${_source}")
+ set(_include_dirs "-DINCLUDE_DIRECTORIES:STRING=${QT_INCLUDES}")
+
+ try_run(_run_result _compile_result ${CMAKE_BINARY_DIR} ${_source_file} CMAKE_FLAGS "${_include_dirs}")
+
+ if(NOT _compile_result)
+ message(FATAL_ERROR "Could not compile simple test program:\n ${_source}")
+ endif(NOT _compile_result)
+ if(_run_result)
+ message(FATAL_ERROR "Qt compiled without support for -fvisibility=hidden. This will break plugins and linking of some applications. Please fix your Qt installation.")
+ endif(_run_result)
+
+ if (GCC_IS_NEWER_THAN_4_2)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
+ endif (GCC_IS_NEWER_THAN_4_2)
+ else (__KDE_HAVE_GCC_VISIBILITY AND GCC_IS_NEWER_THAN_4_1 AND NOT _GCC_COMPILED_WITH_BAD_ALLOCATOR AND NOT WIN32)
+ set (__KDE_HAVE_GCC_VISIBILITY 0)
+ endif (__KDE_HAVE_GCC_VISIBILITY AND GCC_IS_NEWER_THAN_4_1 AND NOT _GCC_COMPILED_WITH_BAD_ALLOCATOR AND NOT WIN32)
+
+endif (CMAKE_COMPILER_IS_GNUCXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
+set(CMAKE_COLOR_MAKEFILE ON)
+
+set(PHONON_LIB_MAJOR_VERSION "4")
+set(PHONON_LIB_MINOR_VERSION "4")
+set(PHONON_LIB_PATCH_VERSION "0")
+set(PHONON_LIB_VERSION "${PHONON_LIB_MAJOR_VERSION}.4.0")
+set(PHONON_LIB_SOVERSION ${PHONON_LIB_MAJOR_VERSION})
+
+add_definitions(${QT_DEFINITIONS})
+remove_definitions(-DQT3_SUPPORT_WARNINGS -DQT3_SUPPORT)
+if(MSVC)
+ add_definitions( -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS )
+endif(MSVC)
+
+# for including config.h and for includes like <kparts/foo.h>
+include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/includes ${CMAKE_CURRENT_SOURCE_DIR}/phonon ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/phonon)
+
+macro(_SET_FANCY _var _value _comment)
+ if (KDESupport_SOURCE_DIR)
+ # when building inside kdesupport other subprojects write crap into our variables
+ set(${_var} "${_value}")
+ else (KDESupport_SOURCE_DIR)
+ if (NOT DEFINED ${_var})
+ set(${_var} "${_value}")
+ else (NOT DEFINED ${_var})
+ set(${_var} "${${_var}}" CACHE PATH "${_comment}")
+ endif (NOT DEFINED ${_var})
+ endif (KDESupport_SOURCE_DIR)
+endmacro(_SET_FANCY)
+
+set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
+
+if (WIN32)
+ _set_fancy(EXEC_INSTALL_PREFIX "." "Base directory for executables and libraries")
+else(WIN32)
+ _set_fancy(EXEC_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" "Base directory for executables and libraries")
+endif(WIN32)
+_set_fancy(SHARE_INSTALL_PREFIX "${EXEC_INSTALL_PREFIX}/share" "Base directory for files which go to share/")
+_set_fancy(INCLUDE_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/include" "The subdirectory to the header prefix")
+_set_fancy(BIN_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/bin" "The install dir for executables (default ${EXEC_INSTALL_PREFIX}/bin)")
+_set_fancy(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" "The subdirectory relative to the install prefix where libraries will be installed (default is ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX})")
+_set_fancy(PLUGIN_INSTALL_DIR "${LIB_INSTALL_DIR}/kde4" "The subdirectory relative to the install prefix where plugins will be installed (default is ${LIB_INSTALL_DIR}/kde4)")
+_set_fancy(ICON_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/icons" "The icon install dir (default ${SHARE_INSTALL_PREFIX}/share/icons/)")
+_set_fancy(SERVICES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/kde4/services" "The install dir for service (desktop, protocol, ...) files")
+_set_fancy(DBUS_INTERFACES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/dbus-1/interfaces" "The dbus interfaces install dir (default: ${SHARE_INSTALL_PREFIX}/dbus-1/interfaces)")
+_set_fancy(DBUS_SERVICES_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/dbus-1/services" "The dbus services install dir (default: ${SHARE_INSTALL_PREFIX}/dbus-1/services)")
+
+set(INSTALL_TARGETS_DEFAULT_ARGS RUNTIME DESTINATION "${BIN_INSTALL_DIR}"
+ LIBRARY DESTINATION "${LIB_INSTALL_DIR}"
+ ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" COMPONENT Devel )
+
+# on the Mac support an extra install directory for application bundles
+if(APPLE)
+ set(INSTALL_TARGETS_DEFAULT_ARGS ${INSTALL_TARGETS_DEFAULT_ARGS}
+ BUNDLE DESTINATION "${BUNDLE_INSTALL_DIR}" )
+ set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined dynamic_lookup")
+ set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -flat_namespace -undefined dynamic_lookup")
+endif(APPLE)
+
+if (CMAKE_SYSTEM_NAME MATCHES Linux)
+ if (CMAKE_COMPILER_IS_GNUCXX)
+ set ( CMAKE_SHARED_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_SHARED_LINKER_FLAGS}")
+ set ( CMAKE_MODULE_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_MODULE_LINKER_FLAGS}")
+
+ set ( CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-new-dtags ${CMAKE_SHARED_LINKER_FLAGS}")
+ set ( CMAKE_MODULE_LINKER_FLAGS "-Wl,--enable-new-dtags ${CMAKE_MODULE_LINKER_FLAGS}")
+ set ( CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-new-dtags ${CMAKE_EXE_LINKER_FLAGS}")
+
+ # we profile...
+ if(CMAKE_BUILD_TYPE_TOLOWER MATCHES profile)
+ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
+ set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
+ endif(CMAKE_BUILD_TYPE_TOLOWER MATCHES profile)
+ endif (CMAKE_COMPILER_IS_GNUCXX)
+ if (CMAKE_C_COMPILER MATCHES "icc")
+ set ( CMAKE_SHARED_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_SHARED_LINKER_FLAGS}")
+ set ( CMAKE_MODULE_LINKER_FLAGS "-Wl,--fatal-warnings -Wl,--no-undefined -lc ${CMAKE_MODULE_LINKER_FLAGS}")
+ endif (CMAKE_C_COMPILER MATCHES "icc")
+endif (CMAKE_SYSTEM_NAME MATCHES Linux)
+
+set(PHONON_LIBS phonon ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
+if(QT_QTDBUS_FOUND)
+ list(APPEND PHONON_LIBS phonon ${QT_QTDBUS_LIBRARY})
+endif(QT_QTDBUS_FOUND)
+
+set(EXECUTABLE_OUTPUT_PATH ${Phonon_BINARY_DIR}/bin)
+if (WIN32)
+ set(LIBRARY_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH})
+else (WIN32)
+ set(LIBRARY_OUTPUT_PATH ${Phonon_BINARY_DIR}/lib)
+endif (WIN32)
+
+if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER MATCHES "icc")
+ set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-check-new -fno-common")
+endif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER MATCHES "icc")
+
+# Set up RPATH handling, so the libs are found if they are installed to a non-standard location.
+# By default cmake builds the targets with full RPATH to everything in the build directory,
+# but then removes the RPATH when installing.
+# These two options below make it set the RPATH of the installed targets to all
+# RPATH directories outside the current CMAKE_BINARY_DIR and also the library
+# install directory. Alex
+set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+set(CMAKE_INSTALL_RPATH "${LIB_INSTALL_DIR}" )
+
+if(APPLE)
+ set(CMAKE_INSTALL_NAME_DIR ${LIB_INSTALL_DIR})
+endif(APPLE)
+
+
+add_subdirectory(phonon)
+add_subdirectory(includes)
+if (Q_WS_MAC AND BUILD_PHONON_QT7)
+ add_subdirectory(qt7)
+endif (Q_WS_MAC AND BUILD_PHONON_QT7)
+if (Q_WS_WIN)
+ add_subdirectory(ds9)
+endif (Q_WS_WIN)
+
+if (Q_WS_X11)
+ add_subdirectory(gstreamer)
+ add_subdirectory(xine)
+endif (Q_WS_X11)
+
+if(NOT WIN32) # pkgconfig file
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/phonon.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/phonon.pc @ONLY)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/phonon.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+endif(NOT WIN32)
+
+macro_display_feature_log()
diff --git a/src/3rdparty/phonon/COPYING.LIB b/src/3rdparty/phonon/COPYING.LIB
new file mode 100644
index 0000000..2d2d780
--- /dev/null
+++ b/src/3rdparty/phonon/COPYING.LIB
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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 library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/3rdparty/phonon/ds9/CMakeLists.txt b/src/3rdparty/phonon/ds9/CMakeLists.txt
new file mode 100644
index 0000000..7378b53
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/CMakeLists.txt
@@ -0,0 +1,54 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+#
+# This library 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, either version 2 or 3 of the License.
+#
+# This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+project(phonon-ds9)
+include(ConfigureChecks.cmake)
+
+if (BUILD_PHONON_DS9)
+ find_package(OPENGL REQUIRED)
+
+ include_directories($ENV{DXDSDK_DIR}/include $ENV{DXSDK_DIR})
+ set(phonon_ds9_SRCS
+ abstractvideorenderer.cpp
+ audiooutput.cpp
+ backend.cpp
+ backendnode.cpp
+ effect.cpp
+ fakesource.cpp
+ iodevicereader.cpp
+ mediagraph.cpp
+ mediaobject.cpp
+ videowidget.cpp
+ videorenderer_vmr9.cpp
+ videorenderer_soft.cpp
+ volumeeffect.cpp
+ qbasefilter.cpp
+ qpin.cpp
+ qasyncreader.cpp
+ qaudiocdreader.cpp
+ qmeminputpin.cpp
+ )
+
+ add_definitions(-DPHONON_MAKE_QT_ONLY_BACKEND -DUNICODE)
+ automoc4_add_library(phonon_ds9 MODULE ${phonon_ds9_SRCS})
+ set_target_properties(phonon_ds9 PROPERTIES PREFIX "")
+ target_link_libraries(phonon_ds9
+ ${PHONON_LIBS} ${QT_QTOPENGL_LIBRARY} ${OPENGL_gl_LIBRARY}
+ dxguid strmiids dmoguids msdmo ole32 oleaut32 uuid gdi32)
+ # 'MODULE' is treated as a LIBRARY
+ install(TARGETS phonon_ds9
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}/phonon_backend
+ LIBRARY DESTINATION ${BIN_INSTALL_DIR}/phonon_backend
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
+ install(FILES ds9.desktop DESTINATION ${SERVICES_INSTALL_DIR}/phononbackends)
+endif (BUILD_PHONON_DS9)
diff --git a/src/3rdparty/phonon/ds9/ConfigureChecks.cmake b/src/3rdparty/phonon/ds9/ConfigureChecks.cmake
new file mode 100644
index 0000000..c13056f
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/ConfigureChecks.cmake
@@ -0,0 +1,44 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+#
+# This library 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, either version 2 or 3 of the License.
+#
+# This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+# We must find:
+# $DXSDK_DIR/include/d3d9.h
+# $DXDSK_DIR/$LIB/dxguid.lib
+# vmr9.h
+# dshow.h
+# strmiids.lib
+# dmoguids.lib
+# msdmo.lib
+include(CheckCXXSourceCompiles)
+
+macro_push_required_vars()
+
+set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${CMAKE_INCLUDE_PATH} $ENV{DXSDK_DIR} $ENV{DXSDK_DIR}/include)
+set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dxguid strmiids dmoguids msdmo)
+
+CHECK_CXX_SOURCE_COMPILES(
+"#include <d3d9.h>
+#include <dshow.h>
+#include <strmif.h>
+#include <vmr9.h>
+
+int main() { }" BUILD_PHONON_DS9)
+
+macro_pop_required_vars()
+
+if (BUILD_PHONON_DS9)
+ message(STATUS "Found DirectShow 9 support: $ENV{DXSDK_DIR}")
+else (BUILD_PHONON_DS9)
+ message(STATUS "DirectShow 9 support NOT found")
+endif (BUILD_PHONON_DS9)
diff --git a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp
new file mode 100644
index 0000000..a9d0694
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp
@@ -0,0 +1,118 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "abstractvideorenderer.h"
+
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+
+ AbstractVideoRenderer::AbstractVideoRenderer() :
+ m_dstX(0), m_dstY(0), m_dstWidth(0), m_dstHeight(0),
+ m_active(false)
+ {
+ }
+
+ AbstractVideoRenderer::~AbstractVideoRenderer()
+ {
+ }
+
+ Filter AbstractVideoRenderer::getFilter() const
+ {
+ return m_filter;
+ }
+
+ QSize AbstractVideoRenderer::sizeHint() const
+ {
+ QSize s = videoSize();
+ if (s.isNull()) {
+ s = QSize(640, 480).boundedTo( QApplication::desktop()->availableGeometry().size() );
+ }
+ return s;
+ }
+
+ void AbstractVideoRenderer::setActive(bool b)
+ {
+ m_active = b;
+ }
+
+ bool AbstractVideoRenderer::isActive() const
+ {
+ return m_active;
+ }
+
+ void AbstractVideoRenderer::internalNotifyResize(const QSize &size, const QSize &videoSize,
+ Phonon::VideoWidget::AspectRatio aspectRatio, Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ //update the video rects
+ qreal ratio = -1.;
+ const int videoWidth = videoSize.width(),
+ videoHeight = videoSize.height();
+
+ switch(aspectRatio)
+ {
+ case Phonon::VideoWidget::AspectRatioAuto:
+ {
+ //preserve the aspect ratio of the video
+ ratio = qreal(videoWidth) / qreal(videoHeight);
+ }
+ break;
+ case Phonon::VideoWidget::AspectRatio4_3:
+ ratio = qreal(4. / 3.);
+ break;
+ case Phonon::VideoWidget::AspectRatio16_9:
+ ratio = qreal(16. / 9.);
+ break;
+ case Phonon::VideoWidget::AspectRatioWidget:
+ default:
+ break;
+ }
+
+ const qreal realWidth = size.width(),
+ realHeight = size.height();
+
+ //reinitialization
+ m_dstWidth = size.width();
+ m_dstHeight = size.height();
+ m_dstX = m_dstY = 0;
+
+ if (ratio > 0) {
+ if ((realWidth / realHeight > ratio && scaleMode == Phonon::VideoWidget::FitInView)
+ || (realWidth / realHeight < ratio && scaleMode == Phonon::VideoWidget::ScaleAndCrop)) {
+ //the height is correct, let's change the width
+ m_dstWidth = qRound(realHeight * ratio);
+ m_dstX = qRound((realWidth - realHeight * ratio) / 2.);
+ } else {
+ m_dstHeight = qRound(realWidth / ratio);
+ m_dstY = qRound((realHeight - realWidth / ratio) / 2.);
+ }
+ }
+ }
+ }
+}
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/abstractvideorenderer.h b/src/3rdparty/phonon/ds9/abstractvideorenderer.h
new file mode 100644
index 0000000..25c660f
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/abstractvideorenderer.h
@@ -0,0 +1,73 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef PHONON_ABSTRACTVIDEORENDERER_H
+#define PHONON_ABSTRACTVIDEORENDERER_H
+
+#include "backendnode.h"
+
+#include <phonon/videowidget.h>
+
+QT_BEGIN_NAMESPACE
+
+class QImage;
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ //this is the interface used by the videorenderer from the VideoWidget class
+ class AbstractVideoRenderer
+ {
+ public:
+ virtual ~AbstractVideoRenderer();
+
+ virtual void repaintCurrentFrame(QWidget *target, const QRect &rect) = 0;
+ virtual void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode) = 0;
+ virtual void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation) = 0;
+
+ void setActive(bool);
+ bool isActive() const;
+
+ virtual bool isNative() const = 0;
+ virtual QImage snapshot() const = 0;
+
+ Filter getFilter() const;
+ QSize sizeHint() const;
+
+ protected:
+ virtual QSize videoSize() const = 0;
+
+ AbstractVideoRenderer();
+ void internalNotifyResize(const QSize &size, const QSize &videoSize,
+ Phonon::VideoWidget::AspectRatio aspectRatio, Phonon::VideoWidget::ScaleMode scaleMode);
+
+
+ Filter m_filter;
+ int m_dstX, m_dstY, m_dstWidth, m_dstHeight;
+ bool m_active;
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_VIDEO
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/audiooutput.cpp b/src/3rdparty/phonon/ds9/audiooutput.cpp
new file mode 100644
index 0000000..fcc062c
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/audiooutput.cpp
@@ -0,0 +1,111 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiooutput.h"
+#include "mediaobject.h"
+
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ AudioOutput::AudioOutput(Backend *back, QObject *parent)
+ : BackendNode(parent), m_currentIndex(0), m_crossfadeProgress(1.),
+ m_device(-1), m_backend(back), m_volume(0.)
+ {
+ }
+
+ AudioOutput::~AudioOutput()
+ {
+ }
+
+ int AudioOutput::outputDevice() const
+ {
+ return m_device;
+ }
+
+ static const qreal log10over20 = qreal(0.1151292546497022842); // ln(10) / 20
+
+ void AudioOutput::setVolume(qreal newVolume)
+ {
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ ComPointer<IBasicAudio> audio(m_filters[i], IID_IBasicAudio);
+ if (audio) {
+ const qreal currentVolume = newVolume * (m_currentIndex == i ? m_crossfadeProgress : 1-m_crossfadeProgress);
+ const qreal newDbVolume = (qMax(0., 1.-::log(::pow(currentVolume, -log10over20)))-1.) * 10000;
+ audio->put_Volume(qRound(newDbVolume));
+ }
+ }
+
+ if (m_volume != newVolume) {
+ m_volume = newVolume;
+ emit volumeChanged(newVolume);
+ }
+ }
+
+ void AudioOutput::setCrossFadingProgress(short currentIndex, qreal progress)
+ {
+ m_crossfadeProgress = progress;
+ m_currentIndex = currentIndex;
+ setVolume(m_volume);
+ }
+
+ bool AudioOutput::setOutputDevice(const AudioOutputDevice & newDevice)
+ {
+ //stub implementation
+ return setOutputDevice(newDevice.index());
+ }
+
+ qreal AudioOutput::volume() const
+ {
+ return m_volume;
+ }
+
+ bool AudioOutput::setOutputDevice(int newDevice)
+ {
+ if (newDevice == m_device) {
+ return true;
+ }
+
+ //free the previous one if it was already set
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ const Filter &oldFilter = m_filters[i];
+
+ Filter newFilter = m_backend->getAudioOutputFilter(newDevice);
+
+ if (m_mediaObject && oldFilter && newFilter) {
+ m_mediaObject->switchFilters(i, oldFilter, newFilter);
+ }
+
+ m_filters[i] = newFilter;
+
+
+ }
+
+ m_device = newDevice;
+ setVolume(m_volume);
+ return true;
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_audiooutput.cpp"
diff --git a/src/3rdparty/phonon/ds9/audiooutput.h b/src/3rdparty/phonon/ds9/audiooutput.h
new file mode 100644
index 0000000..c3bfc8b
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/audiooutput.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_AUDIOOUTPUT_H
+#define PHONON_AUDIOOUTPUT_H
+
+#include "backendnode.h"
+#include <phonon/audiooutputinterface.h>
+
+#include "backend.h"
+
+struct IBaseFilter;
+struct IBasicAudio;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class AudioOutput : public BackendNode, public Phonon::AudioOutputInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioOutputInterface)
+ public:
+ AudioOutput(Backend *back, QObject *parent);
+ ~AudioOutput();
+
+ // Attributes Getters:
+ qreal volume() const;
+ int outputDevice() const;
+ void setVolume(qreal newVolume);
+ bool setOutputDevice(int newDevice);
+ bool setOutputDevice(const AudioOutputDevice & newDevice);
+ void setCrossFadingProgress(short currentIndex, qreal progress);
+
+ Q_SIGNALS:
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+
+ private:
+ short m_currentIndex;
+ qreal m_crossfadeProgress;
+
+ int m_device;
+ Backend *m_backend;
+ qreal m_volume;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_AUDIOOUTPUT_H
diff --git a/src/3rdparty/phonon/ds9/backend.cpp b/src/3rdparty/phonon/ds9/backend.cpp
new file mode 100644
index 0000000..fbc4bdc
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/backend.cpp
@@ -0,0 +1,351 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backend.h"
+#include "backendnode.h"
+
+#include "audiooutput.h"
+#include "effect.h"
+#include "mediaobject.h"
+#include "videowidget.h"
+#include "volumeeffect.h"
+
+//windows specific (DirectX Media Object)
+#include <dmo.h>
+
+#include <QtCore/QSettings>
+#include <QtCore/QSet>
+#include <QtCore/QVariant>
+
+#include <QtCore/QtPlugin>
+
+QT_BEGIN_NAMESPACE
+
+Q_EXPORT_PLUGIN2(phonon_ds9, Phonon::DS9::Backend);
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ QMutex *Backend::directShowMutex = 0;
+
+ bool Backend::AudioMoniker::operator==(const AudioMoniker &other)
+ {
+ return other->IsEqual(*this) == S_OK;
+ }
+
+
+ Backend::Backend(QObject *parent, const QVariantList &)
+ : QObject(parent)
+ {
+ directShowMutex = &m_directShowMutex;
+
+ ::CoInitialize(0);
+
+ //registering meta types
+ qRegisterMetaType<HRESULT>("HRESULT");
+ qRegisterMetaType<Graph>("Graph");
+ }
+
+ Backend::~Backend()
+ {
+ m_audioOutputs.clear();
+ m_audioEffects.clear();
+ ::CoUninitialize();
+
+ directShowMutex = 0;
+ }
+
+ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+ {
+ switch (c)
+ {
+ case MediaObjectClass:
+ return new MediaObject(parent);
+ case AudioOutputClass:
+ return new AudioOutput(this, parent);
+#ifndef QT_NO_PHONON_EFFECT
+ case EffectClass:
+ return new Effect(m_audioEffects[ args[0].toInt() ], parent);
+#endif //QT_NO_PHONON_EFFECT
+#ifndef QT_NO_PHONON_VIDEO
+ case VideoWidgetClass:
+ return new VideoWidget(qobject_cast<QWidget *>(parent));
+#endif //QT_NO_PHONON_VIDEO
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+ case VolumeFaderEffectClass:
+ return new VolumeEffect(parent);
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+ default:
+ return 0;
+ }
+ }
+
+ bool Backend::supportsVideo() const
+ {
+#ifndef QT_NO_PHONON_VIDEO
+ return true;
+#else
+ return false;
+#endif //QT_NO_PHONON_VIDEO
+ }
+
+ QStringList Backend::availableMimeTypes() const
+ {
+ QStringList ret;
+ {
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Multimedia\\mplayer2\\mime types"), QSettings::NativeFormat);
+ ret += settings.childGroups();
+ }
+ {
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Multimedia\\wmplayer\\mime types"), QSettings::NativeFormat);
+ ret += settings.childGroups();
+ }
+
+ ret.removeDuplicates();
+ ret.replaceInStrings("\\", "/");
+ qSort(ret);
+ return ret;
+ }
+
+ Filter Backend::getAudioOutputFilter(int index) const
+ {
+ Filter ret;
+ if (index >= 0 && index < m_audioOutputs.count()) {
+ m_audioOutputs.at(index)->BindToObject(0, 0, IID_IBaseFilter, reinterpret_cast<void**>(&ret));
+ } else {
+ //just return the default audio renderer (not directsound)
+ ret = Filter(CLSID_AudioRender, IID_IBaseFilter);
+ }
+ return ret;
+ }
+
+
+ QList<int> Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const
+ {
+ QMutexLocker locker(&m_directShowMutex);
+ QList<int> ret;
+
+ switch(type)
+ {
+ case Phonon::AudioOutputDeviceType:
+ {
+#ifdef Q_OS_WINCE
+ ret << 0; // only one audio device with index 0
+#else
+ ComPointer<ICreateDevEnum> devEnum(CLSID_SystemDeviceEnum, IID_ICreateDevEnum);
+ if (!devEnum) {
+ return ret; //it is impossible to enumerate the devices
+ }
+ ComPointer<IEnumMoniker> enumMon;
+ HRESULT hr = devEnum->CreateClassEnumerator(CLSID_AudioRendererCategory, enumMon.pparam(), 0);
+ if (FAILED(hr)) {
+ break;
+ }
+ AudioMoniker mon;
+
+ //let's reorder the devices so that directshound appears first
+ int nbds = 0; //number of directsound devices
+
+ while (S_OK == enumMon->Next(1, mon.pparam(), 0)) {
+ LPOLESTR str = 0;
+ mon->GetDisplayName(0,0,&str);
+ const QString name = QString::fromWCharArray(str);
+ ComPointer<IMalloc> alloc;
+ ::CoGetMalloc(1, alloc.pparam());
+ alloc->Free(str);
+
+ int insert_pos = 0;
+ if (!m_audioOutputs.contains(mon)) {
+ insert_pos = m_audioOutputs.count();
+ m_audioOutputs.append(mon);
+ } else {
+ insert_pos = m_audioOutputs.indexOf(mon);
+ }
+
+ if (name.contains(QLatin1String("DirectSound"))) {
+ ret.insert(nbds++, insert_pos);
+ } else {
+ ret.append(insert_pos);
+ }
+ }
+#endif
+ break;
+ }
+#ifndef QT_NO_PHONON_EFFECT
+ case Phonon::EffectType:
+ {
+ m_audioEffects.clear();
+ ComPointer<IEnumDMO> enumDMO;
+ HRESULT hr = ::DMOEnum(DMOCATEGORY_AUDIO_EFFECT, DMO_ENUMF_INCLUDE_KEYED, 0, 0, 0, 0, enumDMO.pparam());
+ if (SUCCEEDED(hr)) {
+ CLSID clsid;
+ while (S_OK == enumDMO->Next(1, &clsid, 0, 0)) {
+ ret += m_audioEffects.count();
+ m_audioEffects.append(clsid);
+ }
+ }
+ break;
+ }
+ break;
+#endif //QT_NO_PHONON_EFFECT
+ default:
+ break;
+ }
+ return ret;
+ }
+
+ QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const
+ {
+ QMutexLocker locker(&m_directShowMutex);
+ QHash<QByteArray, QVariant> ret;
+ switch (type)
+ {
+ case Phonon::AudioOutputDeviceType:
+ {
+#ifdef Q_OS_WINCE
+ ret["name"] = QLatin1String("default audio device");
+#else
+ const AudioMoniker &mon = m_audioOutputs[index];
+ LPOLESTR str = 0;
+ HRESULT hr = mon->GetDisplayName(0,0, &str);
+ if (SUCCEEDED(hr)) {
+ QString name = QString::fromWCharArray(str);
+ ComPointer<IMalloc> alloc;
+ ::CoGetMalloc(1, alloc.pparam());
+ alloc->Free(str);
+ ret["name"] = name.mid(name.indexOf('\\') + 1);
+ }
+#endif
+ }
+ break;
+#ifndef QT_NO_PHONON_EFFECT
+ case Phonon::EffectType:
+ {
+ WCHAR name[80]; // 80 is clearly stated in the MSDN doc
+ HRESULT hr = ::DMOGetName(m_audioEffects[index], name);
+ if (SUCCEEDED(hr)) {
+ ret["name"] = QString::fromWCharArray(name);
+ }
+ }
+ break;
+#endif //QT_NO_PHONON_EFFECT
+ default:
+ break;
+ }
+ return ret;
+ }
+
+ bool Backend::endConnectionChange(QSet<QObject *> objects)
+ {
+ //end of a transaction
+ for(QSet<QObject *>::const_iterator it = objects.begin(); it != objects.end(); ++it) {
+ if (BackendNode *node = qobject_cast<BackendNode*>(*it)) {
+ MediaObject *mo = node->mediaObject();
+ if (mo) {
+ switch(mo->transactionState)
+ {
+ case Phonon::ErrorState:
+ case Phonon::StoppedState:
+ case Phonon::LoadingState:
+ //nothing to do
+ break;
+ case Phonon::PausedState:
+ mo->transactionState = Phonon::StoppedState;
+ mo->pause();
+ break;
+ default:
+ mo->transactionState = Phonon::StoppedState;
+ mo->play();
+ break;
+ }
+
+ if (mo->state() == Phonon::ErrorState)
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
+ bool Backend::startConnectionChange(QSet<QObject *> objects)
+ {
+ //let's save the state of the graph (before we stop it)
+ for(QSet<QObject *>::const_iterator it = objects.begin(); it != objects.end(); ++it) {
+ if (BackendNode *node = qobject_cast<BackendNode*>(*it)) {
+ if (MediaObject *mo = node->mediaObject()) {
+ if (mo->state() != Phonon::StoppedState) {
+ mo->transactionState = mo->state();
+ mo->ensureStopped(); //we have to stop the graph..
+ if (mo->state() == Phonon::ErrorState)
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ bool Backend::connectNodes(QObject *_source, QObject *_sink)
+ {
+ BackendNode *source = qobject_cast<BackendNode*>(_source);
+ if (!source) {
+ return false;
+ }
+ BackendNode *sink = qobject_cast<BackendNode*>(_sink);
+ if (!sink) {
+ return false;
+ }
+
+ //setting the graph if needed
+ if (source->mediaObject() == 0 && sink->mediaObject() == 0) {
+ //error: no graph selected
+ return false;
+ } else if (source->mediaObject() && source->mediaObject() != sink->mediaObject()) {
+ //this' graph becomes the common one
+ source->mediaObject()->grabNode(sink);
+ } else if (source->mediaObject() == 0) {
+ //sink's graph becomes the common one
+ sink->mediaObject()->grabNode(source);
+ }
+
+ return source->mediaObject()->connectNodes(source, sink);
+ }
+
+ bool Backend::disconnectNodes(QObject *_source, QObject *_sink)
+ {
+ BackendNode *source = qobject_cast<BackendNode*>(_source);
+ if (!source) {
+ return false;
+ }
+ BackendNode *sink = qobject_cast<BackendNode*>(_sink);
+ if (!sink) {
+ return false;
+ }
+
+ return source->mediaObject() == 0 ||
+ source->mediaObject()->disconnectNodes(source, sink);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_backend.cpp"
diff --git a/src/3rdparty/phonon/ds9/backend.h b/src/3rdparty/phonon/ds9/backend.h
new file mode 100644
index 0000000..7c3c109
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/backend.h
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_BACKEND_H
+#define PHONON_BACKEND_H
+
+#include "phononds9_namespace.h"
+#include <phonon/backendinterface.h>
+#include <phonon/phononnamespace.h>
+
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+
+#include "compointer.h"
+#include "backendnode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class AudioOutput;
+ class MediaObject;
+
+ typedef Phonon::ObjectDescriptionType ObjectDescriptionType;
+
+ class Backend : public QObject, public Phonon::BackendInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::BackendInterface)
+ public:
+ Backend(QObject *parent = 0, const QVariantList & = QVariantList());
+ virtual ~Backend();
+
+ QObject *createObject(Phonon::BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
+
+ bool supportsVideo() const;
+ QStringList availableMimeTypes() const;
+
+ QList<int> objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const;
+
+ bool connectNodes(QObject *, QObject *);
+ bool disconnectNodes(QObject *, QObject *);
+
+ //transaction management
+ bool startConnectionChange(QSet<QObject *>);
+ bool endConnectionChange(QSet<QObject *>);
+
+ Filter getAudioOutputFilter(int index) const;
+
+ static QMutex *directShowMutex;
+
+ Q_SIGNALS:
+ void objectDescriptionChanged(ObjectDescriptionType);
+
+ private:
+ class AudioMoniker : public ComPointer<IMoniker>
+ {
+ public:
+ bool operator==(const AudioMoniker &other);
+ };
+ mutable QVector<AudioMoniker> m_audioOutputs;
+ mutable QVector<CLSID> m_audioEffects;
+ mutable QMutex m_directShowMutex;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_BACKEND_H
diff --git a/src/3rdparty/phonon/ds9/backendnode.cpp b/src/3rdparty/phonon/ds9/backendnode.cpp
new file mode 100644
index 0000000..737ab7b
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/backendnode.cpp
@@ -0,0 +1,134 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backendnode.h"
+#include "mediaobject.h"
+
+#include <ocidl.h> // ISpecifyPropertyPages
+#include <olectl.h> // OleCreatePropertyFrame
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ // Displays a property dialog for a filter (experimental but should be put into main
+ /*static void showPropertyDialog(const Filter &filter)
+ {
+ ComPointer<ISpecifyPropertyPages> prop(filter, IID_ISpecifyPropertyPages);
+ if (prop != 0) {
+ IUnknown *iunk[] = {filter};
+ // Show the page.
+ CAUUID caGUID;
+ prop->GetPages(&caGUID);
+ OleCreatePropertyFrame(
+ 0, // Parent window
+ 0, 0, // (Reserved)
+ 0, // Caption for the dialog box
+ 1, // Number of objects (just the filter)
+ iunk, // Array of object pointers.
+ caGUID.cElems, // Number of property pages
+ caGUID.pElems, // Array of property page CLSIDs
+ 0, // Locale identifier
+ 0, 0 // Reserved
+ );
+ }
+ }*/
+
+ //for now we have 2 graphs that do the same
+ BackendNode::BackendNode(QObject *parent) : QObject(parent), m_mediaObject(0)
+ {
+ }
+
+ BackendNode::~BackendNode()
+ {
+ //this will remove the filter from the graph
+ FILTER_INFO info;
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ const Filter &filter = m_filters[i];
+ if (!filter)
+ continue;
+ filter->QueryFilterInfo(&info);
+ if (info.pGraph) {
+ HRESULT hr = info.pGraph->RemoveFilter(filter);
+
+ if (FAILED(hr) && m_mediaObject) {
+ m_mediaObject->ensureStopped();
+
+ hr = info.pGraph->RemoveFilter(filter);
+ }
+ Q_ASSERT(SUCCEEDED(hr));
+ info.pGraph->Release();
+ }
+ }
+ }
+
+ void BackendNode::setMediaObject(MediaObject *mo)
+ {
+ if (m_mediaObject) {
+ disconnect(m_mediaObject, SIGNAL(destroyed()), this, SLOT(mediaObjectDestroyed()));
+ }
+ m_mediaObject = mo;
+ connect(mo, SIGNAL(destroyed()), SLOT(mediaObjectDestroyed()));
+ }
+
+ void BackendNode::mediaObjectDestroyed()
+ {
+ //remove the filter from its graph
+ FILTER_INFO info;
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ const Filter &filter = m_filters[i];
+ if (!filter)
+ continue;
+ filter->QueryFilterInfo(&info);
+ if (info.pGraph) {
+ HRESULT hr = info.pGraph->RemoveFilter(filter);
+ Q_ASSERT(SUCCEEDED(hr));
+ Q_UNUSED(hr);
+ info.pGraph->Release();
+ }
+ }
+ m_mediaObject = 0;
+ }
+
+ QList<InputPin> BackendNode::pins(const Filter &filter, PIN_DIRECTION wantedDirection)
+ {
+ QList<InputPin> ret;
+ if (filter) {
+ ComPointer<IEnumPins> enumPin;
+ HRESULT hr = filter->EnumPins(enumPin.pparam());
+ Q_UNUSED(hr);
+ Q_ASSERT( SUCCEEDED(hr));
+ InputPin pin;
+ while (enumPin->Next(1, pin.pparam(), 0) == S_OK) {
+ PIN_DIRECTION dir;
+ hr = pin->QueryDirection(&dir);
+ Q_ASSERT( SUCCEEDED(hr));
+ if (dir == wantedDirection) {
+ ret.append(pin);
+ }
+ }
+ }
+ return ret;
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_backendnode.cpp"
diff --git a/src/3rdparty/phonon/ds9/backendnode.h b/src/3rdparty/phonon/ds9/backendnode.h
new file mode 100644
index 0000000..17bd3fb
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/backendnode.h
@@ -0,0 +1,73 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_BACKENDNODE_H
+#define PHONON_BACKENDNODE_H
+
+#include "phononds9_namespace.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QVector>
+
+#include "compointer.h"
+
+QT_BEGIN_NAMESPACE
+
+
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class MediaObject;
+ typedef ComPointer<IPin> InputPin;
+ typedef ComPointer<IPin> OutputPin;
+ typedef ComPointer<IBaseFilter> Filter;
+ typedef ComPointer<IGraphBuilder> Graph;
+
+ class BackendNode : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ BackendNode(QObject *parent);
+ virtual ~BackendNode();
+
+ MediaObject *mediaObject() const {return m_mediaObject;}
+
+ static QList<InputPin> pins(const Filter &, PIN_DIRECTION);
+
+ Filter filter(int index) const { return m_filters[index]; }
+ //add a pointer to the base Media Object (giving access to the graph and error management)
+ void setMediaObject(MediaObject *mo);
+
+ //called by the connections to tell the node that it's been connection to anothe one through its 'inpin' input port
+ virtual void connected(BackendNode *, const InputPin& inpin) {}
+
+ private Q_SLOTS:
+ void mediaObjectDestroyed();
+
+ protected:
+ Filter m_filters[FILTER_COUNT];
+ MediaObject *m_mediaObject;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/compointer.h b/src/3rdparty/phonon/ds9/compointer.h
new file mode 100644
index 0000000..180febf
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/compointer.h
@@ -0,0 +1,114 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_COMPOINTER_H
+#define PHONON_COMPOINTER_H
+
+#include <windows.h>
+#include <dshow.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ template<class T> class ComPointer
+ {
+ public:
+ explicit ComPointer(T *t = 0) : m_t(t)
+ {
+ }
+
+ explicit ComPointer( const IID &clsid, const IID &iid) : m_t(0)
+ {
+ ::CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, iid,
+ reinterpret_cast<void**>(&m_t));
+ }
+
+ explicit ComPointer(IUnknown *_unk, const GUID &guid) : m_t(0)
+ {
+ if (_unk) {
+ _unk->QueryInterface(guid, reinterpret_cast<void**>(&m_t));
+ }
+ }
+
+ ComPointer(const ComPointer<T> &other) : m_t(other.m_t)
+ {
+ if (m_t) {
+ m_t->AddRef();
+ }
+ }
+
+ ComPointer<T> &operator=(const ComPointer<T> &other)
+ {
+ if (other.m_t) {
+ other.m_t->AddRef();
+ }
+ if (m_t) {
+ m_t->Release();
+ }
+ m_t = other.m_t;
+ return *this;
+ }
+
+ T *operator->() const
+ {
+ return m_t;
+ }
+
+ operator T*() const
+ {
+ return m_t;
+ }
+
+ //the following method first reinitialize their value to avoid mem leaks
+ T ** pparam()
+ {
+ if (m_t) {
+ m_t->Release();
+ m_t = 0;
+ }
+ return &m_t;
+ }
+
+ bool operator==(const ComPointer<T> &other) const
+ {
+ return m_t == other.m_t;
+ }
+
+ bool operator!=(const ComPointer<T> &other) const
+ {
+ return m_t != other.m_t;
+ }
+
+ ~ComPointer()
+ {
+ if (m_t) {
+ m_t->Release();
+ }
+ }
+
+ private:
+ T *m_t;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/ds9.desktop b/src/3rdparty/phonon/ds9/ds9.desktop
new file mode 100644
index 0000000..764390e
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/ds9.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=PhononBackend
+MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;application/x-quicktimeplayer;video/mkv;video/msvideo;video/x-msvideo;video/x-flic;audio/x-aiff;audio/aiff;audio/x-pn-aiff;audio/x-realaudio;audio/basic;audio/x-basic;audio/x-pn-au;audio/x-8svx;audio/8svx;audio/x-16sv;audio/168sv;image/x-ilbm;image/ilbm;video/x-anim;video/anim;image/png;image/x-png;video/mng;video/x-mng;audio/x-ogg;audio/x-speex+ogg;application/ogg;application/ogg;audio/vnd.rn-realaudio;audio/x-pn-realaudio-plugin;audio/x-real-audio;application/vnd.rn-realmedia;video/mpeg;video/x-mpeg;audio/x-wav;audio/wav;audio/x-pn-wav;audio/x-pn-windows-acm;audio/mpeg2;audio/x-mpeg2;audio/mpeg3;audio/x-mpeg3;audio/mpeg;audio/x-mpeg;x-mpegurl;audio/x-mpegurl;audio/mp3;audio/mpeg;
+X-KDE-Library=phonon_ds9
+X-KDE-PhononBackendInfo-InterfaceVersion=1
+X-KDE-PhononBackendInfo-Version=0.1
+X-KDE-PhononBackendInfo-Website=http://qt.nokia.com/
+InitialPreference=15
+
+Name=DirectShow9
+Name[bg]=DirectShow9
+Name[ca]=DirectShow9
+Name[cs]=DirectShow9
+Name[da]=DirectShow9
+Name[de]=DirectShow9
+Name[el]=DirectShow9
+Name[en_GB]=DirectShow9
+Name[es]=DirectShow9
+Name[et]=DirectShow9
+Name[eu]=DirectShow9
+Name[fr]=DirectShow9
+Name[ga]=DirectShow9
+Name[gl]=DirectShow9
+Name[hsb]=DirectShow9
+Name[hu]=DirectShow9
+Name[is]=DirectShow9
+Name[it]=DirectShow9
+Name[ja]=DirectShow9
+Name[ko]=DirectShow9
+Name[ku]=DirectShow9
+Name[lt]=DirectShow9
+Name[lv]=DirectShow9
+Name[nds]=DirectShow9
+Name[nl]=DirectShow9
+Name[nn]=DirectShow9
+Name[pa]=ਡਾਇਰੈਕਸ਼ੋ9
+Name[pl]=DirectShow9
+Name[pt]=DirectShow9
+Name[pt_BR]=DirectShow9
+Name[se]=DirectShow9
+Name[sk]=DirectShow 9
+Name[sl]=DirectShow 9
+Name[sr]=Директшоу‑9
+Name[sr@latin]=DirectShow‑9
+Name[sv]=Directshow 9
+Name[tr]=DirectShow9
+Name[uk]=DirectShow9
+Name[x-test]=xxDirectShow9xx
+Name[zh_CN]=DirectShow9
+Name[zh_TW]=DirectShow9
+
+Comment=Phonon DirectShow9 backend
+Comment[bg]=Phonon DirectShow9
+Comment[ca]=Dorsal DirectShow9 del Phonon
+Comment[cs]=Phonon DirectShow9 backend
+Comment[da]=DirectShow9-backend til Phonon
+Comment[de]=Phonon-Treiber für DirectShow9
+Comment[el]=Σύστημα υποστήριξης DirectShow9 του Phonon
+Comment[en_GB]=Phonon DirectShow9 backend
+Comment[es]=Motor DirectShow9 para Phonon
+Comment[et]=Phononi DirectShow9 taustaprogramm
+Comment[eu]=Phonon DirectShow9 backend
+Comment[fr]=Système de gestion DirectShow9 pour Phonon
+Comment[ga]=Inneall DirectShow9 le haghaidh Phonon
+Comment[gl]=Infraestrutura de DirectShow9 para Phonon
+Comment[hsb]=Phonon DirectShow9 backend
+Comment[hu]=Phonon DirectShow9 modul
+Comment[is]=Phonon DirectShow9 bakendi
+Comment[it]=Motore DirectShow9 di Phonon
+Comment[ja]=Phonon DirectShow9 バックエンド
+Comment[ko]=Phonon DirectShow9 백엔드
+Comment[ku]=Binesaza Phonon DirectShow9
+Comment[lt]=Phonon DirectShow9 galinė sąsaja
+Comment[lv]=Phonon DirectShow9 aizmugure
+Comment[nds]=Phonon-Hülpprogrmm DirectShow9
+Comment[nl]=DirectShow9-backend (Phonon)
+Comment[nn]=Phonon-motor for DirectShow9
+Comment[pa]=ਫੋਨੋਨ ਡਾਇਰੈਕਟਸ਼ੋ9 ਬੈਕਐਂਡ
+Comment[pl]=Obsługa DirectShow9 przez Phonon
+Comment[pt]=Infra-estrutura do DirectShow9 para o Phonon
+Comment[pt_BR]=Infraestrutura Phonon DirectShow9
+Comment[se]=Phonon DirectShow9 duogášmohtor
+Comment[sk]=Phonon DirectShow 9 podsystém
+Comment[sl]=Phononova Hrbtenica DirectShow 9
+Comment[sr]=Директшоу‑9 као позадина Фонона
+Comment[sr@latin]=DirectShow‑9 kao pozadina Phonona
+Comment[sv]=Phonon Directshow 9-gränssnitt
+Comment[tr]=Phonon DirectShow9 arka ucu
+Comment[uk]=Сервер DirectShow9 для Phonon
+Comment[x-test]=xxPhonon DirectShow9 backendxx
+Comment[zh_CN]=Phonon DirectShow9 后端
+Comment[zh_TW]=Phonon DirectShow9 後端介面
diff --git a/src/3rdparty/phonon/ds9/effect.cpp b/src/3rdparty/phonon/ds9/effect.cpp
new file mode 100644
index 0000000..ebe976b
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/effect.cpp
@@ -0,0 +1,152 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "effect.h"
+#include <phonon/effectparameter.h>
+
+#include <medparam.h>
+#include <dmo.h>
+#include <dmodshow.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ Effect::Effect(CLSID effectClass, QObject *parent)
+ : BackendNode(parent)
+ {
+ //creation of the filter
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ Filter &filter = m_filters[i];
+ filter = Filter(CLSID_DMOWrapperFilter, IID_IBaseFilter);
+ Q_ASSERT(filter);
+ ComPointer<IDMOWrapperFilter> wrapper(filter, IID_IDMOWrapperFilter);
+ Q_ASSERT(wrapper);
+ wrapper->Init(effectClass, DMOCATEGORY_AUDIO_EFFECT);
+ }
+ }
+
+ Effect::Effect(QObject *parent) : BackendNode(parent)
+ {
+ //at this point the QVector of Filter should be filled
+ }
+
+ Effect::~Effect()
+ {
+ }
+
+ QList<Phonon::EffectParameter> Effect::parameters() const
+ {
+ QList<Phonon::EffectParameter> ret;
+ ComPointer<IMediaParamInfo> paramInfo(m_filters[0], IID_IMediaParamInfo);
+ if (!paramInfo) {
+ return ret;
+ }
+ DWORD paramCount = 0;
+ paramInfo->GetParamCount( &paramCount);
+
+ for(quint32 i = 0; i < paramCount; i++) {
+ MP_PARAMINFO info;
+ HRESULT hr = paramInfo->GetParamInfo(i, &info);
+ Q_ASSERT(SUCCEEDED(hr));
+ WCHAR *name = 0;
+ hr = paramInfo->GetParamText(i, &name);
+ Q_ASSERT(SUCCEEDED(hr));
+ QVariant def, min, max;
+
+ QVariantList values;
+
+ switch(info.mpType)
+ {
+ case MPT_ENUM:
+ {
+ WCHAR *current = name;
+ current += wcslen(current) + 1; //skip the name
+ current += wcslen(current) + 1; //skip the unit
+ for(; *current; current += wcslen(current) + 1) {
+ values.append( QString::fromWCharArray(current) );
+ }
+ }
+ //FALLTHROUGH
+ case MPT_INT:
+ def = int(info.mpdNeutralValue);
+ min = int(info.mpdMinValue);
+ max = int(info.mpdMaxValue);
+ break;
+ case MPT_FLOAT:
+ def = info.mpdNeutralValue;
+ min = info.mpdMinValue;
+ max = info.mpdMaxValue;
+ break;
+ case MPT_BOOL:
+ def = bool(info.mpdNeutralValue);
+ break;
+ case MPT_MAX:
+ //Reserved ms-help://MS.PSDKSVR2003R2.1033/directshow/htm/mp_typeenumeration.htm
+ break;
+ }
+
+ Phonon::EffectParameter::Hints hint = info.mopCaps == MP_CAPS_CURVE_INVSQUARE ?
+ Phonon::EffectParameter::LogarithmicHint : Phonon::EffectParameter::Hints(0);
+
+ const QString n = QString::fromWCharArray(name);
+ ret.append(Phonon::EffectParameter(i, n, hint, def, min, max, values));
+ ::CoTaskMemFree(name); //let's free the memory
+ }
+ return ret;
+ }
+
+ QVariant Effect::parameterValue(const Phonon::EffectParameter &p) const
+ {
+ QVariant ret;
+ ComPointer<IMediaParams> params(m_filters[0], IID_IMediaParams);
+ Q_ASSERT(params);
+ MP_DATA data;
+ HRESULT hr = params->GetParam(p.id(), &data);
+ if(SUCCEEDED(hr))
+ return data;
+ else
+ return QVariant();
+ }
+
+ void Effect::setParameterValue(const Phonon::EffectParameter &p, const QVariant &v)
+ {
+ if (v.isNull()) {
+ return;
+ }
+
+ for(int i=0; i < FILTER_COUNT ; ++i) {
+ const Filter &filter = m_filters[i];
+ ComPointer<IMediaParams> params(filter, IID_IMediaParams);
+ Q_ASSERT(params);
+
+ params->SetParam(p.id(), v.toFloat());
+ }
+ }
+
+ }
+}
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
+
+#include "moc_effect.cpp"
diff --git a/src/3rdparty/phonon/ds9/effect.h b/src/3rdparty/phonon/ds9/effect.h
new file mode 100644
index 0000000..50f3ea2
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/effect.h
@@ -0,0 +1,59 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_AUDIOEFFECT_H
+#define PHONON_AUDIOEFFECT_H
+
+#include <QtCore/QObject>
+#include <phonon/effectinterface.h>
+#include "backendnode.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class EffectInterface;
+
+ class Effect : public BackendNode, public Phonon::EffectInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface)
+ public:
+ Effect(CLSID effectClass, QObject *parent);
+ ~Effect();
+
+ QList<Phonon::EffectParameter> parameters() const;
+ QVariant parameterValue(const Phonon::EffectParameter &) const;
+ void setParameterValue(const Phonon::EffectParameter &, const QVariant &);
+
+
+ protected:
+ //this is the constructor called by the explicit subclasses of effect
+ Effect(QObject *parent);
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
+
+#endif // PHONON_AUDIOEFFECT_H
diff --git a/src/3rdparty/phonon/ds9/fakesource.cpp b/src/3rdparty/phonon/ds9/fakesource.cpp
new file mode 100644
index 0000000..4dce138
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/fakesource.cpp
@@ -0,0 +1,144 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "fakesource.h"
+#include "qpin.h"
+
+#include <dshow.h>
+#include <initguid.h>
+#include <dvdmedia.h> // VIDEOINFOHEADER2
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ static WAVEFORMATEX g_defaultWaveFormat = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0};
+ static VIDEOINFOHEADER2 g_defaultVideoInfo = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {sizeof(BITMAPINFOHEADER), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0} };
+
+ static const AM_MEDIA_TYPE g_fakeAudioType = {MEDIATYPE_Audio, MEDIASUBTYPE_PCM, 0, 0, 2, FORMAT_WaveFormatEx, 0, sizeof(WAVEFORMATEX), reinterpret_cast<BYTE*>(&g_defaultWaveFormat)};
+ static const AM_MEDIA_TYPE g_fakeVideoType = {MEDIATYPE_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 0, FORMAT_VideoInfo2, 0, sizeof(VIDEOINFOHEADER2), reinterpret_cast<BYTE*>(&g_defaultVideoInfo)};
+
+ class FakePin : public QPin
+ {
+ public:
+ FakePin(FakeSource *source, const AM_MEDIA_TYPE &mt) :
+ QPin(source, PINDIR_OUTPUT, QVector<AM_MEDIA_TYPE>() << mt), m_source(source)
+ {
+ setAvailable(true);
+ }
+
+ ~FakePin()
+ {
+ }
+
+
+ STDMETHODIMP Disconnect()
+ {
+ HRESULT hr = QPin::Disconnect();
+ if (SUCCEEDED(hr)) {
+ setAvailable(true);
+ }
+ return hr;
+ }
+
+
+ STDMETHODIMP Connect(IPin *pin, const AM_MEDIA_TYPE *type)
+ {
+ HRESULT hr = QPin::Connect(pin, type);
+ if (SUCCEEDED(hr)) {
+ setAvailable(false);
+ }
+ return hr;
+ }
+
+ private:
+ void setAvailable(bool avail)
+ {
+ if (mediaTypes().first().majortype == MEDIATYPE_Audio) {
+ if (avail) {
+ m_source->addAvailableAudioPin(this);
+ } else {
+ m_source->removeAvailableAudioPin(this);
+ }
+ } else {
+ if (avail) {
+ m_source->addAvailableVideoPin(this);
+ } else {
+ m_source->removeAvailableVideoPin(this);
+ }
+ }
+ }
+
+ FakeSource *m_source;
+
+
+ };
+
+ FakeSource::FakeSource() : QBaseFilter(CLSID_NULL)
+ {
+ createFakeAudioPin();
+ createFakeVideoPin();
+ }
+
+ FakeSource::~FakeSource()
+ {
+ }
+
+ void FakeSource::addAvailableAudioPin(FakePin *pin)
+ {
+ availableAudioPins += pin;
+ }
+
+ void FakeSource::addAvailableVideoPin(FakePin *pin)
+ {
+ availableVideoPins += pin;
+ }
+
+ void FakeSource::removeAvailableAudioPin(FakePin *pin)
+ {
+ availableAudioPins -= pin;
+
+ if (availableAudioPins.isEmpty()) {
+ createFakeAudioPin();
+ }
+ }
+
+ void FakeSource::removeAvailableVideoPin(FakePin *pin)
+ {
+ availableVideoPins -= pin;
+
+ if (availableVideoPins.isEmpty()) {
+ createFakeVideoPin();
+ }
+ }
+
+ void FakeSource::createFakeAudioPin()
+ {
+ new FakePin(this, g_fakeAudioType);
+ }
+
+ void FakeSource::createFakeVideoPin()
+ {
+ new FakePin(this, g_fakeVideoType);
+ }
+
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/fakesource.h b/src/3rdparty/phonon/ds9/fakesource.h
new file mode 100644
index 0000000..a32e0c2
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/fakesource.h
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_FAKESOURCE_H
+#define PHONON_FAKESOURCE_H
+
+#include <QtCore/QSet>
+
+#include "qbasefilter.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class FakePin;
+ class FakeSource : public QBaseFilter
+ {
+ public:
+ FakeSource();
+ ~FakeSource();
+
+ void addAvailableAudioPin(FakePin*);
+ void addAvailableVideoPin(FakePin*);
+ void removeAvailableAudioPin(FakePin*);
+ void removeAvailableVideoPin(FakePin*);
+ private:
+ void createFakeVideoPin();
+ void createFakeAudioPin();
+
+ QSet<FakePin*> availableAudioPins;
+ QSet<FakePin*> availableVideoPins;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/iodevicereader.cpp b/src/3rdparty/phonon/ds9/iodevicereader.cpp
new file mode 100644
index 0000000..ba4ae5c
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/iodevicereader.cpp
@@ -0,0 +1,175 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "iodevicereader.h"
+#include "qasyncreader.h"
+
+#include "mediagraph.h"
+
+#include <phonon/streaminterface.h>
+
+#include <dshow.h>
+#include <initguid.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ //these mediatypes define a stream, its type will be autodetected by DirectShow
+ static QVector<AM_MEDIA_TYPE> getMediaTypes()
+ {
+ //the order here is important because otherwise,
+ //directshow might not be able to detect the stream type correctly
+
+ AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_Avi, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
+
+ QVector<AM_MEDIA_TYPE> ret;
+ //AVI stream
+ ret << mt;
+ //WAVE stream
+ mt.subtype = MEDIASUBTYPE_WAVE;
+ ret << mt;
+ //normal auto-detect stream (must be at the end!)
+ mt.subtype = MEDIASUBTYPE_NULL;
+ ret << mt;
+ return ret;
+ }
+
+ class StreamReader : public QAsyncReader, public Phonon::StreamInterface
+ {
+ public:
+ StreamReader(QBaseFilter *parent, const Phonon::MediaSource &source, const MediaGraph *mg) :
+ QAsyncReader(parent, getMediaTypes()),
+ m_seekable(false), m_pos(0), m_size(-1), m_mediaGraph(mg)
+ {
+ connectToSource(source);
+ }
+
+ //for Phonon::StreamInterface
+ void writeData(const QByteArray &data)
+ {
+ m_pos += data.size();
+ m_buffer += data;
+ }
+
+ void endOfData()
+ {
+ }
+
+ void setStreamSize(qint64 newSize)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_size = newSize;
+ }
+
+ void setStreamSeekable(bool s)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_seekable = s;
+ }
+
+ //virtual pure members
+
+ //implementation from IAsyncReader
+ STDMETHODIMP Length(LONGLONG *total, LONGLONG *available)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (total) {
+ *total = m_size;
+ }
+
+ if (available) {
+ *available = m_size;
+ }
+
+ return S_OK;
+ }
+
+
+ HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual)
+ {
+ Q_ASSERT(!m_mutex.tryLock());
+ if (m_mediaGraph->isStopping()) {
+ return VFW_E_WRONG_STATE;
+ }
+
+ if(m_size != 1 && pos + length > m_size) {
+ //it tries to read outside of the boundaries
+ return E_FAIL;
+ }
+
+ if (m_pos - m_buffer.size() != pos) {
+ if (!m_seekable) {
+ return S_FALSE;
+ }
+ m_pos = pos;
+ seekStream(pos);
+ m_buffer.clear();
+ }
+
+ int oldSize = m_buffer.size();
+ while (m_buffer.size() < int(length)) {
+ needData();
+
+ if (oldSize == m_buffer.size()) {
+ break; //we didn't get any data
+ }
+ oldSize = m_buffer.size();
+ }
+
+ int bytesRead = qMin(m_buffer.size(), int(length));
+ qMemCopy(buffer, m_buffer.data(), bytesRead);
+ //truncate the buffer
+ m_buffer = m_buffer.mid(bytesRead);
+
+ if (actual) {
+ *actual = bytesRead; //initialization
+ }
+
+ return bytesRead == length ? S_OK : S_FALSE;
+ }
+
+ public:
+ //for Phonon::StreamInterface
+ QByteArray m_buffer;
+ bool m_seekable;
+ qint64 m_pos;
+ qint64 m_size;
+
+ const MediaGraph *m_mediaGraph;
+ };
+
+ IODeviceReader::IODeviceReader(const Phonon::MediaSource &source, const MediaGraph *mg) :
+ QBaseFilter(CLSID_NULL)
+ {
+ //create the output pin
+ m_streamReader = new StreamReader(this, source, mg);
+ }
+
+ IODeviceReader::~IODeviceReader()
+ {
+ }
+ }
+}
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/iodevicereader.h b/src/3rdparty/phonon/ds9/iodevicereader.h
new file mode 100644
index 0000000..c8b91c3
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/iodevicereader.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_IODEVICEREADER_H
+#define PHONON_IODEVICEREADER_H
+
+#include "qbasefilter.h"
+
+#include <phonon/mediasource.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+ class MediaSource;
+ namespace DS9
+ {
+ class MediaGraph;
+ class StreamReader;
+
+ //for the streams...
+ //the filter
+ class IODeviceReader : public QBaseFilter
+ {
+ public:
+ IODeviceReader(const MediaSource &source, const MediaGraph *);
+ ~IODeviceReader();
+
+ private:
+ StreamReader *m_streamReader;
+ };
+
+ }
+}
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/lgpl-2.1.txt b/src/3rdparty/phonon/ds9/lgpl-2.1.txt
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/lgpl-2.1.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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 library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/3rdparty/phonon/ds9/lgpl-3.txt b/src/3rdparty/phonon/ds9/lgpl-3.txt
new file mode 100644
index 0000000..fc8a5de
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/lgpl-3.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/3rdparty/phonon/ds9/mediagraph.cpp b/src/3rdparty/phonon/ds9/mediagraph.cpp
new file mode 100644
index 0000000..3e7a68b
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/mediagraph.cpp
@@ -0,0 +1,1101 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "fakesource.h"
+#include "iodevicereader.h"
+#include "qaudiocdreader.h"
+
+#include "mediagraph.h"
+#include "mediaobject.h"
+
+
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+#include <qnetwork.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ //description of a connection
+ struct GraphConnection
+ {
+ Filter output;
+ int outputOffset;
+ Filter input;
+ int inputOffset;
+ };
+
+ static QList<GraphConnection> getConnections(Filter source)
+ {
+ QList<GraphConnection> ret;
+ int outOffset = 0;
+ const QList<OutputPin> outputs = BackendNode::pins(source, PINDIR_OUTPUT);
+ for (int i = 0; i < outputs.count(); ++i) {
+ InputPin input;
+ if (outputs.at(i)->ConnectedTo(input.pparam()) == S_OK) {
+ PIN_INFO info;
+ input->QueryPinInfo(&info);
+ Filter current(info.pFilter);
+ if (current) {
+ //this is a valid connection
+ const int inOffset = BackendNode::pins(current, PINDIR_INPUT).indexOf(input);
+ const GraphConnection connection = {source, outOffset, current, inOffset};
+ ret += connection;
+ ret += getConnections(current); //get subsequent connections
+ }
+ }
+ outOffset++;
+ }
+ return ret;
+ }
+
+
+/*
+ static HRESULT saveToFile(Graph graph, const QString &filepath)
+ {
+ const WCHAR wszStreamName[] = L"ActiveMovieGraph";
+ HRESULT hr;
+ ComPointer<IStorage> storage;
+
+ // First, create a document file that will hold the GRF file
+ hr = StgCreateDocfile((OLECHAR*)filepath.utf16(),
+ STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, storage.pparam());
+
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ // Next, create a stream to store.
+ ComPointer<IStream> stream;
+ hr = storage->CreateStream(wszStreamName,
+ STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
+ 0, 0, stream.pparam());
+
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ // The IpersistStream::Save method converts a stream into a persistent object.
+ ComPointer<IPersistStream> persist(graph, IID_IPersistStream);
+ hr = persist->Save(stream, TRUE);
+ if (SUCCEEDED(hr)) {
+ hr = storage->Commit(STGC_DEFAULT);
+ }
+
+ return hr;
+ }
+*/
+
+ MediaGraph::MediaGraph(MediaObject *mo, short index) :
+ m_graph(CLSID_FilterGraph, IID_IGraphBuilder),
+ m_fakeSource(new FakeSource()),
+ m_hasVideo(false), m_hasAudio(false), m_connectionsDirty(false),
+ m_isStopping(false), m_isSeekable(false), m_result(S_OK),
+ m_index(index), m_renderId(0), m_seekId(0),
+ m_currentTime(0), m_totalTime(0), m_mediaObject(mo)
+ {
+ m_mediaControl = ComPointer<IMediaControl>(m_graph, IID_IMediaControl);
+ Q_ASSERT(m_mediaControl);
+ m_mediaSeeking = ComPointer<IMediaSeeking>(m_graph, IID_IMediaSeeking);
+ Q_ASSERT(m_mediaSeeking);
+
+ HRESULT hr = m_graph->AddFilter(m_fakeSource, 0);
+ if (m_mediaObject->catchComError(hr)) {
+ return;
+ }
+ }
+
+ MediaGraph::~MediaGraph()
+ {
+ }
+
+ short MediaGraph::index() const
+ {
+ return m_index;
+ }
+
+ void MediaGraph::grabNode(BackendNode *node)
+ {
+ grabFilter(node->filter(m_index));
+ }
+
+ void MediaGraph::grabFilter(Filter filter)
+ {
+ if (filter) {
+ FILTER_INFO info;
+ filter->QueryFilterInfo(&info);
+ if (info.pGraph != m_graph) {
+ if (info.pGraph) {
+ m_mediaObject->catchComError(info.pGraph->RemoveFilter(filter));
+ }
+ m_mediaObject->catchComError(m_graph->AddFilter(filter, 0));
+ }
+ if (info.pGraph) {
+ info.pGraph->Release();
+ }
+ }
+ }
+
+ void MediaGraph::switchFilters(Filter oldFilter, Filter newFilter)
+ {
+ OAFilterState state = syncGetRealState();
+ if (state != State_Stopped) {
+ ensureStopped(); //to do the transaction
+ }
+
+
+ OutputPin connected;
+ {
+ InputPin pin = BackendNode::pins(oldFilter, PINDIR_INPUT).first();
+ pin->ConnectedTo(connected.pparam());
+ }
+
+ m_graph->RemoveFilter(oldFilter);
+ m_graph->AddFilter(newFilter, 0);
+
+ if (connected) {
+ InputPin pin = BackendNode::pins(newFilter, PINDIR_INPUT).first();
+ //let's reestablish the connections
+ m_graph->Connect(connected, pin);
+ }
+
+ switch(state)
+ {
+ case State_Running:
+ play();
+ break;
+ case State_Paused:
+ pause();
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ OAFilterState MediaGraph::syncGetRealState() const
+ {
+ OAFilterState state;
+ m_mediaControl->GetState(INFINITE, &state);
+ return state;
+ }
+
+
+
+ void MediaGraph::ensureSourceDisconnected()
+ {
+ for (int i = 0; i < m_sinkConnections.count(); ++i) {
+ const Filter currentFilter = m_sinkConnections.at(i)->filter(m_index);
+ const QList<InputPin> inputs = BackendNode::pins(currentFilter, PINDIR_INPUT);
+ const QList<InputPin> outputs = BackendNode::pins(m_fakeSource, PINDIR_OUTPUT);
+
+ for (int i = 0; i < inputs.count(); ++i) {
+ for (int o = 0; o < outputs.count(); o++) {
+ tryDisconnect(outputs.at(o), inputs.at(i));
+ }
+
+ for (int d = 0; d < m_decoderPins.count(); ++d) {
+ tryDisconnect(m_decoderPins.at(d), inputs.at(i));
+ }
+ }
+ }
+ }
+
+ void MediaGraph::ensureSourceConnectedTo(bool force)
+ {
+ if (m_connectionsDirty == false && force == false) {
+ return;
+ }
+
+ m_connectionsDirty = false;
+ ensureSourceDisconnected();
+
+ //reconnect the pins
+ for (int i = 0; i < m_sinkConnections.count(); ++i) {
+ const Filter currentFilter = m_sinkConnections.at(i)->filter(m_index);
+ const QList<InputPin> inputs = BackendNode::pins(currentFilter, PINDIR_INPUT);
+ for(int i = 0; i < inputs.count(); ++i) {
+ //we ensure the filter belongs to the graph
+ grabFilter(currentFilter);
+
+ for (int d = 0; d < m_decoderPins.count(); ++d) {
+ //a decoder has only one output
+ if (tryConnect(m_decoderPins.at(d), inputs.at(i))) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ QList<Filter> MediaGraph::getAllFilters(Graph graph)
+ {
+ QList<Filter> ret;
+ ComPointer<IEnumFilters> enumFilters;
+ graph->EnumFilters(enumFilters.pparam());
+ Filter current;
+ while( enumFilters && enumFilters->Next(1, current.pparam(), 0) == S_OK) {
+ ret += current;
+ }
+ return ret;
+ }
+
+ QList<Filter> MediaGraph::getAllFilters() const
+ {
+ return getAllFilters(m_graph);
+ }
+
+
+ bool MediaGraph::isSeekable() const
+ {
+ return m_isSeekable;
+ }
+
+ qint64 MediaGraph::absoluteTotalTime() const
+ {
+ if (m_seekId) {
+ return m_totalTime;
+ } else {
+ qint64 ret = 0;
+ if (m_mediaSeeking) {
+ m_mediaSeeking->GetDuration(&ret);
+ ret /= 10000; //convert to milliseconds
+ }
+ return ret;
+ }
+ }
+
+ qint64 MediaGraph::absoluteCurrentTime() const
+ {
+ if (m_seekId) {
+ return m_currentTime;
+ } else {
+ qint64 ret = -1;
+ if (m_mediaSeeking) {
+ HRESULT hr = m_mediaSeeking->GetCurrentPosition(&ret);
+ if (FAILED(hr)) {
+ return ret;
+ }
+ ret /= 10000; //convert to milliseconds
+ }
+ return ret;
+ }
+ }
+
+ Phonon::MediaSource MediaGraph::mediaSource() const
+ {
+ return m_mediaSource;
+ }
+
+ void MediaGraph::play()
+ {
+ ensureSourceConnectedTo();
+ m_mediaObject->workerThread()->addStateChangeRequest(m_graph, State_Running, m_decoders);
+ }
+
+ void MediaGraph::pause()
+ {
+ ensureSourceConnectedTo();
+ m_mediaObject->workerThread()->addStateChangeRequest(m_graph, State_Paused, m_decoders);
+ }
+
+ HRESULT MediaGraph::renderResult() const
+ {
+ return m_result;
+ }
+
+ bool MediaGraph::isStopping() const
+ {
+ return m_isStopping;
+ }
+
+ Graph MediaGraph::graph() const
+ {
+ return m_graph;
+ }
+
+ void MediaGraph::stop()
+ {
+ if (!isLoading()) {
+ ensureStopped();
+ absoluteSeek(0); //resets the clock
+ } else {
+ m_mediaObject->workerThread()->abortCurrentRender(m_renderId);
+ m_renderId = 0; //cancels current loading
+ }
+ m_mediaObject->workerThread()->addStateChangeRequest(m_graph, State_Stopped);
+ }
+
+ void MediaGraph::ensureStopped()
+ {
+ m_isStopping = true;
+ //special case here because we want stopped to be synchronous
+ m_graph->Abort();
+ m_mediaControl->Stop();
+ OAFilterState dummy;
+ //this will wait until the change is effective
+ m_mediaControl->GetState(INFINITE, &dummy);
+ m_isStopping = false;
+ }
+
+ bool MediaGraph::isLoading() const
+ {
+ return m_renderId != 0;
+ }
+
+ void MediaGraph::absoluteSeek(qint64 time)
+ {
+ //this just sends a request
+ if (m_seekId == 0) {
+ m_currentTime = absoluteCurrentTime();
+ m_totalTime = absoluteTotalTime();
+ }
+ m_seekId = m_mediaObject->workerThread()->addSeekRequest(m_graph, time);
+ }
+
+ HRESULT MediaGraph::removeFilter(const Filter& filter)
+ {
+ FILTER_INFO info;
+ filter->QueryFilterInfo(&info);
+#ifdef GRAPH_DEBUG
+ qDebug() << "removeFilter" << QString((const QChar *)info.achName);
+#endif
+ if (info.pGraph) {
+ info.pGraph->Release();
+ if (info.pGraph == m_graph)
+ return m_graph->RemoveFilter(filter);
+ }
+
+ //already removed
+ return S_OK;
+ }
+
+ HRESULT MediaGraph::cleanup()
+ {
+ stop();
+
+ ensureSourceDisconnected();
+
+ QList<Filter> list = m_decoders;
+ if (m_demux) {
+ list << m_demux;
+ }
+ if (m_realSource) {
+ list << m_realSource;
+ }
+ list << m_decoders;
+
+ for (int i = 0; i < m_decoders.count(); ++i) {
+ list += getFilterChain(m_demux, m_decoders.at(i));
+ }
+
+ for (int i = 0; i < list.count(); ++i) {
+ removeFilter(list.at(i));
+ }
+
+ //Let's reinitialize the internal lists
+ m_decoderPins.clear();
+ m_decoders.clear();
+ m_demux = Filter();
+ m_realSource = Filter();
+ m_mediaSource = Phonon::MediaSource();
+
+ absoluteSeek(0); //resets the clock
+
+ return S_OK;
+ }
+
+
+ bool MediaGraph::disconnectNodes(BackendNode *source, BackendNode *sink)
+ {
+ const Filter sinkFilter = sink->filter(m_index);
+ const QList<InputPin> inputs = BackendNode::pins(sinkFilter, PINDIR_INPUT);
+
+ QList<OutputPin> outputs;
+ if (source == m_mediaObject) {
+ outputs = BackendNode::pins(m_fakeSource, PINDIR_OUTPUT);
+ outputs += m_decoderPins;
+ } else {
+ outputs = BackendNode::pins(source->filter(m_index), PINDIR_OUTPUT);
+ }
+
+
+ for (int i = 0; i < inputs.count(); ++i) {
+ for (int o = 0; o < outputs.count(); ++o) {
+ tryDisconnect(outputs.at(o), inputs.at(i));
+ }
+ }
+
+ if (m_sinkConnections.removeOne(sink)) {
+ m_connectionsDirty = true;
+ }
+ return true;
+ }
+
+ bool MediaGraph::tryDisconnect(const OutputPin &out, const InputPin &in)
+ {
+ bool ret = false;
+
+ OutputPin output;
+ if (SUCCEEDED(in->ConnectedTo(output.pparam()))) {
+
+ if (output == out) {
+ //we need a simple disconnection
+ ret = SUCCEEDED(out->Disconnect()) && SUCCEEDED(in->Disconnect());
+ } else {
+ InputPin in2;
+ if (SUCCEEDED(out->ConnectedTo(in2.pparam()))) {
+ PIN_INFO info;
+ in2->QueryPinInfo(&info);
+ Filter tee(info.pFilter);
+ CLSID clsid;
+ tee->GetClassID(&clsid);
+ if (clsid == CLSID_InfTee) {
+ //we have to remove all intermediate filters between the tee and the sink
+ PIN_INFO info;
+ in->QueryPinInfo(&info);
+ Filter sink(info.pFilter);
+ QList<Filter> list = getFilterChain(tee, sink);
+ out->QueryPinInfo(&info);
+ Filter source(info.pFilter);
+
+ if (list.isEmpty()) {
+ output->QueryPinInfo(&info);
+ if (Filter(info.pFilter) == tee) {
+ ret = SUCCEEDED(output->Disconnect()) && SUCCEEDED(in->Disconnect());
+ }
+ } else {
+ ret = true;
+ for (int i = 0; i < list.count(); ++i) {
+ ret = ret && SUCCEEDED(removeFilter(list.at(i)));
+ }
+ }
+
+ //Let's try to see if the Tee filter is still useful
+ if (ret) {
+ int connections = 0;
+ const QList<OutputPin> outputs = BackendNode::pins(tee, PINDIR_OUTPUT);
+ for(int i = 0; i < outputs.count(); ++i) {
+ InputPin p;
+ if ( SUCCEEDED(outputs.at(i)->ConnectedTo(p.pparam()))) {
+ connections++;
+ }
+ }
+ if (connections == 0) {
+ //this avoids a crash if the filter is destroyed
+ //by the subsequent call to removeFilter
+ output = OutputPin();
+ removeFilter(tee); //there is no more output for the tee, we remove it
+ }
+ }
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+ bool MediaGraph::tryConnect(const OutputPin &out, const InputPin &newIn)
+ {
+
+
+ ///The management of the creation of the Tees is done here (this is the only place where we call IPin::Connect
+ InputPin inPin;
+ if (SUCCEEDED(out->ConnectedTo(inPin.pparam()))) {
+
+ //the fake source has another mechanism for the connection
+ if (BackendNode::pins(m_fakeSource, PINDIR_OUTPUT).contains(out)) {
+ return false;
+ }
+
+ //the output pin is already connected
+ PIN_INFO info;
+ inPin->QueryPinInfo(&info);
+ Filter filter(info.pFilter); //this will ensure the interface is "Release"d
+ CLSID clsid;
+ filter->GetClassID(&clsid);
+ if (clsid == CLSID_InfTee) {
+ //there is already a Tee (namely 'filter') in use
+ const QList<OutputPin> outputs = BackendNode::pins(filter, PINDIR_OUTPUT);
+ for(int i = 0; i < outputs.count(); ++i) {
+ const OutputPin &pin = outputs.at(i);
+ if (HRESULT(VFW_E_NOT_CONNECTED) == pin->ConnectedTo(inPin.pparam())) {
+ return SUCCEEDED(pin->Connect(newIn, 0));
+ }
+ }
+ //we shoud never go here
+ return false;
+ } else {
+ QAMMediaType type;
+ out->ConnectionMediaType(&type);
+
+ //first we disconnect the current connection (and we save the current media type)
+ if (!tryDisconnect(out, inPin)) {
+ return false;
+ }
+
+ //..then we try to connect the new node
+ if (SUCCEEDED(out->Connect(newIn, 0))) {
+
+ //we have to insert the Tee
+ if (!tryDisconnect(out, newIn)) {
+ return false;
+ }
+
+ Filter filter(CLSID_InfTee, IID_IBaseFilter);
+ if (!filter) {
+ //rollback
+ m_graph->Connect(out, inPin);
+ return false;
+ }
+
+ if (FAILED(m_graph->AddFilter(filter, 0))) {
+ return false;
+ }
+
+
+ InputPin teeIn = BackendNode::pins(filter, PINDIR_INPUT).first(); //a Tee has always one input
+ HRESULT hr = out->Connect(teeIn, &type);
+ if (FAILED(hr)) {
+ hr = m_graph->Connect(out, teeIn);
+ }
+ if (FAILED(hr)) {
+ m_graph->Connect(out, inPin);
+ return false;
+ }
+
+ OutputPin teeOut = BackendNode::pins(filter, PINDIR_OUTPUT).last(); //the last is always the one that's not connected
+
+ //we simply reconnect the pins as they
+ hr = m_graph->Connect(teeOut, inPin);
+ if (FAILED(hr)) {
+ m_graph->Connect(out, inPin);
+ return false;
+ }
+
+ teeOut = BackendNode::pins(filter, PINDIR_OUTPUT).last(); //the last is always the one that's not connected
+ if (FAILED(m_graph->Connect(teeOut, newIn))) {
+ m_graph->Connect(out, inPin);
+ return false;
+ }
+
+ return true;
+ } else {
+ //we simply reconnect the pins as they
+ m_graph->Connect(out, inPin);
+ return false;
+ }
+ }
+
+ } else {
+ return SUCCEEDED(m_graph->Connect(out, newIn));
+ }
+ }
+
+ bool MediaGraph::connectNodes(BackendNode *source, BackendNode *sink)
+ {
+ bool ret = false;
+ const QList<InputPin> inputs = BackendNode::pins(sink->filter(m_index), PINDIR_INPUT);
+ QList<OutputPin> outputs = BackendNode::pins(source == m_mediaObject ? m_fakeSource : source->filter(m_index), PINDIR_OUTPUT);
+
+ if (source == m_mediaObject) {
+ grabFilter(m_fakeSource);
+ }
+
+#ifdef GRAPH_DEBUG
+ qDebug() << Q_FUNC_INFO << source << sink << this;
+#endif
+
+ for (int o = 0; o < outputs.count(); o++) {
+ InputPin p;
+ for (int i = 0; i < inputs.count(); i++) {
+ const InputPin &inPin = inputs.at(i);
+ if (tryConnect(outputs.at(o), inPin)) {
+ //tell the sink node that it just got a new input
+ sink->connected(source, inPin);
+ ret = true;
+ if (source == m_mediaObject) {
+ m_connectionsDirty = true;
+ m_sinkConnections += sink;
+#ifdef GRAPH_DEBUG
+ qDebug() << "found a sink connection" << sink << m_sinkConnections.count();
+#endif
+ }
+ break;
+ }
+ }
+ }
+
+ return ret;
+ }
+
+
+ HRESULT MediaGraph::loadSource(const Phonon::MediaSource &source)
+ {
+ m_hasVideo = false;
+ m_hasAudio = false;
+ m_isSeekable = false;
+
+
+ //cleanup of the previous filters
+ m_result = cleanup();
+ if (FAILED(m_result)) {
+ return m_result;
+ }
+
+ m_mediaSource = source;
+
+ switch (source.type())
+ {
+ case Phonon::MediaSource::Disc:
+ if (source.discType() == Phonon::Dvd) {
+ m_result = E_NOTIMPL;
+ /*m_realSource = Filter(CLSID_DVDNavigator, IID_IBaseFilter);
+ if (m_realSource) {
+ return REGDB_E_CLASSNOTREG;
+ }
+
+ m_result = m_graph->AddFilter(m_realSource, L"DVD Navigator");*/
+
+
+ #ifndef QT_NO_PHONON_MEDIACONTROLLER
+ } else if (source.discType() == Phonon::Cd) {
+ m_realSource = Filter(new QAudioCDPlayer);
+
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+ } else {
+ m_result = E_NOTIMPL;
+ }
+ if (FAILED(m_result)) {
+ return m_result;
+ }
+ m_renderId = m_mediaObject->workerThread()->addFilterToRender(m_realSource);
+ return m_result;
+ case Phonon::MediaSource::Invalid:
+ return m_result;
+ case Phonon::MediaSource::Url:
+ case Phonon::MediaSource::LocalFile:
+ {
+ QString url;
+ if (source.type() == Phonon::MediaSource::LocalFile) {
+ url = source.fileName();
+ } else {
+ url = source.url().toString();
+ }
+ m_renderId = m_mediaObject->workerThread()->addUrlToRender(url);
+ }
+ break;
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ case Phonon::MediaSource::Stream:
+ {
+ m_realSource = Filter(new IODeviceReader(source, this));
+ m_renderId = m_mediaObject->workerThread()->addFilterToRender(m_realSource);
+ }
+ break;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ default:
+ m_result = E_FAIL;
+ }
+
+ return m_result;
+ }
+
+ void MediaGraph::finishSeeking(quint16 workId, qint64 time)
+ {
+ if (m_seekId == workId) {
+ m_currentTime = time;
+ m_mediaObject->seekingFinished(this);
+ m_seekId = 0;
+ } else {
+ //it's a queue seek command
+ //we're still seeking
+ }
+ }
+
+ void MediaGraph::finishLoading(quint16 workId, HRESULT hr, Graph graph)
+ {
+ if (m_renderId == workId) {
+ m_renderId = 0;
+
+ //let's determine if the graph is seekable
+ {
+ ComPointer<IMediaSeeking> mediaSeeking(graph, IID_IMediaSeeking);
+ DWORD caps = AM_SEEKING_CanSeekAbsolute;
+ m_isSeekable = mediaSeeking && SUCCEEDED(mediaSeeking->CheckCapabilities(&caps));
+ }
+
+ m_result = reallyFinishLoading(hr, graph);
+ m_mediaObject->loadingFinished(this);
+ }
+ }
+
+
+ HRESULT MediaGraph::reallyFinishLoading(HRESULT hr, const Graph &graph)
+ {
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ const Graph oldGraph = m_graph;
+ m_graph = graph;
+
+ //we keep the source and all the way down to the decoders
+ QList<Filter> removedFilters;
+
+ const QList<Filter> allFilters = getAllFilters(graph);
+ for (int i = 0; i < allFilters.count(); ++i) {
+ const Filter &filter = allFilters.at(i);
+ if (isSourceFilter(filter)) {
+ m_realSource = filter; //save the source filter
+ if (!m_demux ) {
+ m_demux = filter; //in the WMV case, the demuxer is the source filter itself
+ }
+ } else if (isDemuxerFilter(filter)) {
+ m_demux = filter;
+ } else if (isDecoderFilter(filter)) {
+ m_decoders += filter;
+ m_decoderPins += BackendNode::pins(filter, PINDIR_OUTPUT).first();
+ } else {
+ removedFilters += filter;
+ }
+ }
+
+ for (int i = 0; i < m_decoders.count(); ++i) {
+ QList<Filter> chain = getFilterChain(m_demux, m_decoders.at(i));
+ for (int i = 0; i < chain.count(); ++i) {
+ //we keep those filters
+ removedFilters.removeOne(chain.at(i));
+ }
+ }
+
+ for (int i = 0; i < removedFilters.count(); ++i) {
+ graph->RemoveFilter(removedFilters.at(i));
+ }
+
+ m_mediaObject->workerThread()->replaceGraphForEventManagement(graph, oldGraph);
+
+ //let's transfer the nodes from the current graph to the new one
+ QList<GraphConnection> connections; //we store the connections that need to be restored
+
+ // First get all the sink nodes (nodes with no input connected)
+ for (int i = 0; i < m_sinkConnections.count(); ++i) {
+ Filter currentFilter = m_sinkConnections.at(i)->filter(m_index);
+ connections += getConnections(currentFilter);
+ grabFilter(currentFilter);
+ }
+
+ //we need to do something smart to detect if the streams are unencoded
+ if (m_demux) {
+ const QList<OutputPin> outputs = BackendNode::pins(m_demux, PINDIR_OUTPUT);
+ for (int i = 0; i < outputs.count(); ++i) {
+ const OutputPin &out = outputs.at(i);
+ InputPin pin;
+ if (out->ConnectedTo(pin.pparam()) == HRESULT(VFW_E_NOT_CONNECTED)) {
+ m_decoderPins += out; //unconnected outputs can be decoded outputs
+ }
+ }
+ }
+
+ ensureSourceConnectedTo(true);
+
+ //let's reestablish the connections
+ for (int i = 0; i < connections.count(); ++i) {
+ const GraphConnection &connection = connections.at(i);
+ //check if we shoud transfer the sink node
+
+ grabFilter(connection.input);
+ grabFilter(connection.output);
+
+ const OutputPin output = BackendNode::pins(connection.output, PINDIR_OUTPUT).at(connection.outputOffset);
+ const InputPin input = BackendNode::pins(connection.input, PINDIR_INPUT).at(connection.inputOffset);
+ HRESULT hr = output->Connect(input, 0);
+ Q_UNUSED(hr);
+ Q_ASSERT( SUCCEEDED(hr));
+ }
+
+ //Finally, let's update the interfaces
+ m_mediaControl = ComPointer<IMediaControl>(graph, IID_IMediaControl);
+ m_mediaSeeking = ComPointer<IMediaSeeking>(graph, IID_IMediaSeeking);
+ return hr;
+ }
+
+ //utility functions
+ //retrieves the filters between source and sink
+ QList<Filter> MediaGraph::getFilterChain(const Filter &source, const Filter &sink)
+ {
+ QList<Filter> ret;
+ Filter current = sink;
+ while (current && BackendNode::pins(current, PINDIR_INPUT).count() == 1 && current != source) {
+ if (current != source)
+ ret += current;
+ InputPin pin = BackendNode::pins(current, PINDIR_INPUT).first();
+ current = Filter();
+ OutputPin output;
+ if (pin->ConnectedTo(output.pparam()) == S_OK) {
+ PIN_INFO info;
+ if (SUCCEEDED(output->QueryPinInfo(&info)) && info.pFilter) {
+ current = Filter(info.pFilter); //this will take care of releasing the interface pFilter
+ }
+ }
+ }
+ if (current != source) {
+ //the soruce and sink don't seem to be connected
+ ret.clear();
+ }
+ return ret;
+ }
+
+ bool MediaGraph::isDecoderFilter(const Filter &filter)
+ {
+ if (filter == 0) {
+ return false;
+ }
+#ifdef GRAPH_DEBUG
+ {
+ FILTER_INFO info;
+ filter->QueryFilterInfo(&info);
+ qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName);
+ if (info.pGraph) {
+ info.pGraph->Release();
+ }
+ }
+#endif
+
+
+ QList<InputPin> inputs = BackendNode::pins(filter, PINDIR_INPUT);
+ QList<OutputPin> outputs = BackendNode::pins(filter, PINDIR_OUTPUT);
+
+ //TODO: find a better way to detect if a node is a decoder
+ if (inputs.count() == 0 || outputs.count() ==0) {
+ return false;
+ }
+
+ //the input pin must be encoded data
+ QAMMediaType type;
+ HRESULT hr = inputs.first()->ConnectionMediaType(&type);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+
+ //...and the output must be decoded
+ QAMMediaType type2;
+ hr = outputs.first()->ConnectionMediaType(&type2);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ if (type2.majortype != MEDIATYPE_Video &&
+ type2.majortype != MEDIATYPE_Audio) {
+ return false;
+ }
+
+ if (type2.majortype == MEDIATYPE_Video) {
+ m_hasVideo = true;
+ } else {
+ m_hasAudio = true;
+ }
+
+#ifdef GRAPH_DEBUG
+ {
+ FILTER_INFO info;
+ filter->QueryFilterInfo(&info);
+ qDebug() << "found a decoder filter" << QString((const QChar *)info.achName);
+ if (info.pGraph) {
+ info.pGraph->Release();
+ }
+ }
+#endif
+
+ return true;
+ }
+
+ bool MediaGraph::isSourceFilter(const Filter &filter) const
+ {
+#ifdef GRAPH_DEBUG
+ {
+ FILTER_INFO info;
+ filter->QueryFilterInfo(&info);
+ qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName);
+ if (info.pGraph) {
+ info.pGraph->Release();
+ }
+ }
+#endif
+ //a source filter is one that has no input
+ return BackendNode::pins(filter, PINDIR_INPUT).isEmpty();
+ }
+
+ bool MediaGraph::isDemuxerFilter(const Filter &filter) const
+ {
+ QList<InputPin> inputs = BackendNode::pins(filter, PINDIR_INPUT);
+ QList<OutputPin> outputs = BackendNode::pins(filter, PINDIR_OUTPUT);
+
+#ifdef GRAPH_DEBUG
+ {
+ FILTER_INFO info;
+ filter->QueryFilterInfo(&info);
+ qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName);
+ if (info.pGraph) {
+ info.pGraph->Release();
+ }
+ }
+#endif
+
+ if (inputs.count() != 1 || outputs.count() == 0) {
+ return false; //a demuxer has only one input
+ }
+
+ QAMMediaType type;
+ HRESULT hr = inputs.first()->ConnectionMediaType(&type);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ if (type.majortype != MEDIATYPE_Stream) {
+ return false;
+ }
+
+ for (int i = 0; i < outputs.count(); ++i) {
+ QAMMediaType type;
+ //for now we support only video and audio
+ hr = outputs.at(i)->ConnectionMediaType(&type);
+ if (SUCCEEDED(hr) &&
+ type.majortype != MEDIATYPE_Video && type.majortype != MEDIATYPE_Audio) {
+ return false;
+ }
+ }
+#ifdef GRAPH_DEBUG
+ {
+ FILTER_INFO info;
+ filter->QueryFilterInfo(&info);
+ qDebug() << "found a demuxer filter" << QString((const QChar *)info.achName);
+ if (info.pGraph) {
+ info.pGraph->Release();
+ }
+ }
+#endif
+ return true;
+ }
+
+ QMultiMap<QString, QString> MediaGraph::metadata() const
+ {
+ QMultiMap<QString, QString> ret;
+ ComPointer<IAMMediaContent> mediaContent(m_demux, IID_IAMMediaContent);
+ if (mediaContent) {
+ //let's get the meta data
+ BSTR str;
+ HRESULT hr = mediaContent->get_AuthorName(&str);
+ if (SUCCEEDED(hr)) {
+ ret.insert(QLatin1String("ARTIST"), QString::fromWCharArray(str));
+ SysFreeString(str);
+ }
+ hr = mediaContent->get_Title(&str);
+ if (SUCCEEDED(hr)) {
+ ret.insert(QLatin1String("TITLE"), QString::fromWCharArray(str));
+ SysFreeString(str);
+ }
+ hr = mediaContent->get_Description(&str);
+ if (SUCCEEDED(hr)) {
+ ret.insert(QLatin1String("DESCRIPTION"), QString::fromWCharArray(str));
+ SysFreeString(str);
+ }
+ hr = mediaContent->get_Copyright(&str);
+ if (SUCCEEDED(hr)) {
+ ret.insert(QLatin1String("COPYRIGHT"), QString::fromWCharArray(str));
+ SysFreeString(str);
+ }
+ hr = mediaContent->get_MoreInfoText(&str);
+ if (SUCCEEDED(hr)) {
+ ret.insert(QLatin1String("MOREINFO"), QString::fromWCharArray(str));
+ SysFreeString(str);
+ }
+ }
+ return ret;
+ }
+
+ Filter MediaGraph::realSource() const
+ {
+ return m_realSource;
+ }
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ void MediaGraph::setStopPosition(qint64 time)
+ {
+ qint64 current = 0,
+ stop = 0;
+ m_mediaSeeking->GetPositions(&current, &stop);
+
+ const bool shouldSeek = current == stop;
+
+ if (time == -1) {
+ HRESULT hr = m_mediaSeeking->GetDuration(&time);
+ if (FAILED(hr)) {
+ return;
+ }
+ } else {
+ time *= 10000;
+ }
+
+ if (time == stop) {
+ //the stop position is already at the right place
+ return;
+ }
+
+ if (shouldSeek) {
+ m_mediaSeeking->SetPositions(&current, AM_SEEKING_AbsolutePositioning,
+ &time, AM_SEEKING_AbsolutePositioning);
+ } else {
+ m_mediaSeeking->SetPositions(0, AM_SEEKING_NoPositioning,
+ &time, AM_SEEKING_AbsolutePositioning);
+ }
+ }
+
+ qint64 MediaGraph::stopPosition() const
+ {
+ qint64 ret;
+ m_mediaSeeking->GetStopPosition(&ret);
+ return ret / 10000;
+
+ }
+
+ QList<qint64> MediaGraph::titles() const
+ {
+ //for now we only manage that for the audio cd
+ ComPointer<ITitleInterface> titleIFace(m_realSource, IID_ITitleInterface);
+ if (titleIFace) {
+ return titleIFace->titles();
+ } else {
+ // the default value: only one title that starts at position 0
+ return QList<qint64>() << 0;
+ }
+ }
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+
+
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/mediagraph.h b/src/3rdparty/phonon/ds9/mediagraph.h
new file mode 100644
index 0000000..13e7bcf
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/mediagraph.h
@@ -0,0 +1,148 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_MEDIAGRAPH_H
+#define PHONON_MEDIAGRAPH_H
+
+#include "backendnode.h"
+#include <QtCore/QMultiMap>
+
+#include <phonon/mediasource.h>
+
+//#define GRAPH_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class MediaObject;
+
+ //in the end we should probably have no more inheritance here: everything should be in the interface of the class
+ //could be nice to then remove all the "*this" in the code of this class
+ class MediaGraph : public QObject
+ {
+ public:
+ MediaGraph(MediaObject *mo, short index);
+ ~MediaGraph();
+ bool isSeekable() const;
+ qint64 absoluteTotalTime() const;
+ qint64 absoluteCurrentTime() const;
+ void play();
+ void stop();
+ void pause();
+ void absoluteSeek(qint64);
+
+ QMultiMap<QString, QString> metadata() const;
+
+ static QList<Filter> getAllFilters(Graph graph);
+ QList<Filter> getAllFilters() const;
+
+ HRESULT loadSource(const Phonon::MediaSource &);
+
+ bool hasVideo() const { return m_hasVideo; }
+ void grabNode(BackendNode *node);
+ void grabFilter(Filter filter);
+
+ //connections of the nodes
+ bool connectNodes(BackendNode *source, BackendNode *sink);
+ bool disconnectNodes(BackendNode *source, BackendNode *sink);
+
+ Phonon::MediaSource mediaSource() const;
+
+ //before loading a source, and after its playback this will be called
+ HRESULT cleanup();
+ void ensureStopped();
+
+ short index() const;
+
+ Filter realSource() const;
+
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ QList<qint64> titles() const;
+ void setStopPosition(qint64 time);
+ qint64 stopPosition() const;
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+ void switchFilters(Filter oldFilter, Filter newFilter);
+ OAFilterState syncGetRealState() const;
+
+ bool isLoading() const;
+ bool isStopping() const;
+ HRESULT renderResult() const;
+
+ Graph graph() const;
+
+ void finishLoading(quint16 workId, HRESULT hr, Graph);
+ void finishSeeking(quint16 workId, qint64 time);
+
+ private:
+ bool isSourceFilter(const Filter &filter) const;
+ bool isDemuxerFilter(const Filter &filter) const;
+ bool isDecoderFilter(const Filter &filter);
+ static QList<Filter> getFilterChain(const Filter &source, const Filter &sink);
+
+ HRESULT reallyFinishLoading(HRESULT, const Graph &graph);
+
+
+ //utility functions
+ void ensureSourceConnectedTo(bool force = false);
+ void ensureSourceDisconnected();
+ bool tryConnect(const OutputPin &, const InputPin &);
+ bool tryDisconnect(const OutputPin &, const InputPin &);
+ HRESULT removeFilter(const Filter& filter);
+
+ //after loading, removes the decoders that are not linked to a sink
+ HRESULT removeUselessDecoders();
+
+ //COM objects
+ Graph m_graph;
+ ComPointer<IMediaControl> m_mediaControl;
+ ComPointer<IMediaSeeking> m_mediaSeeking;
+ Filter m_fakeSource, m_realSource;
+ Filter m_demux;
+ QList<OutputPin> m_decoderPins;
+ QList<Filter> m_decoders;
+
+ bool m_hasVideo;
+ bool m_hasAudio;
+ bool m_connectionsDirty;
+ bool m_isStopping;
+ mutable bool m_isSeekable;
+ HRESULT m_result;
+ quint16 m_index;
+ quint16 m_renderId;
+ quint16 m_seekId;
+
+ //while seeking we need to store the current time
+ qint64 m_currentTime;
+ qint64 m_totalTime;
+
+ MediaObject *m_mediaObject;
+ Phonon::MediaSource m_mediaSource;
+ QList<BackendNode*> m_sinkConnections; //connections to the source
+
+ Q_DISABLE_COPY(MediaGraph);
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_MEDIAGRAPH_H
diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp
new file mode 100644
index 0000000..d640956
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/mediaobject.cpp
@@ -0,0 +1,1181 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QtCore/QVector>
+#include <QtCore/QTimerEvent>
+#include <QtCore/QTimer>
+#include <QtCore/QTime>
+#include <QtCore/QLibrary>
+
+#ifndef Q_CC_MSVC
+#include <dshow.h>
+#endif
+#include <objbase.h>
+#include <initguid.h>
+#include <qnetwork.h>
+#ifdef Q_CC_MSVC
+# include <comdef.h>
+#endif
+#include <evcode.h>
+
+#include "mediaobject.h"
+#include "videowidget.h"
+#include "audiooutput.h"
+
+
+#include <QtCore/QDebug>
+
+#define TIMER_INTERVAL 16 //... ms for the timer that polls the current state (we use the multimedia timer)
+#define PRELOAD_TIME 2000 // 2 seconds to load a source
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ typedef BOOL (WINAPI* LPAMGETERRORTEXT)(HRESULT, WCHAR *, DWORD);
+
+ //first the definition of the WorkerThread class
+ WorkerThread::WorkerThread()
+ : QThread(), m_finished(false), m_currentWorkId(1)
+ {
+ }
+
+ WorkerThread::~WorkerThread()
+ {
+ }
+
+ void WorkerThread::run()
+ {
+ while (m_finished == false) {
+ HANDLE handles[FILTER_COUNT +1];
+ handles[0] = m_waitCondition;
+ int count = 1;
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ if (m_graphHandle[i].graph) {
+ handles[count++] = m_graphHandle[i].handle;
+ }
+ }
+ DWORD result = ::WaitForMultipleObjects(count, handles, FALSE, INFINITE);
+ if (result == WAIT_OBJECT_0) {
+ handleTask();
+ } else {
+ //this is the event management
+ const Graph &graph = m_graphHandle[result - WAIT_OBJECT_0 - 1].graph;
+ long eventCode;
+ LONG_PTR param1, param2;
+
+ ComPointer<IMediaEvent> mediaEvent(graph, IID_IMediaEvent);
+ mediaEvent->GetEvent(&eventCode, &param1, &param2, 0);
+ emit eventReady(graph, eventCode, param1);
+ mediaEvent->FreeEventParams(eventCode, param1, param2);
+ }
+ }
+ }
+
+ //wants to know as soon as the state is set
+ void WorkerThread::addStateChangeRequest(Graph graph, OAFilterState state, QList<Filter> decoders)
+ {
+ QMutexLocker locker(&m_mutex);
+ bool found = false;
+ //we try to see if there is already an attempt to change the state and we remove it
+ for(int i = 0; !found && i < m_queue.size(); ++i) {
+ const Work &w = m_queue.at(i);
+ if (w.graph == graph && w.task == ChangeState) {
+ found = true;
+ m_queue.removeAt(i);
+ }
+ }
+
+ //now let's create the new task
+ Work w;
+ w.task = ChangeState;
+ w.id = m_currentWorkId++;
+ w.graph = graph;
+ w.state = state;
+ w.decoders = decoders;
+ m_queue.enqueue(w);
+ m_waitCondition.set();
+ }
+
+ quint16 WorkerThread::addSeekRequest(Graph graph, qint64 time)
+ {
+ QMutexLocker locker(&m_mutex);
+ bool found = false;
+ //we try to see if there is already an attempt to seek and we remove it
+ for(int i = 0; !found && i < m_queue.size(); ++i) {
+ const Work &w = m_queue.at(i);
+ if (w.graph == graph && w.task == Seek) {
+ found = true;
+ m_queue.removeAt(i);
+ }
+ }
+
+ Work w;
+ w.task = Seek;
+ //we create a new graph
+ w.graph = graph;
+ w.id = m_currentWorkId++;
+ w.time = time;
+ m_queue.enqueue(w);
+ m_waitCondition.set();
+ return w.id;
+ }
+
+ quint16 WorkerThread::addUrlToRender(const QString &url)
+ {
+ QMutexLocker locker(&m_mutex);
+ Work w;
+ w.task = Render;
+ //we create a new graph
+ w.graph = Graph(CLSID_FilterGraph, IID_IGraphBuilder);
+ w.url = url;
+ w.url.detach();
+ w.id = m_currentWorkId++;
+ m_queue.enqueue(w);
+ m_waitCondition.set();
+ return w.id;
+ }
+
+ quint16 WorkerThread::addFilterToRender(const Filter &filter)
+ {
+ QMutexLocker locker(&m_mutex);
+ Work w;
+ w.task = Render;
+ //we create a new graph
+ w.graph = Graph(CLSID_FilterGraph, IID_IGraphBuilder);
+ w.filter = filter;
+ w.graph->AddFilter(filter, 0);
+ w.id = m_currentWorkId++;
+ m_queue.enqueue(w);
+ m_waitCondition.set();
+ return w.id;
+ }
+
+ void WorkerThread::replaceGraphForEventManagement(Graph newGraph, Graph oldGraph)
+ {
+ QMutexLocker locker(&m_mutex);
+ Work w;
+ w.task = ReplaceGraph;
+ w.graph = newGraph;
+ w.oldGraph = oldGraph;
+ m_queue.enqueue(w);
+ m_waitCondition.set();
+ }
+
+ void WorkerThread::handleTask()
+ {
+ QMutexLocker locker(Backend::directShowMutex);
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_finished || m_queue.isEmpty()) {
+ return;
+ }
+
+ m_currentWork = m_queue.dequeue();
+
+ //we ensure to have the wait condition in the right state
+ if (m_queue.isEmpty()) {
+ m_waitCondition.reset();
+ } else {
+ m_waitCondition.set();
+ }
+ }
+
+ HRESULT hr = S_OK;
+
+ if (m_currentWork.task == ReplaceGraph) {
+ int index = -1;
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ if (m_graphHandle[i].graph == m_currentWork.oldGraph) {
+ m_graphHandle[i].graph = Graph();
+ index = i;
+ break;
+ } else if (index == -1 && m_graphHandle[i].graph == 0) {
+ //this is the first available slot
+ index = i;
+ }
+ }
+
+ Q_ASSERT(index != -1);
+
+ //add the new graph
+ HANDLE h;
+ if (SUCCEEDED(ComPointer<IMediaEvent>(m_currentWork.graph, IID_IMediaEvent)
+ ->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) {
+ m_graphHandle[index].graph = m_currentWork.graph;
+ m_graphHandle[index].handle = h;
+ }
+ } else if (m_currentWork.task == Render) {
+ if (m_currentWork.filter) {
+ //let's render pins
+ const QList<OutputPin> outputs = BackendNode::pins(m_currentWork.filter, PINDIR_OUTPUT);
+ for (int i = 0; SUCCEEDED(hr) && i < outputs.count(); ++i) {
+ hr = m_currentWork.graph->Render(outputs.at(i));
+ }
+ } else if (!m_currentWork.url.isEmpty()) {
+ //let's render a url (blocking call)
+ hr = m_currentWork.graph->RenderFile(reinterpret_cast<const wchar_t *>(m_currentWork.url.utf16()), 0);
+ }
+ if (hr != E_ABORT) {
+ emit asyncRenderFinished(m_currentWork.id, hr, m_currentWork.graph);
+ }
+ } else if (m_currentWork.task == Seek) {
+ //that's a seekrequest
+ ComPointer<IMediaSeeking> mediaSeeking(m_currentWork.graph, IID_IMediaSeeking);
+ qint64 newtime = m_currentWork.time * 10000;
+ hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning,
+ 0, AM_SEEKING_NoPositioning);
+ emit asyncSeekingFinished(m_currentWork.id, newtime / 10000);
+ hr = E_ABORT; //to avoid emitting asyncRenderFinished
+ } else if (m_currentWork.task == ChangeState) {
+
+ //remove useless decoders
+ QList<Filter> unused;
+ for (int i = 0; i < m_currentWork.decoders.count(); ++i) {
+ const Filter &filter = m_currentWork.decoders.at(i);
+ bool used = false;
+ const QList<OutputPin> pins = BackendNode::pins(filter, PINDIR_OUTPUT);
+ for( int i = 0; i < pins.count(); ++i) {
+ InputPin input;
+ if (pins.at(i)->ConnectedTo(input.pparam()) == S_OK) {
+ used = true;
+ }
+ }
+ if (!used) {
+ unused += filter;
+ }
+ }
+
+ //we can get the state
+ for (int i = 0; i < unused.count(); ++i) {
+ //we should remove this filter from the graph
+ m_currentWork.graph->RemoveFilter(unused.at(i));
+ }
+
+
+ //we can get the state
+ ComPointer<IMediaControl> mc(m_currentWork.graph, IID_IMediaControl);
+
+ //we change the state here
+ switch(m_currentWork.state)
+ {
+ case State_Stopped:
+ mc->Stop();
+ break;
+ case State_Paused:
+ mc->Pause();
+ break;
+ case State_Running:
+ mc->Run();
+ break;
+ }
+ OAFilterState s;
+ //blocking call
+ HRESULT hr = mc->GetState(INFINITE, &s);
+
+ if (SUCCEEDED(hr)) {
+ if (s == State_Stopped) {
+ emit stateReady(m_currentWork.graph, Phonon::StoppedState);
+ } else if (s == State_Paused) {
+ emit stateReady(m_currentWork.graph, Phonon::PausedState);
+ } else /*if (s == State_Running)*/ {
+ emit stateReady(m_currentWork.graph, Phonon::PlayingState);
+ }
+ }
+ }
+
+ {
+ QMutexLocker locker(&m_mutex);
+ m_currentWork = Work(); //reinitialize
+ }
+ }
+
+ void WorkerThread::abortCurrentRender(qint16 renderId)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_currentWork.id == renderId) {
+ m_currentWork.graph->Abort();
+ }
+ bool found = false;
+ for(int i = 0; !found && i < m_queue.size(); ++i) {
+ const Work &w = m_queue.at(i);
+ if (w.id == renderId) {
+ found = true;
+ m_queue.removeAt(i);
+ if (m_queue.isEmpty()) {
+ m_waitCondition.reset();
+ }
+ }
+ }
+ }
+
+ //tells the thread to stop processing
+ void WorkerThread::signalStop()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_queue.clear();
+ if (m_currentWork.graph) {
+ //in case we're currently rendering something
+ m_currentWork.graph->Abort();
+
+ }
+
+ m_finished = true;
+ m_waitCondition.set();
+ }
+
+
+ MediaObject::MediaObject(QObject *parent) : BackendNode(parent),
+ transactionState(Phonon::StoppedState),
+ m_errorType(Phonon::NoError),
+ m_state(Phonon::LoadingState),
+ m_nextState(Phonon::StoppedState),
+ m_prefinishMark(0),
+ m_tickInterval(0),
+ m_buffering(false),
+ m_oldHasVideo(false),
+ m_prefinishMarkSent(false),
+ m_aboutToFinishSent(false),
+ m_nextSourceReadyToStart(false),
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ m_autoplayTitles(true),
+ m_currentTitle(0),
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+ m_targetTick(INFINITE)
+ {
+
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ m_graphs[i] = new MediaGraph(this, i);
+ }
+
+ connect(&m_thread, SIGNAL(stateReady(Graph,Phonon::State)),
+ SLOT(slotStateReady(Graph,Phonon::State)));
+
+ connect(&m_thread, SIGNAL(eventReady(Graph,long,long)),
+ SLOT(handleEvents(Graph,long,long)));
+
+ connect(&m_thread, SIGNAL(asyncRenderFinished(quint16,HRESULT,Graph)),
+ SLOT(finishLoading(quint16,HRESULT,Graph)));
+
+ connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16,qint64)),
+ SLOT(finishSeeking(quint16,qint64)));
+ //really special case
+ m_mediaObject = this;
+ m_thread.start();
+ }
+
+ MediaObject::~MediaObject()
+ {
+ //be sure to finish the timer first
+ m_tickTimer.stop();
+
+ //we finish the worker thread here
+ m_thread.signalStop();
+ m_thread.wait();
+
+ //and then we delete the graphs
+ for (int i = 0; i < FILTER_COUNT; ++i) {
+ delete m_graphs[i];
+ }
+ }
+
+ WorkerThread *MediaObject::workerThread()
+ {
+ return &m_thread;
+ }
+
+ MediaGraph *MediaObject::currentGraph() const
+ {
+ return m_graphs[0];
+ }
+
+ MediaGraph *MediaObject::nextGraph() const
+ {
+ return m_graphs[FILTER_COUNT - 1];
+ }
+
+ //utility function to save the graph to a file
+ void MediaObject::timerEvent(QTimerEvent *e)
+ {
+ if (e->timerId() == m_tickTimer.timerId()) {
+
+ const qint64 current = currentTime();
+ const qint64 total = totalTime();
+
+ if ( m_tickInterval != 0 && current > m_targetTick) {
+ updateTargetTick();
+ emit tick(current);
+ }
+
+ //check that the title hasn't changed
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ if (m_autoplayTitles && m_currentTitle < _iface_availableTitles() - 1) {
+
+ if (current >= total) {
+ //we go to the next title
+ _iface_setCurrentTitle(m_currentTitle + 1, false);
+ emit tick(current);
+ }
+ return;
+ }
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+ if (total) {
+ const qint64 remaining = total - current;
+
+ if (m_transitionTime < 0 && m_nextSourceReadyToStart) {
+ if (remaining < -m_transitionTime + TIMER_INTERVAL/2) {
+ //we need to switch graphs to run the next source in the queue (with cross-fading)
+ switchToNextSource();
+ return;
+ } else if (current < -m_transitionTime) {
+ //we are currently crossfading
+ for (int i = 0; i < m_audioOutputs.count(); ++i) {
+ m_audioOutputs.at(i)->setCrossFadingProgress( currentGraph()->index(), qMin( qreal(1.), qreal(current) / qreal(-m_transitionTime)));
+ }
+ }
+ }
+
+ if (m_prefinishMark > 0 && !m_prefinishMarkSent && remaining < m_prefinishMark + TIMER_INTERVAL/2) {
+#ifdef GRAPH_DEBUG
+ qDebug() << "DS9: emit prefinishMarkReached" << remaining << QTime::currentTime().toString();
+#endif
+ m_prefinishMarkSent = true;
+
+ emit prefinishMarkReached( remaining );
+ }
+
+ if (!m_aboutToFinishSent && remaining < PRELOAD_TIME - m_transitionTime + TIMER_INTERVAL/2) {
+ //let's take a 2 seconds time to actually load the next file
+#ifdef GRAPH_DEBUG
+ qDebug() << "DS9: emit aboutToFinish" << remaining << QTime::currentTime().toString();
+#endif
+ m_aboutToFinishSent = true;
+ emit aboutToFinish();
+ }
+ } else {
+ //total is 0: the stream is probably live (endless)
+ }
+
+ if (m_buffering) {
+ ComPointer<IAMNetworkStatus> status(currentGraph()->realSource(), IID_IAMNetworkStatus);
+ if (status) {
+ long l;
+ status->get_BufferingProgress(&l);
+ emit bufferStatus(l);
+#ifdef GRAPH_DEBUG
+ qDebug() << "emit bufferStatus(" << l << ")";
+#endif
+ }
+ }
+ }
+ }
+
+ void MediaObject::switchToNextSource()
+ {
+ m_prefinishMarkSent = false;
+ m_aboutToFinishSent = false;
+ m_nextSourceReadyToStart = false;
+
+ m_oldHasVideo = currentGraph()->hasVideo();
+
+ qSwap(m_graphs[0], m_graphs[1]); //swap the graphs
+
+ if (m_transitionTime >= 0)
+ m_graphs[1]->stop(); //make sure we stop the previous graph
+
+ if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid &&
+ catchComError(currentGraph()->renderResult())) {
+ setState(Phonon::ErrorState);
+ return;
+ }
+
+ //we need to play the next media
+ play();
+
+ //we tell the video widgets to switch now to the new source
+#ifndef QT_NO_PHONON_VIDEO
+ for (int i = 0; i < m_videoWidgets.count(); ++i) {
+ m_videoWidgets.at(i)->setCurrentGraph(currentGraph()->index());
+ }
+#endif //QT_NO_PHONON_VIDEO
+
+ emit currentSourceChanged(currentGraph()->mediaSource());
+ emit metaDataChanged(currentGraph()->metadata());
+
+ if (nextGraph()->hasVideo() != currentGraph()->hasVideo()) {
+ emit hasVideoChanged(currentGraph()->hasVideo());
+ }
+
+ emit tick(0);
+ emit totalTimeChanged(totalTime());
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ setTitles(currentGraph()->titles());
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+ }
+
+ Phonon::State MediaObject::state() const
+ {
+ if (m_buffering) {
+ return Phonon::BufferingState;
+ } else {
+ return m_state;
+ }
+ }
+
+ bool MediaObject::hasVideo() const
+ {
+ return currentGraph()->hasVideo();
+ }
+
+ bool MediaObject::isSeekable() const
+ {
+ return currentGraph()->isSeekable();
+ }
+
+ qint64 MediaObject::totalTime() const
+ {
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ //1st, check if there is more titles after
+ const qint64 ret = (m_currentTitle < _iface_availableTitles() - 1) ?
+ titleAbsolutePosition(m_currentTitle+1) : currentGraph()->absoluteTotalTime();
+
+ //this is the duration of the current title
+ return ret - titleAbsolutePosition(m_currentTitle);
+#else
+ return currentGraph()->absoluteTotalTime();
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+ }
+
+ qint64 MediaObject::currentTime() const
+ {
+ //this handles inaccuracy when stopping on a title
+ return currentGraph()->absoluteCurrentTime()
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ - titleAbsolutePosition(m_currentTitle)
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+ ;
+ }
+
+ qint32 MediaObject::tickInterval() const
+ {
+ return m_tickInterval;
+ }
+
+ void MediaObject::setTickInterval(qint32 newTickInterval)
+ {
+ m_tickInterval = newTickInterval;
+ updateTargetTick();
+ }
+
+ void MediaObject::pause()
+ {
+ if (currentGraph()->isLoading()) {
+ m_nextState = Phonon::PausedState;
+ } else {
+ currentGraph()->pause();
+ }
+ }
+
+ void MediaObject::stop()
+ {
+ if (currentGraph()->isLoading()) {
+ m_nextState = Phonon::StoppedState;
+ } else {
+ currentGraph()->stop();
+ }
+ }
+
+ void MediaObject::ensureStopped()
+ {
+ currentGraph()->ensureStopped();
+ if (m_state == Phonon::ErrorState) {
+ //we reset the state here
+ m_state = Phonon::StoppedState;
+ }
+ }
+
+ void MediaObject::play()
+ {
+ if (currentGraph()->isLoading()) {
+ m_nextState = Phonon::PlayingState;
+ } else {
+ currentGraph()->play();
+ }
+ }
+
+ QString MediaObject::errorString() const
+ {
+ return m_errorString;
+ }
+
+ Phonon::ErrorType MediaObject::errorType() const
+ {
+ return m_errorType;
+ }
+
+
+ void MediaObject::updateTargetTick()
+ {
+ if (m_tickInterval) {
+ const qint64 current = currentTime();
+ m_targetTick = current / m_tickInterval * m_tickInterval;
+ if (current == 0 || m_targetTick < current) {
+ m_targetTick += m_tickInterval;
+ }
+ }
+ }
+
+ void MediaObject::setState(Phonon::State newstate)
+ {
+ if (newstate == Phonon::PlayingState) {
+ updateTargetTick();
+ }
+
+ if (newstate == m_state) {
+ return;
+ }
+
+ //manage the timer
+ if (newstate == Phonon::PlayingState) {
+ m_tickTimer.start(TIMER_INTERVAL, this);
+ } else {
+ m_tickTimer.stop();
+ }
+
+ Phonon::State oldstate = state();
+ m_state = newstate;
+ emit stateChanged(newstate, oldstate);
+ }
+
+
+ qint32 MediaObject::prefinishMark() const
+ {
+ return m_prefinishMark;
+ }
+
+ void MediaObject::setPrefinishMark(qint32 newPrefinishMark)
+ {
+ m_prefinishMark = newPrefinishMark;
+ }
+
+ qint32 MediaObject::transitionTime() const
+ {
+ return m_transitionTime;
+ }
+
+ void MediaObject::setTransitionTime(qint32 time)
+ {
+ m_transitionTime = time;
+ }
+
+ qint64 MediaObject::remainingTime() const
+ {
+ return totalTime() - currentTime();
+ }
+
+
+ Phonon::MediaSource MediaObject::source() const
+ {
+ return currentGraph()->mediaSource();
+ }
+
+ void MediaObject::setNextSource(const Phonon::MediaSource &source)
+ {
+ m_nextSourceReadyToStart = true;
+ const bool shouldSwitch = (m_state == Phonon::StoppedState || m_state == Phonon::ErrorState);
+ nextGraph()->loadSource(source); //let's preload the source
+
+ if (shouldSwitch) {
+ switchToNextSource();
+ }
+ }
+
+ void MediaObject::setSource(const Phonon::MediaSource &source)
+ {
+ m_nextSourceReadyToStart = false;
+ m_prefinishMarkSent = false;
+ m_aboutToFinishSent = false;
+
+ m_oldHasVideo = currentGraph()->hasVideo();
+ setState(Phonon::LoadingState);
+ //After loading we go into stopped state
+ m_nextState = Phonon::StoppedState;
+ catchComError(currentGraph()->loadSource(source));
+ emit currentSourceChanged(source);
+ }
+
+ void MediaObject::slotStateReady(Graph graph, Phonon::State newState)
+ {
+ if (graph == currentGraph()->graph() && !currentGraph()->isLoading()) {
+ setState(newState);
+ }
+ }
+
+ void MediaObject::loadingFinished(MediaGraph *mg)
+ {
+ if (mg == currentGraph()) {
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ //Title interface
+ m_currentTitle = 0;
+ setTitles(currentGraph()->titles());
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+ HRESULT hr = mg->renderResult();
+
+ if (catchComError(hr)) {
+ return;
+ }
+
+ if (m_oldHasVideo != currentGraph()->hasVideo()) {
+ emit hasVideoChanged(currentGraph()->hasVideo());
+ }
+
+#ifndef QT_NO_PHONON_VIDEO
+ if (currentGraph()->hasVideo()) {
+ updateVideoGeometry();
+ }
+#endif //QT_NO_PHONON_VIDEO
+
+ emit metaDataChanged(currentGraph()->metadata());
+ emit totalTimeChanged(totalTime());
+
+ //let's put the next state
+ switch(m_nextState)
+ {
+ case Phonon::PausedState:
+ pause();
+ break;
+ case Phonon::PlayingState:
+ play();
+ break;
+ case Phonon::ErrorState:
+ setState(Phonon::ErrorState);
+ break;
+ case Phonon::StoppedState:
+ default:
+ stop();
+ break;
+ }
+ }
+ }
+
+ void MediaObject::seek(qint64 time)
+ {
+ //we seek into the current title
+ currentGraph()->absoluteSeek(time
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ + titleAbsolutePosition(m_currentTitle)
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+ );
+ }
+
+ void MediaObject::seekingFinished(MediaGraph *mg)
+ {
+ if (mg == currentGraph()) {
+
+ updateTargetTick();
+ if (currentTime() < totalTime() - m_prefinishMark) {
+ m_prefinishMarkSent = false;
+ }
+
+ if (currentTime() < totalTime() - PRELOAD_TIME + m_transitionTime) {
+ m_aboutToFinishSent = false;
+ }
+
+ //this helps the update of the application (seekslider for example)
+ if (m_state == PausedState || m_state == PlayingState) {
+ emit tick(currentTime());
+ }
+ }
+ }
+
+
+ bool MediaObject::catchComError(HRESULT hr)
+ {
+
+ m_errorString.clear();
+ m_errorType = Phonon::NoError;
+
+ if (hr != S_OK) {
+#ifdef GRAPH_DEBUG
+ qWarning("an error occurred 0x%x",hr);
+#endif
+ LPAMGETERRORTEXT getErrorText = (LPAMGETERRORTEXT)QLibrary::resolve(QLatin1String("quartz"), "AMGetErrorTextW");
+
+ WCHAR buffer[MAX_ERROR_TEXT_LEN];
+ if (getErrorText && getErrorText(hr, buffer, MAX_ERROR_TEXT_LEN)) {
+ m_errorString = QString::fromWCharArray(buffer);
+ } else {
+ m_errorString = QString::fromLatin1("Unknown error");
+ }
+ const QString comError = QString::number(uint(hr), 16);
+ if (!m_errorString.toLower().contains(comError.toLower())) {
+ m_errorString += QString::fromLatin1(" (0x%1)").arg(comError);
+ }
+ if (FAILED(hr)) {
+ m_errorType = Phonon::FatalError;
+ setState(Phonon::ErrorState);
+ } else {
+ m_errorType = Phonon::NormalError;
+ m_nextState = Phonon::ErrorState;
+ }
+ } else {
+ m_errorType = Phonon::NoError;
+
+ }
+
+ return m_errorType == Phonon::FatalError;
+ }
+
+
+ void MediaObject::grabNode(BackendNode *node)
+ {
+ for (int i = 0; i < FILTER_COUNT; ++i) {
+ m_graphs[i]->grabNode(node);
+ }
+ node->setMediaObject(this);
+ }
+
+ bool MediaObject::connectNodes(BackendNode *source, BackendNode *sink)
+ {
+ bool ret = true;
+ for (int i = 0; i < FILTER_COUNT; ++i) {
+ ret = ret && m_graphs[i]->connectNodes(source, sink);
+ }
+ if (ret) {
+#ifndef QT_NO_PHONON_VIDEO
+ if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) {
+ m_videoWidgets += video;
+ } else
+#endif //QT_NO_PHONON_VIDEO
+ if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) {
+ m_audioOutputs += audio;
+ }
+ }
+ return ret;
+ }
+
+ bool MediaObject::disconnectNodes(BackendNode *source, BackendNode *sink)
+ {
+ bool ret = true;
+ for (int i = 0; i < FILTER_COUNT; ++i) {
+ ret = ret && m_graphs[i]->disconnectNodes(source, sink);
+ }
+ if (ret) {
+#ifndef QT_NO_PHONON_VIDEO
+ if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) {
+ m_videoWidgets.removeOne(video);
+ } else
+#endif //QT_NO_PHONON_VIDEO
+ if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) {
+ m_audioOutputs.removeOne(audio);
+ }
+ }
+ return ret;
+ }
+
+#ifndef QT_NO_PHONON_VIDEO
+ void MediaObject::updateVideoGeometry()
+ {
+ for (int i = 0; i < m_videoWidgets.count(); ++i) {
+ m_videoWidgets.at(i)->notifyVideoLoaded();
+ }
+ }
+#endif //QT_NO_PHONON_VIDEO
+
+ void MediaObject::handleComplete(IGraphBuilder *graph)
+ {
+ if (graph == currentGraph()->graph()) {
+ if (m_transitionTime >= PRELOAD_TIME || m_aboutToFinishSent == false) {
+ emit aboutToFinish(); //give a chance to the frontend to give a next source
+ m_aboutToFinishSent = true;
+ }
+
+ if (!m_nextSourceReadyToStart) {
+ //this is the last source, we simply finish
+ const qint64 current = currentTime();
+ const OAFilterState currentState = currentGraph()->syncGetRealState();
+
+ emit tick(current); //this ensures that the end of the seek slider is reached
+ emit finished();
+
+ if (currentTime() == current && currentGraph()->syncGetRealState() == currentState) {
+ //no seek operation in-between
+ pause();
+ setState(Phonon::PausedState); //we set it here
+ }
+
+ } else if (m_transitionTime == 0) {
+ //gapless transition
+ switchToNextSource(); //let's call the function immediately
+ } else if (m_transitionTime > 0) {
+ //management of the transition (if it is >= 0)
+ QTimer::singleShot(m_transitionTime, this, SLOT(switchToNextSource()));
+ }
+ } else {
+ //it is just the end of the previous source (in case of cross-fading)
+ nextGraph()->cleanup();
+ }
+ for (int i = 0; i < m_audioOutputs.count(); ++i) {
+ m_audioOutputs.at(i)->setCrossFadingProgress( currentGraph()->index(), 1.); //cross-fading is in any case finished
+ }
+ }
+
+ void MediaObject::finishLoading(quint16 workId, HRESULT hr, Graph graph)
+ {
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ m_graphs[i]->finishLoading(workId, hr, graph);
+ }
+ }
+
+ void MediaObject::finishSeeking(quint16 workId, qint64 time)
+ {
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ m_graphs[i]->finishSeeking(workId, time);
+ }
+ }
+
+
+ void MediaObject::handleEvents(Graph graph, long eventCode, long param1)
+ {
+ QString eventDescription;
+ switch (eventCode)
+ {
+ case EC_BUFFERING_DATA:
+ if (graph == currentGraph()->graph()) {
+ m_buffering = param1;
+ emit stateChanged(state(), m_state);
+ }
+ break;
+ case EC_LENGTH_CHANGED:
+ if (graph == currentGraph()->graph()) {
+ emit totalTimeChanged( totalTime() );
+ }
+ break;
+
+ case EC_COMPLETE:
+ handleComplete(graph);
+ break;
+
+#ifndef QT_NO_PHONON_VIDEO
+ case EC_VIDEO_SIZE_CHANGED:
+ if (graph == currentGraph()->graph()) {
+ updateVideoGeometry();
+ }
+ break;
+#endif //QT_NO_PHONON_VIDEO
+
+#ifdef GRAPH_DEBUG
+ case EC_ACTIVATE: qDebug() << "EC_ACTIVATE: A video window is being " << (param1 ? "ACTIVATED" : "DEACTIVATED"); break;
+ case EC_BUILT: qDebug() << "EC_BUILT: Send by the Video Control when a graph has been built. Not forwarded to applications."; break;
+ case EC_CLOCK_CHANGED: qDebug() << "EC_CLOCK_CHANGED"; break;
+ case EC_CLOCK_UNSET: qDebug() << "EC_CLOCK_UNSET: The clock provider was disconnected."; break;
+ case EC_CODECAPI_EVENT: qDebug() << "EC_CODECAPI_EVENT: Sent by an encoder to signal an encoding event."; break;
+ case EC_DEVICE_LOST: qDebug() << "EC_DEVICE_LOST: A Plug and Play device was removed or has become available again."; break;
+ case EC_DISPLAY_CHANGED: qDebug() << "EC_DISPLAY_CHANGED: The display mode has changed."; break;
+ case EC_END_OF_SEGMENT: qDebug() << "EC_END_OF_SEGMENT: The end of a segment has been reached."; break;
+ case EC_ERROR_STILLPLAYING: qDebug() << "EC_ERROR_STILLPLAYING: An asynchronous command to run the graph has failed."; break;
+ case EC_ERRORABORT: qDebug() << "EC_ERRORABORT: An operation was aborted because of an error."; break;
+ case EC_EXTDEVICE_MODE_CHANGE: qDebug() << "EC_EXTDEVICE_MODE_CHANGE: Not supported."; break;
+ case EC_FULLSCREEN_LOST: qDebug() << "EC_FULLSCREEN_LOST: The video renderer is switching out of full-screen mode."; break;
+ case EC_GRAPH_CHANGED: qDebug() << "EC_GRAPH_CHANGED: The filter graph has changed."; break;
+ case EC_NEED_RESTART: qDebug() << "EC_NEED_RESTART: A filter is requesting that the graph be restarted."; break;
+ case EC_NOTIFY_WINDOW: qDebug() << "EC_NOTIFY_WINDOW: Notifies a filter of the video renderer's window."; break;
+ case EC_OLE_EVENT: qDebug() << "EC_OLE_EVENT: A filter is passing a text string to the application."; break;
+ case EC_OPENING_FILE: qDebug() << "EC_OPENING_FILE: The graph is opening a file, or has finished opening a file."; break;
+ case EC_PALETTE_CHANGED: qDebug() << "EC_PALETTE_CHANGED: The video palette has changed."; break;
+ case EC_PAUSED: qDebug() << "EC_PAUSED: A pause request has completed."; break;
+ case EC_PREPROCESS_COMPLETE: qDebug() << "EC_PREPROCESS_COMPLETE: Sent by the WM ASF Writer filter when it completes the pre-processing for multipass encoding."; break;
+ case EC_QUALITY_CHANGE: qDebug() << "EC_QUALITY_CHANGE: The graph is dropping samples, for quality control."; break;
+ case EC_REPAINT: qDebug() << "EC_REPAINT: A video renderer requires a repaint."; break;
+ case EC_SEGMENT_STARTED: qDebug() << "EC_SEGMENT_STARTED: A new segment has started."; break;
+ case EC_SHUTTING_DOWN: qDebug() << "EC_SHUTTING_DOWN: The filter graph is shutting down, prior to being destroyed."; break;
+ case EC_SNDDEV_IN_ERROR: qDebug() << "EC_SNDDEV_IN_ERROR: A device error has occurred in an audio capture filter."; break;
+ case EC_SNDDEV_OUT_ERROR: qDebug() << "EC_SNDDEV_OUT_ERROR: A device error has occurred in an audio renderer filter."; break;
+ case EC_STARVATION: qDebug() << "EC_STARVATION: A filter is not receiving enough data."; break;
+ case EC_STATE_CHANGE: qDebug() << "EC_STATE_CHANGE: The filter graph has changed state."; break;
+ case EC_STEP_COMPLETE: qDebug() << "EC_STEP_COMPLETE: A filter performing frame stepping has stepped the specified number of frames."; break;
+ case EC_STREAM_CONTROL_STARTED: qDebug() << "EC_STREAM_CONTROL_STARTED: A stream-control start command has taken effect."; break;
+ case EC_STREAM_CONTROL_STOPPED: qDebug() << "EC_STREAM_CONTROL_STOPPED: A stream-control stop command has taken effect."; break;
+ case EC_STREAM_ERROR_STILLPLAYING: qDebug() << "EC_STREAM_ERROR_STILLPLAYING: An error has occurred in a stream. The stream is still playing."; break;
+ case EC_STREAM_ERROR_STOPPED: qDebug() << "EC_STREAM_ERROR_STOPPED: A stream has stopped because of an error."; break;
+ case EC_TIMECODE_AVAILABLE: qDebug() << "EC_TIMECODE_AVAILABLE: Not supported."; break;
+ case EC_UNBUILT: qDebug() << "Sent by the Video Control when a graph has been torn down. Not forwarded to applications."; break;
+ case EC_USERABORT: qDebug() << "EC_USERABORT: Send by the Video Control when a graph has been torn down. Not forwarded to applications."; break;
+ case EC_VMR_RECONNECTION_FAILED: qDebug() << "EC_VMR_RECONNECTION_FAILED: Sent by the VMR-7 and the VMR-9 when it was unable to accept a dynamic format change request from the upstream decoder."; break;
+ case EC_VMR_RENDERDEVICE_SET: qDebug() << "EC_VMR_RENDERDEVICE_SET: Sent when the VMR has selected its rendering mechanism."; break;
+ case EC_VMR_SURFACE_FLIPPED: qDebug() << "EC_VMR_SURFACE_FLIPPED: Sent when the VMR-7's allocator presenter has called the DirectDraw Flip method on the surface being presented."; break;
+ case EC_WINDOW_DESTROYED: qDebug() << "EC_WINDOW_DESTROYED: The video renderer was destroyed or removed from the graph"; break;
+ case EC_WMT_EVENT: qDebug() << "EC_WMT_EVENT: Sent by the Windows Media Format SDK when an application uses the ASF Reader filter to play ASF files protected by digital rights management (DRM)."; break;
+ case EC_WMT_INDEX_EVENT: qDebug() << "EC_WMT_INDEX_EVENT: Sent by the Windows Media Format SDK when an application uses the ASF Writer to index Windows Media Video files."; break;
+
+ //documented by Microsoft but not supported in the Platform SDK
+ // case EC_BANDWIDTHCHANGE : qDebug() << "EC_BANDWIDTHCHANGE: not supported"; break;
+ // case EC_CONTENTPROPERTY_CHANGED: qDebug() << "EC_CONTENTPROPERTY_CHANGED: not supported."; break;
+ // case EC_EOS_SOON: qDebug() << "EC_EOS_SOON: not supported"; break;
+ // case EC_ERRORABORTEX: qDebug() << "EC_ERRORABORTEX: An operation was aborted because of an error."; break;
+ // case EC_FILE_CLOSED: qDebug() << "EC_FILE_CLOSED: The source file was closed because of an unexpected event."; break;
+ // case EC_LOADSTATUS: qDebug() << "EC_LOADSTATUS: Notifies the application of progress when opening a network file."; break;
+ // case EC_MARKER_HIT: qDebug() << "EC_MARKER_HIT: not supported."; break;
+ // case EC_NEW_PIN: qDebug() << "EC_NEW_PIN: not supported."; break;
+ // case EC_PLEASE_REOPEN: qDebug() << "EC_PLEASE_REOPEN: The source file has changed."; break;
+ // case EC_PROCESSING_LATENCY: qDebug() << "EC_PROCESSING_LATENCY: Indicates the amount of time that a component is taking to process each sample."; break;
+ // case EC_RENDER_FINISHED: qDebug() << "EC_RENDER_FINISHED: Not supported."; break;
+ // case EC_SAMPLE_LATENCY: qDebug() << "EC_SAMPLE_LATENCY: Specifies how far behind schedule a component is for processing samples."; break;
+ // case EC_SAMPLE_NEEDED: qDebug() << "EC_SAMPLE_NEEDED: Requests a new input sample from the Enhanced Video Renderer (EVR) filter."; break;
+ // case EC_SCRUB_TIME: qDebug() << "EC_SCRUB_TIME: Specifies the time stamp for the most recent frame step."; break;
+ // case EC_STATUS: qDebug() << "EC_STATUS: Contains two arbitrary status strings."; break;
+ // case EC_VIDEOFRAMEREADY: qDebug() << "EC_VIDEOFRAMEREADY: A video frame is ready for display."; break;
+
+ default:
+ qDebug() << "Unknown event" << eventCode << "(" << param1 << ")";
+ break;
+#else
+ default:
+ break;
+#endif
+ }
+ }
+
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ //interface management
+ bool MediaObject::hasInterface(Interface iface) const
+ {
+ return iface == AddonInterface::TitleInterface;
+ }
+
+ QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> &params)
+ {
+ if (hasInterface(iface)) {
+
+ switch (iface)
+ {
+ case TitleInterface:
+ switch (command)
+ {
+ case availableTitles:
+ return _iface_availableTitles();
+ case title:
+ return _iface_currentTitle();
+ case setTitle:
+ _iface_setCurrentTitle(params.first().toInt());
+ break;
+ case autoplayTitles:
+ return m_autoplayTitles;
+ case setAutoplayTitles:
+ m_autoplayTitles = params.first().toBool();
+ updateStopPosition();
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QVariant();
+ }
+
+
+ //TitleInterface
+
+ //this is called to set the time for the different titles
+ qint64 MediaObject::titleAbsolutePosition(int title) const
+ {
+ if (title >= 0 && title < m_titles.count()) {
+ return m_titles.at(title);
+ } else {
+ return 0;
+ }
+ }
+
+ void MediaObject::setTitles(const QList<qint64> &titles)
+ {
+ //this is called when the source is loaded
+ const bool emitSignal = m_titles.count() != titles.count();
+ m_titles = titles;
+ if (emitSignal) {
+ emit availableTitlesChanged(titles.count());
+ }
+ updateStopPosition();
+ }
+
+
+ int MediaObject::_iface_availableTitles() const
+ {
+ return m_titles.count() - 1;
+ }
+
+ int MediaObject::_iface_currentTitle() const
+ {
+ return m_currentTitle;
+ }
+
+ void MediaObject::_iface_setCurrentTitle(int title, bool bseek)
+ {
+#ifdef GRAPH_DEBUG
+ qDebug() << "_iface_setCurrentTitle" << title;
+#endif
+ const int oldTitle = m_currentTitle;
+ m_currentTitle = title;
+ updateStopPosition();
+ if (bseek) {
+ //let's seek to the beginning of the song
+ seek(0);
+ } else {
+ updateTargetTick();
+ }
+ if (oldTitle != title) {
+ emit titleChanged(title);
+ emit totalTimeChanged(totalTime());
+ }
+
+ }
+
+ void MediaObject::updateStopPosition()
+ {
+ if (!m_autoplayTitles && m_currentTitle < _iface_availableTitles() - 1) {
+ //stop position is set to the end of the track
+ currentGraph()->setStopPosition(titleAbsolutePosition(m_currentTitle+1));
+ } else {
+ //stop position is set to the end
+ currentGraph()->setStopPosition(-1);
+ }
+ }
+#endif //QT_NO_PHONON_QT_NO_PHONON_MEDIACONTROLLER
+
+ void MediaObject::switchFilters(int index, Filter oldFilter, Filter newFilter)
+ {
+ if (currentGraph()->index() == index) {
+ currentGraph()->switchFilters(oldFilter, newFilter);
+ } else {
+ nextGraph()->switchFilters(oldFilter, newFilter);
+ }
+
+ }
+
+
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_mediaobject.cpp"
diff --git a/src/3rdparty/phonon/ds9/mediaobject.h b/src/3rdparty/phonon/ds9/mediaobject.h
new file mode 100644
index 0000000..34aa666
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/mediaobject.h
@@ -0,0 +1,313 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_MEDIAOBJECT_H
+#define PHONON_MEDIAOBJECT_H
+
+#include <phonon/mediaobjectinterface.h>
+#include <phonon/addoninterface.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QObject>
+#include <QtCore/QQueue>
+#include <QtCore/QBasicTimer>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+
+#include "backendnode.h"
+#include "mediagraph.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class MediaSource;
+
+ namespace DS9
+ {
+ class VideoWidget;
+ class AudioOutput;
+
+ class QWinWaitCondition
+ {
+ public:
+ QWinWaitCondition() : m_handle(::CreateEvent(0,0,0,0))
+ {
+ }
+
+ ~QWinWaitCondition()
+ {
+ ::CloseHandle(m_handle);
+ }
+
+ void reset()
+ {
+ //will block
+ ::ResetEvent(m_handle);
+ }
+
+ void set()
+ {
+ //will unblock
+ ::SetEvent(m_handle);
+ }
+
+ operator HANDLE()
+ {
+ return m_handle;
+ }
+
+ operator HEVENT()
+ {
+ return reinterpret_cast<HEVENT>(m_handle);
+ }
+
+
+ private:
+ HANDLE m_handle;
+ };
+
+ class WorkerThread : public QThread
+ {
+ Q_OBJECT
+ public:
+ WorkerThread();
+ ~WorkerThread();
+
+ virtual void run();
+
+ //wants to know as soon as the state is set
+ void addStateChangeRequest(Graph graph, OAFilterState, QList<Filter> = QList<Filter>());
+
+ quint16 addSeekRequest(Graph graph, qint64 time);
+ quint16 addUrlToRender(const QString &url);
+ quint16 addFilterToRender(const Filter &filter);
+
+ void replaceGraphForEventManagement(Graph newGraph, Graph oldGraph);
+
+ void abortCurrentRender(qint16 renderId);
+
+ //tells the thread to stop processing
+ void signalStop();
+
+ Q_SIGNALS:
+ void asyncRenderFinished(quint16, HRESULT, Graph);
+ void asyncSeekingFinished(quint16, qint64);
+ void stateReady(Graph, Phonon::State);
+ void eventReady(Graph, long eventCode, long param1);
+
+ private:
+
+ enum Task
+ {
+ None,
+ Render,
+ Seek,
+ ChangeState,
+ ReplaceGraph //just updates recalls WaitForMultipleObject
+ };
+
+ struct Work
+ {
+ Work() : task(None), id(0), time(0) { }
+ Task task;
+ quint16 id;
+ Graph graph;
+ Graph oldGraph;
+ Filter filter;
+ QString url;
+ union
+ {
+ qint64 time;
+ OAFilterState state;
+ };
+ QList<Filter> decoders; //for the state change requests
+ };
+ void handleTask();
+
+ Work m_currentWork;
+ QQueue<Work> m_queue;
+ bool m_finished;
+ quint16 m_currentWorkId;
+ QWinWaitCondition m_waitCondition;
+ QMutex m_mutex; // mutex for the m_queue, m_finished and m_currentWorkId
+
+ //this is for WaitForMultipleObjects
+ struct
+ {
+ Graph graph;
+ HANDLE handle;
+ } m_graphHandle[FILTER_COUNT];
+ };
+
+
+ class MediaObject : public BackendNode, public Phonon::MediaObjectInterface
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ , public Phonon::AddonInterface
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ {
+ friend class Stream;
+ Q_OBJECT
+ Q_INTERFACES(Phonon::MediaObjectInterface
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ Phonon::AddonInterface
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ )
+ public:
+ MediaObject(QObject *parent);
+ ~MediaObject();
+ Phonon::State state() const;
+ bool hasVideo() const;
+ bool isSeekable() const;
+ qint64 currentTime() const;
+ qint32 tickInterval() const;
+
+ void setTickInterval(qint32 newTickInterval);
+ void play();
+ void pause();
+ void stop();
+ void ensureStopped();
+ void seek(qint64 time);
+
+ QString errorString() const;
+ Phonon::ErrorType errorType() const;
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ bool hasInterface(Interface) const;
+ QVariant interfaceCall(Interface iface, int command, const QList<QVariant> &params);
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+ qint64 totalTime() const;
+ qint32 prefinishMark() const;
+ void setPrefinishMark(qint32 newPrefinishMark);
+
+ qint32 transitionTime() const;
+ void setTransitionTime(qint32);
+
+ qint64 remainingTime() const;
+
+ MediaSource source() const;
+ void setSource(const MediaSource &source);
+ void setNextSource(const MediaSource &source);
+
+
+ //COM error management
+ bool catchComError(HRESULT hr);
+
+ void grabNode(BackendNode *node);
+ bool connectNodes(BackendNode *source, BackendNode *sink);
+ bool disconnectNodes(BackendNode *source, BackendNode *sink);
+
+ void switchFilters(int index, Filter oldFilter, Filter newFilter);
+
+ WorkerThread *workerThread();
+ void loadingFinished(MediaGraph *mg);
+ void seekingFinished(MediaGraph *mg);
+ MediaGraph *currentGraph() const;
+
+ //this is used by the backend only
+ Phonon::State transactionState;
+
+ private Q_SLOTS:
+ void switchToNextSource();
+ void slotStateReady(Graph, Phonon::State);
+ void handleEvents(Graph, long eventCode, long param1);
+ void finishLoading(quint16 workId, HRESULT hr, Graph);
+ void finishSeeking(quint16 workId, qint64 time);
+
+ Q_SIGNALS:
+ void stateChanged(Phonon::State newstate, Phonon::State oldstate);
+ void tick(qint64 time);
+ void metaDataChanged(QMultiMap<QString, QString>);
+ void seekableChanged(bool);
+ void hasVideoChanged(bool);
+ void bufferStatus(int);
+
+ // AddonInterface:
+ void titleChanged(int);
+ void availableTitlesChanged(int);
+ void chapterChanged(int);
+ void availableChaptersChanged(int);
+ void angleChanged(int);
+ void availableAnglesChanged(int);
+
+ void finished();
+ void prefinishMarkReached(qint32);
+ void aboutToFinish();
+ void totalTimeChanged(qint64 length) const;
+ void currentSourceChanged(const MediaSource &);
+
+ protected:
+ void setState(Phonon::State);
+ void timerEvent(QTimerEvent *e);
+
+ private:
+#ifndef QT_NO_PHONON_VIDEO
+ void updateVideoGeometry();
+#endif // QT_NO_PHONON_VIDEO
+ void handleComplete(IGraphBuilder *graph);
+ MediaGraph *nextGraph() const;
+
+ void updateTargetTick();
+ void updateStopPosition();
+
+ mutable QString m_errorString;
+ mutable Phonon::ErrorType m_errorType;
+
+ Phonon::State m_state;
+ Phonon::State m_nextState;
+ qint32 m_transitionTime;
+
+ qint32 m_prefinishMark;
+
+ QBasicTimer m_tickTimer;
+ qint32 m_tickInterval;
+
+ //the graph(s)
+ MediaGraph* m_graphs[FILTER_COUNT];
+
+ //...the videowidgets in the graph
+ QList<VideoWidget*> m_videoWidgets;
+ QList<AudioOutput*> m_audioOutputs;
+
+ bool m_buffering:1;
+ bool m_oldHasVideo:1;
+ bool m_prefinishMarkSent:1;
+ bool m_aboutToFinishSent:1;
+ bool m_nextSourceReadyToStart:1;
+
+ //for TitleInterface (and commands)
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ bool m_autoplayTitles:1;
+ QList<qint64> m_titles;
+ int m_currentTitle;
+ int _iface_availableTitles() const;
+ int _iface_currentTitle() const;
+ void _iface_setCurrentTitle(int title, bool bseek = true);
+ void setTitles(const QList<qint64> &titles);
+ qint64 titleAbsolutePosition(int title) const;
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+ qint64 m_targetTick;
+
+ WorkerThread m_thread;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_MEDIAOBJECT_H
diff --git a/src/3rdparty/phonon/ds9/phononds9_namespace.h b/src/3rdparty/phonon/ds9/phononds9_namespace.h
new file mode 100644
index 0000000..e972d41
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/phononds9_namespace.h
@@ -0,0 +1,33 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_DS9_NAMESPACE_H
+#define PHONON_DS9_NAMESPACE_H
+
+#include <QtCore/qnamespace.h>
+
+#define FILTER_COUNT 2 //number of ds9 filters per object
+
+#ifndef QT_BEGIN_NAMESPACE
+#define QT_BEGIN_NAMESPACE
+#endif
+
+#ifndef QT_END_NAMESPACE
+#define QT_END_NAMESPACE
+#endif
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/qasyncreader.cpp b/src/3rdparty/phonon/ds9/qasyncreader.cpp
new file mode 100644
index 0000000..a3f9cda
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qasyncreader.cpp
@@ -0,0 +1,186 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "qasyncreader.h"
+#include "qbasefilter.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ QAsyncReader::QAsyncReader(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mediaTypes) : QPin(parent, PINDIR_OUTPUT, mediaTypes)
+ {
+ }
+
+ QAsyncReader::~QAsyncReader()
+ {
+ }
+
+ STDMETHODIMP QAsyncReader::QueryInterface(REFIID iid, void **out)
+ {
+ if (!out) {
+ return E_POINTER;
+ }
+
+ if (iid == IID_IAsyncReader) {
+ AddRef();
+ *out = static_cast<IAsyncReader*>(this);
+ return S_OK;
+ }
+
+ return QPin::QueryInterface(iid, out);
+ }
+
+ STDMETHODIMP_(ULONG) QAsyncReader::AddRef()
+ {
+ return QPin::AddRef();
+ }
+
+ STDMETHODIMP_(ULONG) QAsyncReader::Release()
+ {
+ return QPin::Release();
+ }
+
+
+ STDMETHODIMP QAsyncReader::RequestAllocator(IMemAllocator *preferred, ALLOCATOR_PROPERTIES *prop,IMemAllocator **actual)
+ {
+ ALLOCATOR_PROPERTIES prop2;
+
+ if (prop->cbAlign == 0) {
+ prop->cbAlign = 1; //align on 1 char
+ }
+
+ if (preferred && preferred->SetProperties(prop, &prop2) == S_OK) {
+ preferred->AddRef();
+ *actual = preferred;
+ return S_OK;
+ }
+
+ //we should try to create one memory allocator ourselves here
+ return E_FAIL;
+ }
+
+ STDMETHODIMP QAsyncReader::Request(IMediaSample *sample,DWORD_PTR user)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_flushing) {
+ return VFW_E_WRONG_STATE;
+ }
+
+ m_requestQueue.enqueue(AsyncRequest(sample, user));
+ m_requestWait.wakeOne();
+ return S_OK;
+ }
+
+ STDMETHODIMP QAsyncReader::WaitForNext(DWORD timeout, IMediaSample **sample, DWORD_PTR *user)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!sample ||!user) {
+ return E_POINTER;
+ }
+
+ //msdn says to return immediately if we're flushing but that doesn't seem to be true
+ //since it triggers a dead-lock somewhere inside directshow (see task 258830)
+
+ *sample = 0;
+ *user = 0;
+
+ if (m_requestQueue.isEmpty()) {
+ if (m_requestWait.wait(&m_mutex, timeout) == false) {
+ return VFW_E_TIMEOUT;
+ }
+ if (m_requestQueue.isEmpty()) {
+ return VFW_E_WRONG_STATE;
+ }
+ }
+
+ AsyncRequest r = m_requestQueue.dequeue();
+
+ //at this point we're sure to have a request to proceed
+ if (r.sample == 0) {
+ return E_FAIL;
+ }
+
+ *sample = r.sample;
+ *user = r.user;
+ return syncReadAlignedUnlocked(r.sample);
+ }
+
+ STDMETHODIMP QAsyncReader::BeginFlush()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_flushing = true;
+ m_requestWait.wakeOne();
+ return S_OK;
+ }
+
+ STDMETHODIMP QAsyncReader::EndFlush()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_flushing = false;
+ return S_OK;
+ }
+
+ STDMETHODIMP QAsyncReader::SyncReadAligned(IMediaSample *sample)
+ {
+ QMutexLocker locker(&m_mutex);
+ return syncReadAlignedUnlocked(sample);
+ }
+
+ STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer)
+ {
+ QMutexLocker locker(&m_mutex);
+ return read(pos, length, buffer, 0);
+ }
+
+
+ STDMETHODIMP QAsyncReader::syncReadAlignedUnlocked(IMediaSample *sample)
+ {
+ Q_ASSERT(!m_mutex.tryLock());
+
+ if (!sample) {
+ return E_POINTER;
+ }
+
+ REFERENCE_TIME start = 0,
+ stop = 0;
+ HRESULT hr = sample->GetTime(&start, &stop);
+ if(FAILED(hr)) {
+ return hr;
+ }
+
+ LONGLONG startPos = start / 10000000;
+ LONG length = static_cast<LONG>((stop - start) / 10000000);
+
+ BYTE *buffer;
+ hr = sample->GetPointer(&buffer);
+ if(FAILED(hr)) {
+ return hr;
+ }
+
+ LONG actual = 0;
+ read(startPos, length, buffer, &actual);
+
+ return sample->SetActualDataLength(actual);
+ }
+
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/qasyncreader.h b/src/3rdparty/phonon/ds9/qasyncreader.h
new file mode 100644
index 0000000..95872f9
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qasyncreader.h
@@ -0,0 +1,75 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_QASYNCREADER_H
+#define PHONON_QASYNCREADER_H
+
+#include <QtCore/QWaitCondition>
+#include <QtCore/QQueue>
+#include <QtCore/QMutex>
+
+#include "qpin.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ //his class reads asynchronously from a QIODevice
+ class QAsyncReader : public QPin, public IAsyncReader
+ {
+ public:
+ QAsyncReader(QBaseFilter *, const QVector<AM_MEDIA_TYPE> &mediaTypes);
+ ~QAsyncReader();
+
+ //reimplementation from IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void** out);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ //reimplementation from IAsyncReader
+ STDMETHODIMP RequestAllocator(IMemAllocator *,ALLOCATOR_PROPERTIES *,IMemAllocator **);
+ STDMETHODIMP Request(IMediaSample *,DWORD_PTR);
+ STDMETHODIMP WaitForNext(DWORD,IMediaSample **,DWORD_PTR *);
+ STDMETHODIMP SyncReadAligned(IMediaSample *);
+ STDMETHODIMP SyncRead(LONGLONG,LONG,BYTE *);
+ STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0;
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
+
+ protected:
+ STDMETHODIMP syncReadAlignedUnlocked(IMediaSample *);
+ virtual HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual) = 0;
+
+ private:
+ struct AsyncRequest
+ {
+ AsyncRequest(IMediaSample *s = 0, DWORD_PTR u = 0) : sample(s), user(u) {}
+ IMediaSample *sample;
+ DWORD_PTR user;
+ };
+
+ QQueue<AsyncRequest> m_requestQueue;
+ QWaitCondition m_requestWait;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp
new file mode 100644
index 0000000..6d0f335
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp
@@ -0,0 +1,312 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "qaudiocdreader.h"
+#include <dshow.h>
+#include <initguid.h>
+
+#include <winioctl.h> // needed for FILE_DEVICE_CD_ROM etc
+
+#define IOCTL_CDROM_READ_TOC CTL_CODE(FILE_DEVICE_CD_ROM, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
+#define IOCTL_CDROM_RAW_READ CTL_CODE(FILE_DEVICE_CD_ROM, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS)
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ // {CA46BFE1-D55B-4adf-B803-BC2B9AD57824}
+ DEFINE_GUID(IID_ITitleInterface,
+ 0xca46bfe1, 0xd55b, 0x4adf, 0xb8, 0x3, 0xbc, 0x2b, 0x9a, 0xd5, 0x78, 0x24);
+
+ struct TRACK_DATA {
+ UCHAR Reserved;
+ UCHAR Control : 4;
+ UCHAR Adr : 4;
+ UCHAR TrackNumber;
+ UCHAR Reserved1;
+ UCHAR Address[4];
+ };
+
+ struct CDROM_TOC {
+ UCHAR Length[2];
+ UCHAR FirstTrack;
+ UCHAR LastTrack;
+ TRACK_DATA TrackData[100];
+ };
+
+ struct WaveStructure
+ {
+ WaveStructure();
+
+ char riff[4];
+ qint32 chunksize;
+ char wave[4];
+ char fmt[4];
+ const qint32 chunksize2;
+ const quint16 formatTag;
+ const quint16 nChannels;
+ const quint32 nSamplesPerSec;
+ const quint32 nAvgBytesPerSec;
+ const quint16 nBlockAlign;
+ const quint16 bitsPerSample;
+ char data[4];
+ qint32 dataLength;
+ };
+
+ enum TRACK_MODE_TYPE {
+ YellowMode2,
+ XAForm2,
+ CDDA
+ };
+
+
+ struct RAW_READ_INFO {
+ LARGE_INTEGER DiskOffset;
+ ULONG SectorCount;
+ TRACK_MODE_TYPE TrackMode;
+ };
+
+ class QAudioCDReader : public QAsyncReader, public ITitleInterface
+ {
+ public:
+ QAudioCDReader(QBaseFilter *parent, QChar drive = QChar());
+ ~QAudioCDReader();
+
+ //reimplementation from IUnknown
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ STDMETHODIMP Length(LONGLONG *,LONGLONG *);
+ STDMETHODIMP QueryInterface(REFIID iid, void** out);
+ QList<qint64> titles() const;
+
+ protected:
+ HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual);
+
+ private:
+ HANDLE m_cddrive;
+ CDROM_TOC m_toc;
+ WaveStructure m_waveHeader;
+ qint64 m_trackAddress;
+ };
+
+
+#define SECTOR_SIZE 2352
+#define NB_SECTORS_READ 20
+
+ static const AM_MEDIA_TYPE audioCDMediaType = { MEDIATYPE_Stream, MEDIASUBTYPE_WAVE, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
+
+ int addressToSectors(UCHAR address[4])
+ {
+ return ((address[0] * 60 + address[1]) * 60 + address[2]) * 75 + address[3] - 150;
+ }
+
+ WaveStructure::WaveStructure() : chunksize(0), chunksize2(16),
+ formatTag(WAVE_FORMAT_PCM), nChannels(2), nSamplesPerSec(44100), nAvgBytesPerSec(176400), nBlockAlign(4), bitsPerSample(16),
+ dataLength(0)
+ {
+ qMemCopy(riff, "RIFF", 4);
+ qMemCopy(wave, "WAVE", 4);
+ qMemCopy(fmt, "fmt ", 4);
+ qMemCopy(data, "data", 4);
+ }
+
+
+ QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector<AM_MEDIA_TYPE>() << audioCDMediaType)
+ {
+ //now open the cd-drive
+ QString path;
+ if (drive.isNull()) {
+ path = QString::fromLatin1("\\\\.\\Cdrom0");
+ } else {
+ path = QString::fromLatin1("\\\\.\\%1:").arg(drive);
+ }
+
+ m_cddrive = ::CreateFile((const wchar_t *)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+
+ qMemSet(&m_toc, 0, sizeof(CDROM_TOC));
+ //read the TOC
+ DWORD bytesRead = 0;
+ bool tocRead = ::DeviceIoControl(m_cddrive, IOCTL_CDROM_READ_TOC, 0, 0, &m_toc, sizeof(CDROM_TOC), &bytesRead, 0);
+
+ if (!tocRead) {
+ qWarning("unable to load the TOC from the CD");
+ return;
+ }
+
+ m_trackAddress = addressToSectors(m_toc.TrackData[0].Address);
+ const qint32 nbSectorsToRead = (addressToSectors(m_toc.TrackData[m_toc.LastTrack + 1 - m_toc.FirstTrack].Address)
+ - m_trackAddress);
+ const qint32 dataLength = nbSectorsToRead * SECTOR_SIZE;
+
+ m_waveHeader.chunksize = 4 + (8 + m_waveHeader.chunksize2) + (8 + dataLength);
+ m_waveHeader.dataLength = dataLength;
+ }
+
+ QAudioCDReader::~QAudioCDReader()
+ {
+ ::CloseHandle(m_cddrive);
+ }
+
+ STDMETHODIMP_(ULONG) QAudioCDReader::AddRef()
+ {
+ return QAsyncReader::AddRef();
+ }
+
+ STDMETHODIMP_(ULONG) QAudioCDReader::Release()
+ {
+ return QAsyncReader::Release();
+ }
+
+
+ STDMETHODIMP QAudioCDReader::Length(LONGLONG *total,LONGLONG *available)
+ {
+ const LONGLONG length = sizeof(WaveStructure) + m_waveHeader.dataLength;
+ if (total) {
+ *total = length;
+ }
+ if (available) {
+ *available = length;
+ }
+
+ return S_OK;
+ }
+
+ STDMETHODIMP QAudioCDReader::QueryInterface(REFIID iid, void** out)
+ {
+ if (!out) {
+ return E_POINTER;
+ }
+
+ if (iid == IID_ITitleInterface) {
+ //we reroute that to the pin
+ *out = static_cast<ITitleInterface*>(this);
+ AddRef();
+ return S_OK;
+ } else {
+ return QAsyncReader::QueryInterface(iid, out);
+ }
+ }
+
+
+ HRESULT QAudioCDReader::read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual)
+ {
+ LONG nbRead = 0;
+
+ if (actual) {
+ *actual = 0;
+ }
+
+ if (pos < sizeof(WaveStructure)) {
+ //we first copy the content of the structure
+ nbRead = qMin(LONG(sizeof(WaveStructure) - pos), length);
+ qMemCopy(buffer, reinterpret_cast<char*>(&m_waveHeader) + pos, nbRead);
+ }
+
+ const LONGLONG posInTrack = pos - sizeof(WaveStructure) + nbRead;
+ const int bytesLeft = qMin(m_waveHeader.dataLength - posInTrack, LONGLONG(length - nbRead));
+
+ if (bytesLeft > 0) {
+
+ //we need to read again
+
+ const int surplus = posInTrack % SECTOR_SIZE; //how many bytes too much at the beginning
+ const int firstSector = posInTrack / SECTOR_SIZE,
+ lastSector = (posInTrack + length - 1) / SECTOR_SIZE;
+ const int sectorsNeeded = lastSector - firstSector + 1;
+ int sectorsRead = 0;
+
+ QByteArray ba(sectorsNeeded * SECTOR_SIZE, 0);
+
+
+ RAW_READ_INFO ReadInfo;
+ ReadInfo.TrackMode = CDDA; // Always use CDDA (numerical: 2)
+ ReadInfo.DiskOffset.QuadPart = (m_trackAddress + firstSector) * 2048;
+ ReadInfo.SectorCount = qMin(sectorsNeeded - sectorsRead, NB_SECTORS_READ);
+ while (ReadInfo.SectorCount) {
+ DWORD dummy = 0;
+ if (::DeviceIoControl( m_cddrive, IOCTL_CDROM_RAW_READ,
+ &ReadInfo, sizeof(ReadInfo),
+ ba.data() + sectorsRead * SECTOR_SIZE,
+ ReadInfo.SectorCount * SECTOR_SIZE,
+ &dummy, NULL ) )
+ {
+ ReadInfo.DiskOffset.QuadPart += ReadInfo.SectorCount * 2048;
+ sectorsRead += ReadInfo.SectorCount;
+ ReadInfo.SectorCount = qMin(sectorsNeeded - sectorsRead, NB_SECTORS_READ);
+ }else {
+ qWarning("an error occurred while reading from the media");
+ return S_FALSE;
+ }
+
+ }
+
+ //consume bytes on the buffer
+ qMemCopy(buffer + nbRead, ba.data() + surplus, bytesLeft);
+
+ //at this point we have all we need in the buffer
+ nbRead += bytesLeft;
+ }
+
+ if (actual) {
+ *actual = nbRead;
+ }
+
+ return nbRead == length ? S_OK : S_FALSE;
+ }
+
+ QList<qint64> QAudioCDReader::titles() const
+ {
+ QList<qint64> ret;
+ ret << 0;
+ for(int i = m_toc.FirstTrack; i <= m_toc.LastTrack ; ++i) {
+ const uchar *address = m_toc.TrackData[i].Address;
+ ret << ((address[0] * 60 + address[1]) * 60 + address[2]) * 1000 + address[3]*1000/75 - 2000;
+
+ }
+ return ret;
+ }
+
+
+ QAudioCDPlayer::QAudioCDPlayer() : QBaseFilter(CLSID_NULL)
+ {
+ new QAudioCDReader(this);
+ }
+
+ QAudioCDPlayer::~QAudioCDPlayer()
+ {
+ }
+
+ STDMETHODIMP QAudioCDPlayer::QueryInterface(REFIID iid, void** out)
+ {
+ if (iid == IID_ITitleInterface) {
+ //we reroute that to the pin
+ return pins().first()->QueryInterface(iid, out);
+ } else {
+ return QBaseFilter::QueryInterface(iid, out);
+ }
+ }
+ }
+}
+
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.h b/src/3rdparty/phonon/ds9/qaudiocdreader.h
new file mode 100644
index 0000000..eff845d
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qaudiocdreader.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_QAUDIOCDREADER_H
+#define PHONON_QAUDIOCDREADER_H
+
+#include "qasyncreader.h"
+#include "qbasefilter.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ struct CDROM_TOC;
+ struct WaveStructure;
+ EXTERN_C const IID IID_ITitleInterface;
+
+ //interface for the Titles
+ struct ITitleInterface : public IUnknown
+ {
+ virtual QList<qint64> titles() const = 0;
+ };
+
+
+ class QAudioCDPlayer : public QBaseFilter
+ {
+ public:
+ QAudioCDPlayer();
+ ~QAudioCDPlayer();
+ STDMETHODIMP QueryInterface(REFIID iid, void** out);
+ };
+
+ }
+}
+
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/qbasefilter.cpp b/src/3rdparty/phonon/ds9/qbasefilter.cpp
new file mode 100644
index 0000000..78b8b8f
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qbasefilter.cpp
@@ -0,0 +1,832 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "qbasefilter.h"
+#include "qpin.h"
+
+#include <QtCore/QMutex>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+
+ class QEnumPins : public IEnumPins
+ {
+ public:
+ QEnumPins(QBaseFilter *filter) : m_refCount(1),
+ m_filter(filter), m_pins(filter->pins()), m_index(0)
+ {
+ m_filter->AddRef();
+ }
+
+ virtual ~QEnumPins()
+ {
+ m_filter->Release();
+ }
+
+ STDMETHODIMP QueryInterface(const IID &iid,void **out)
+ {
+ if (!out) {
+ return E_POINTER;
+ }
+
+ HRESULT hr = S_OK;
+ if (iid == IID_IEnumPins) {
+ *out = static_cast<IEnumPins*>(this);
+ } else if (iid == IID_IUnknown) {
+ *out = static_cast<IUnknown*>(this);
+ } else {
+ *out = 0;
+ hr = E_NOINTERFACE;
+ }
+
+ if (S_OK)
+ AddRef();
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_refCount);
+ }
+
+ STDMETHODIMP_(ULONG) Release()
+ {
+ ULONG refCount = InterlockedDecrement(&m_refCount);
+ if (refCount == 0) {
+ delete this;
+ }
+
+ return refCount;
+ }
+
+ STDMETHODIMP Next(ULONG count,IPin **ret,ULONG *fetched)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_filter->pins() != m_pins) {
+ return VFW_E_ENUM_OUT_OF_SYNC;
+ }
+
+ if (fetched == 0 && count > 1) {
+ return E_INVALIDARG;
+ }
+
+ if (!ret) {
+ return E_POINTER;
+ }
+
+ uint nbfetched = 0;
+ while (nbfetched < count && m_index < m_pins.count()) {
+ IPin *current = m_pins[m_index];
+ current->AddRef();
+ ret[nbfetched] = current;
+ nbfetched++;
+ m_index++;
+ }
+
+ if (fetched) {
+ *fetched = nbfetched;
+ }
+
+ return nbfetched == count ? S_OK : S_FALSE;
+ }
+
+ STDMETHODIMP Skip(ULONG count)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_filter->pins() != m_pins) {
+ return VFW_E_ENUM_OUT_OF_SYNC;
+ }
+
+ m_index = qMin(m_index + int(count), m_pins.count());
+ return m_index == m_pins.count() ? S_FALSE : S_OK;
+ }
+
+ STDMETHODIMP Reset()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_index = 0;
+ return S_OK;
+ }
+
+ STDMETHODIMP Clone(IEnumPins **out)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_filter->pins() != m_pins) {
+ return VFW_E_ENUM_OUT_OF_SYNC;
+ }
+
+ if (!out) {
+ return E_POINTER;
+ }
+
+ *out = new QEnumPins(m_filter);
+ (*out)->Skip(m_index);
+ return S_OK;
+ }
+
+
+ private:
+ LONG m_refCount;
+ QBaseFilter *m_filter;
+ QList<QPin*> m_pins;
+ int m_index;
+ QMutex m_mutex;
+ };
+
+
+ QBaseFilter::QBaseFilter(const CLSID &clsid):
+ m_refCount(1), m_clsid(clsid), m_clock(0), m_graph(0), m_state(State_Stopped)
+ {
+ }
+
+ QBaseFilter::~QBaseFilter()
+ {
+ while (!m_pins.isEmpty()) {
+ delete m_pins.first();
+ }
+ }
+
+ const QList<QPin *> QBaseFilter::pins() const
+ {
+ QMutexLocker locker(&m_mutex);
+ return m_pins;
+ }
+
+ void QBaseFilter::addPin(QPin *pin)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_pins.append(pin);
+ }
+
+ void QBaseFilter::removePin(QPin *pin)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_pins.removeAll(pin);
+ }
+
+ FILTER_STATE QBaseFilter::state() const
+ {
+ return m_state;
+ }
+
+ IFilterGraph *QBaseFilter::graph() const
+ {
+ return m_graph;
+ }
+
+ STDMETHODIMP QBaseFilter::QueryInterface(REFIID iid, void **out)
+ {
+ if (!out) {
+ return E_POINTER;
+ }
+
+ HRESULT hr = S_OK;
+
+ if (iid == IID_IBaseFilter) {
+ *out = static_cast<IBaseFilter*>(this);
+ } else if (iid == IID_IMediaFilter) {
+ *out = static_cast<IMediaFilter*>(this);
+ } else if (iid == IID_IPersist) {
+ *out = static_cast<IPersist*>(this);
+ } else if (iid == IID_IUnknown) {
+ *out = static_cast<IUnknown*>(static_cast<IBaseFilter*>(this));
+ }
+ else if (iid == IID_IMediaPosition || iid == IID_IMediaSeeking) {
+ if (inputPins().isEmpty()) {
+ *out = getUpStreamInterface(iid);
+ if (*out) {
+ return S_OK; //we return here to avoid adding a reference
+ } else {
+ hr = E_NOINTERFACE;
+ }
+ } else if (iid == IID_IMediaSeeking) {
+ *out = static_cast<IMediaSeeking*>(this);
+ } else if (iid == IID_IMediaPosition ||iid == IID_IDispatch) {
+ *out = static_cast<IMediaPosition*>(this);
+ }
+ } else {
+ *out = 0;
+ hr = E_NOINTERFACE;
+ }
+
+ if (hr == S_OK) {
+ AddRef();
+ }
+
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) QBaseFilter::AddRef()
+ {
+ return InterlockedIncrement(&m_refCount);
+ }
+
+ STDMETHODIMP_(ULONG) QBaseFilter::Release()
+ {
+ ULONG refCount = InterlockedDecrement(&m_refCount);
+ if (refCount == 0) {
+ delete this;
+ }
+
+ return refCount;
+ }
+
+ STDMETHODIMP QBaseFilter::GetClassID(CLSID *clsid)
+ {
+ QMutexLocker locker(&m_mutex);
+ *clsid = m_clsid;
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::Stop()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_state = State_Stopped;
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::Pause()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_state = State_Paused;
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::Run(REFERENCE_TIME)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_state = State_Running;
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::GetState(DWORD, FILTER_STATE *state)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!state) {
+ return E_POINTER;
+ }
+
+ *state = m_state;
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::SetSyncSource(IReferenceClock *clock)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (clock) {
+ clock->AddRef();
+ }
+ if (m_clock) {
+ m_clock->Release();
+ }
+ m_clock = clock;
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::GetSyncSource(IReferenceClock **clock)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!clock) {
+ return E_POINTER;
+ }
+
+ if (m_clock) {
+ m_clock->AddRef();
+ }
+
+ *clock = m_clock;
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::FindPin(LPCWSTR name, IPin**pin)
+ {
+ if (!pin) {
+ return E_POINTER;
+ }
+
+ for (int i = 0; i < m_pins.count(); ++i) {
+ IPin * current = m_pins.at(i);
+ PIN_INFO info;
+ current->QueryPinInfo(&info);
+ if (info.pFilter) {
+ info.pFilter->Release();
+ }
+ if ( wcscmp(info.achName, name) == 0) {
+ *pin = current;
+ current->AddRef();
+ return S_OK;
+ }
+ }
+
+ *pin = 0;
+ return VFW_E_NOT_FOUND;
+ }
+
+ STDMETHODIMP QBaseFilter::QueryFilterInfo(FILTER_INFO *info )
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!info) {
+ return E_POINTER;
+ }
+ info->pGraph = m_graph;
+ if (m_graph) {
+ m_graph->AddRef();
+ }
+ qMemCopy(info->achName, m_name.utf16(), qMin(MAX_FILTER_NAME, m_name.length()+1) *2);
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::JoinFilterGraph(IFilterGraph *graph, LPCWSTR name)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_graph = graph;
+ m_name = QString::fromWCharArray(name);
+ return S_OK;
+ }
+
+ STDMETHODIMP QBaseFilter::EnumPins( IEnumPins **ep)
+ {
+ if (!ep) {
+ return E_POINTER;
+ }
+
+ *ep = new QEnumPins(this);
+ return S_OK;
+ }
+
+
+ STDMETHODIMP QBaseFilter::QueryVendorInfo(LPWSTR *)
+ {
+ //we give no information on that
+ return E_NOTIMPL;
+ }
+
+ //implementation from IMediaSeeking
+ STDMETHODIMP QBaseFilter::GetCapabilities(DWORD *pCapabilities)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetCapabilities(pCapabilities);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::CheckCapabilities(DWORD *pCapabilities)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->CheckCapabilities(pCapabilities);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::IsFormatSupported(const GUID *pFormat)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->IsFormatSupported(pFormat);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::QueryPreferredFormat(GUID *pFormat)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->QueryPreferredFormat(pFormat);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetTimeFormat(GUID *pFormat)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetTimeFormat(pFormat);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::IsUsingTimeFormat(const GUID *pFormat)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->IsUsingTimeFormat(pFormat);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::SetTimeFormat(const GUID *pFormat)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->SetTimeFormat(pFormat);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetDuration(LONGLONG *pDuration)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetDuration(pDuration);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetStopPosition(LONGLONG *pStop)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetStopPosition(pStop);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetCurrentPosition(LONGLONG *pCurrent)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetCurrentPosition(pCurrent);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::ConvertTimeFormat(LONGLONG *pTarget,
+ const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetPositions(pCurrent, pStop);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetAvailable(pEarliest, pLatest);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::SetRate(double dRate)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->SetRate(dRate);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetRate(double *dRate)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetRate(dRate);
+ ms->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetPreroll(LONGLONG *pllPreroll)
+ {
+ IMediaSeeking *ms = getUpstreamMediaSeeking();
+ if (!ms) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = ms->GetPreroll(pllPreroll);
+ ms->Release();
+ return hr;
+ }
+
+ //implementation from IMediaPosition
+ STDMETHODIMP QBaseFilter::get_Duration(REFTIME *plength)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->get_Duration(plength);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::put_CurrentPosition(REFTIME llTime)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->put_CurrentPosition(llTime);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::get_CurrentPosition(REFTIME *pllTime)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->get_CurrentPosition(pllTime);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::get_StopTime(REFTIME *pllTime)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->get_StopTime(pllTime);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::put_StopTime(REFTIME llTime)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->put_StopTime(llTime);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::get_PrerollTime(REFTIME *pllTime)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->get_PrerollTime(pllTime);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::put_PrerollTime(REFTIME llTime)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->put_PrerollTime(llTime);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::put_Rate(double dRate)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->put_Rate(dRate);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::get_Rate(double *pdRate)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->get_Rate(pdRate);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::CanSeekForward(LONG *pCanSeekForward)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->CanSeekForward(pCanSeekForward);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::CanSeekBackward(LONG *pCanSeekBackward)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->CanSeekBackward(pCanSeekBackward);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetTypeInfoCount(UINT *pctinfo)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->GetTypeInfoCount(pctinfo);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->GetTypeInfo(iTInfo, lcid, ppTInfo);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
+ mp->Release();
+ return hr;
+ }
+
+ STDMETHODIMP QBaseFilter::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
+ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+ {
+ IMediaPosition *mp = getUpstreamMediaPosition();
+ if (!mp) {
+ return E_NOTIMPL;
+ }
+
+ HRESULT hr = mp->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+ mp->Release();
+ return hr;
+ }
+
+
+ IMediaSeeking *QBaseFilter::getUpstreamMediaSeeking()
+ {
+ return static_cast<IMediaSeeking*>(getUpStreamInterface(IID_IMediaSeeking));
+ }
+
+ IMediaPosition *QBaseFilter::getUpstreamMediaPosition()
+ {
+ return static_cast<IMediaPosition*>(getUpStreamInterface(IID_IMediaPosition));
+ }
+
+ QList<QPin*> QBaseFilter::inputPins() const
+ {
+ QList<QPin*> ret;
+ for(int i = 0; i < m_pins.count(); ++i) {
+ QPin * pin = m_pins.at(i);
+ if (pin->direction() == PINDIR_INPUT) {
+ ret += pin;
+ }
+ }
+ return ret;
+ }
+
+ QList<QPin*> QBaseFilter::outputPins() const
+ {
+ QList<QPin*> ret;
+ for(int i = 0; i < m_pins.count(); ++i) {
+ QPin * pin = m_pins.at(i);
+ if (pin->direction() == PINDIR_OUTPUT) {
+ ret += pin;
+ }
+ }
+ return ret;
+ }
+
+ void *QBaseFilter::getUpStreamInterface(const IID &iid) const
+ {
+ const QList<QPin*> inputs = inputPins();
+ for (int i = 0; i < inputs.count(); ++i) {
+ IPin *out = inputs.at(i)->connected();
+ if (out) {
+ void *ms = 0;
+ out->QueryInterface(iid, &ms);
+ if (ms) {
+ return ms;
+ }
+ }
+ }
+ //none was found
+ return 0;
+ }
+
+
+ //addition
+ HRESULT QBaseFilter::processSample(IMediaSample *)
+ {
+ return S_OK;
+ }
+
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/qbasefilter.h b/src/3rdparty/phonon/ds9/qbasefilter.h
new file mode 100644
index 0000000..a72d6fe
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qbasefilter.h
@@ -0,0 +1,136 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_QBASEFILTER_H
+#define PHONON_QBASEFILTER_H
+
+#include "phononds9_namespace.h"
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+
+#include <dshow.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class QPin;
+ class QBaseFilter : public IBaseFilter, public IMediaSeeking, public IMediaPosition
+ {
+ public:
+ QBaseFilter(const CLSID &clsid);
+ virtual ~QBaseFilter();
+
+ //implementation from IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void** out);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ //implementation from IPersist
+ STDMETHODIMP GetClassID(CLSID *);
+
+ //implementation from IMediaFilter
+ STDMETHODIMP Stop();
+ STDMETHODIMP Pause();
+ STDMETHODIMP Run(REFERENCE_TIME);
+ STDMETHODIMP GetState(DWORD, FILTER_STATE*);
+ STDMETHODIMP SetSyncSource(IReferenceClock*);
+ STDMETHODIMP GetSyncSource(IReferenceClock**);
+
+ //implementation from IBaseFilter
+ STDMETHODIMP EnumPins(IEnumPins**);
+ STDMETHODIMP FindPin(LPCWSTR, IPin**);
+ STDMETHODIMP QueryFilterInfo(FILTER_INFO*);
+ STDMETHODIMP JoinFilterGraph(IFilterGraph*, LPCWSTR);
+ STDMETHODIMP QueryVendorInfo(LPWSTR*);
+
+ //implementation from IMediaSeeking
+ STDMETHODIMP GetCapabilities(DWORD *pCapabilities);
+ STDMETHODIMP CheckCapabilities(DWORD *pCapabilities);
+ STDMETHODIMP IsFormatSupported(const GUID *pFormat);
+ STDMETHODIMP QueryPreferredFormat(GUID *pFormat);
+ STDMETHODIMP GetTimeFormat(GUID *pFormat);
+ STDMETHODIMP IsUsingTimeFormat(const GUID *pFormat);
+ STDMETHODIMP SetTimeFormat(const GUID *pFormat);
+ STDMETHODIMP GetDuration(LONGLONG *pDuration);
+ STDMETHODIMP GetStopPosition(LONGLONG *pStop);
+ STDMETHODIMP GetCurrentPosition(LONGLONG *pCurrent);
+ STDMETHODIMP ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat);
+ STDMETHODIMP SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags);
+ STDMETHODIMP GetPositions(LONGLONG *pCurrent, LONGLONG *pStop);
+ STDMETHODIMP GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest);
+ STDMETHODIMP SetRate(double dRate);
+ STDMETHODIMP GetRate(double *dRate);
+ STDMETHODIMP GetPreroll(LONGLONG *pllPreroll);
+
+ //implementation from IMediaPosition
+ STDMETHODIMP get_Duration(REFTIME *plength);
+ STDMETHODIMP put_CurrentPosition(REFTIME llTime);
+ STDMETHODIMP get_CurrentPosition(REFTIME *pllTime);
+ STDMETHODIMP get_StopTime(REFTIME *pllTime);
+ STDMETHODIMP put_StopTime(REFTIME llTime);
+ STDMETHODIMP get_PrerollTime(REFTIME *pllTime);
+ STDMETHODIMP put_PrerollTime(REFTIME llTime);
+ STDMETHODIMP put_Rate(double dRate);
+ STDMETHODIMP get_Rate(double *pdRate);
+ STDMETHODIMP CanSeekForward(LONG *pCanSeekForward);
+ STDMETHODIMP CanSeekBackward(LONG *pCanSeekBackward);
+
+ //implementation from IDispatch (coming from IMediaPosition)
+ STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
+ STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
+ STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
+ STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
+ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
+
+ //own methods
+ const QList<QPin *> pins() const;
+ void addPin(QPin *pin);
+ void removePin(QPin *pin);
+ IFilterGraph *graph() const;
+ FILTER_STATE state() const;
+
+
+ //reimplement this if you want specific processing of media sample
+ virtual HRESULT processSample(IMediaSample *);
+
+ private:
+ QList<QPin*> outputPins() const;
+ QList<QPin*> inputPins() const;
+
+ void *getUpStreamInterface(const IID &iid) const;
+ IMediaSeeking *getUpstreamMediaSeeking();
+ IMediaPosition *getUpstreamMediaPosition();
+
+ LONG m_refCount;
+ CLSID m_clsid;
+ QString m_name;
+ IReferenceClock *m_clock;
+ IFilterGraph *m_graph;
+ FILTER_STATE m_state;
+ QList<QPin *> m_pins;
+ mutable QMutex m_mutex;
+ };
+ }
+}
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/qevr9.h b/src/3rdparty/phonon/ds9/qevr9.h
new file mode 100644
index 0000000..8599fce
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qevr9.h
@@ -0,0 +1,143 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <d3d9.h>
+
+#define DXVA2_ProcAmp_Brightness 1
+#define DXVA2_ProcAmp_Contrast 2
+#define DXVA2_ProcAmp_Hue 4
+#define DXVA2_ProcAmp_Saturation 8
+
+typedef enum {
+ MFVideoARMode_None = 0x00000000,
+ MFVideoARMode_PreservePicture = 0x00000001,
+ MFVideoARMode_PreservePixel = 0x00000002,
+ MFVideoARMode_NonLinearStretch = 0x00000004,
+ MFVideoARMode_Mask = 0x00000007
+} MFVideoAspectRatioMode;
+
+typedef struct {
+ float left;
+ float top;
+ float right;
+ float bottom;
+} MFVideoNormalizedRect;
+
+typedef struct {
+ UINT DeviceCaps;
+ D3DPOOL InputPool;
+ UINT NumForwardRefSamples;
+ UINT NumBackwardRefSamples;
+ UINT Reserved;
+ UINT DeinterlaceTechnology;
+ UINT ProcAmpControlCaps;
+ UINT VideoProcessorOperations;
+ UINT NoiseFilterTechnology;
+ UINT DetailFilterTechnology;
+} DXVA2_VideoProcessorCaps;
+
+typedef struct {
+ union {
+ struct {
+ USHORT Fraction;
+ SHORT Value;
+ };
+ LONG ll;
+ };
+} DXVA2_Fixed32;
+
+typedef struct {
+ DXVA2_Fixed32 MinValue;
+ DXVA2_Fixed32 MaxValue;
+ DXVA2_Fixed32 DefaultValue;
+ DXVA2_Fixed32 StepSize;
+} DXVA2_ValueRange;
+
+typedef struct {
+ DXVA2_Fixed32 Brightness;
+ DXVA2_Fixed32 Contrast;
+ DXVA2_Fixed32 Hue;
+ DXVA2_Fixed32 Saturation;
+} DXVA2_ProcAmpValues;
+
+DXVA2_Fixed32 DXVA2FloatToFixed(const float _float_)
+{
+ DXVA2_Fixed32 _fixed_;
+ _fixed_.Fraction = LOWORD(_float_ * 0x10000);
+ _fixed_.Value = HIWORD(_float_ * 0x10000);
+ return _fixed_;
+}
+
+float DXVA2FixedToFloat(const DXVA2_Fixed32 _fixed_)
+{
+ return (FLOAT)_fixed_.Value + (FLOAT)_fixed_.Fraction / 0x10000;
+}
+
+#undef INTERFACE
+#define INTERFACE IMFVideoDisplayControl
+DECLARE_INTERFACE_(IMFVideoDisplayControl, IUnknown)
+{
+ STDMETHOD(GetNativeVideoSize)(THIS_ SIZE* pszVideo, SIZE* pszARVideo) PURE;
+ STDMETHOD(GetIdealVideoSize)(THIS_ SIZE* pszMin, SIZE* pszMax) PURE;
+ STDMETHOD(SetVideoPosition)(THIS_ const MFVideoNormalizedRect* pnrcSource, const LPRECT prcDest) PURE;
+ STDMETHOD(GetVideoPosition)(THIS_ MFVideoNormalizedRect* pnrcSource, LPRECT prcDest) PURE;
+ STDMETHOD(SetAspectRatioMode)(THIS_ DWORD dwAspectRatioMode) PURE;
+ STDMETHOD(GetAspectRatioMode)(THIS_ DWORD* pdwAspectRatioMode) PURE;
+ STDMETHOD(SetVideoWindow)(THIS_ HWND hwndVideo) PURE;
+ STDMETHOD(GetVideoWindow)(THIS_ HWND* phwndVideo) PURE;
+ STDMETHOD(RepaintVideo)(THIS_) PURE;
+ STDMETHOD(GetCurrentImage)(THIS_ BITMAPINFOHEADER* pBih, BYTE** pDib, DWORD* pcbDib, LONGLONG* pTimeStamp) PURE;
+ STDMETHOD(SetBorderColor)(THIS_ COLORREF Clr) PURE;
+ STDMETHOD(GetBorderColor)(THIS_ COLORREF* pClr) PURE;
+ STDMETHOD(SetRenderingPrefs)(THIS_ DWORD dwRenderFlags) PURE;
+ STDMETHOD(GetRenderingPrefs)(THIS_ DWORD* pdwRenderFlags) PURE;
+ STDMETHOD(SetFullScreen)(THIS_ BOOL fFullscreen) PURE;
+ STDMETHOD(GetFullScreen)(THIS_ BOOL* pfFullscreen) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IMFVideoMixerControl
+DECLARE_INTERFACE_(IMFVideoMixerControl, IUnknown)
+{
+ STDMETHOD(SetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD dwZ) PURE;
+ STDMETHOD(GetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD* pdwZ) PURE;
+ STDMETHOD(SetStreamOutputRect)(THIS_ DWORD dwStreamID, const MFVideoNormalizedRect* pnrcOutput) PURE;
+ STDMETHOD(GetStreamOutputRect)(THIS_ DWORD dwStreamID, MFVideoNormalizedRect* pnrcOutput) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IMFVideoProcessor
+DECLARE_INTERFACE_(IMFVideoProcessor, IUnknown)
+{
+ STDMETHOD(GetAvailableVideoProcessorModes)(THIS_ UINT* lpdwNumProcessingModes, GUID** ppVideoProcessingModes) PURE;
+ STDMETHOD(GetVideoProcessorCaps)(THIS_ LPGUID lpVideoProcessorMode, DXVA2_VideoProcessorCaps* lpVideoProcessorCaps) PURE;
+ STDMETHOD(GetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE;
+ STDMETHOD(SetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE;
+ STDMETHOD(GetProcAmpRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE;
+ STDMETHOD(GetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* Values) PURE;
+ STDMETHOD(SetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* pValues) PURE;
+ STDMETHOD(GetFilteringRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE;
+ STDMETHOD(GetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE;
+ STDMETHOD(SetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE;
+ STDMETHOD(GetBackgroundColor)(THIS_ COLORREF* lpClrBkg) PURE;
+ STDMETHOD(SetBackgroundColor)(THIS_ COLORREF ClrBkg) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IMFGetService
+DECLARE_INTERFACE_(IMFGetService, IUnknown)
+{
+ STDMETHOD(GetService)(THIS_ REFGUID guidService, REFIID riid, LPVOID* ppvObject) PURE;
+};
+#undef INTERFACE
diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.cpp b/src/3rdparty/phonon/ds9/qmeminputpin.cpp
new file mode 100644
index 0000000..a21fbe7
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qmeminputpin.cpp
@@ -0,0 +1,316 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "qmeminputpin.h"
+#include "qbasefilter.h"
+#include "compointer.h"
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+
+ QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, bool transform, QPin *output) :
+ QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform), m_output(output)
+ {
+ }
+
+ QMemInputPin::~QMemInputPin()
+ {
+ }
+
+ STDMETHODIMP QMemInputPin::QueryInterface(REFIID iid, void **out)
+ {
+ if (!out) {
+ return E_POINTER;
+ }
+
+ if (iid == IID_IMemInputPin) {
+ *out = static_cast<IMemInputPin*>(this);
+ AddRef();
+ return S_OK;
+ } else {
+ return QPin::QueryInterface(iid, out);
+ }
+ }
+
+ STDMETHODIMP_(ULONG) QMemInputPin::AddRef()
+ {
+ return QPin::AddRef();
+ }
+
+ STDMETHODIMP_(ULONG) QMemInputPin::Release()
+ {
+ return QPin::Release();
+ }
+
+ STDMETHODIMP QMemInputPin::EndOfStream()
+ {
+ //this allows to serialize with Receive calls
+ QMutexLocker locker(&m_mutexReceive);
+ IPin *conn = m_output ? m_output->connected() : 0;
+ if (conn) {
+ conn->EndOfStream();
+ }
+ return S_OK;
+ }
+
+ STDMETHODIMP QMemInputPin::BeginFlush()
+ {
+ //pass downstream
+ IPin *conn = m_output ? m_output->connected() : 0;
+ if (conn) {
+ conn->BeginFlush();
+ }
+ QMutexLocker locker(&m_mutex);
+ m_flushing = true;
+ return S_OK;
+ }
+
+ STDMETHODIMP QMemInputPin::EndFlush()
+ {
+ //pass downstream
+ IPin *conn = m_output ? m_output->connected() : 0;
+ if (conn) {
+ conn->EndFlush();
+ }
+ QMutexLocker locker(&m_mutex);
+ m_flushing = false;
+ return S_OK;
+ }
+
+ STDMETHODIMP QMemInputPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+ {
+ if (m_output)
+ m_output->NewSegment(start, stop, rate);
+ return S_OK;
+ }
+
+ //reimplementation to set the type for the output pin
+ //no need to make a deep copy here
+ STDMETHODIMP QMemInputPin::ReceiveConnection(IPin *pin ,const AM_MEDIA_TYPE *mt)
+ {
+ HRESULT hr = QPin::ReceiveConnection(pin, mt);
+ if (hr == S_OK &&
+ mt->majortype != MEDIATYPE_NULL &&
+ mt->subtype != MEDIASUBTYPE_NULL &&
+ mt->formattype != GUID_NULL && m_output) {
+ //we tell the output pin that it should connect with this type
+ hr = m_output->setAcceptedMediaType(connectedType());
+ }
+ return hr;
+ }
+
+ STDMETHODIMP QMemInputPin::GetAllocator(IMemAllocator **alloc)
+ {
+ if (!alloc) {
+ return E_POINTER;
+ }
+
+ *alloc = memoryAllocator(true);
+ if (*alloc) {
+ return S_OK;
+ }
+
+ return VFW_E_NO_ALLOCATOR;
+ }
+
+ STDMETHODIMP QMemInputPin::NotifyAllocator(IMemAllocator *alloc, BOOL readonly)
+ {
+ if (!alloc) {
+ return E_POINTER;
+ }
+
+ {
+ QMutexLocker locker(&m_mutex);
+ m_shouldDuplicateSamples = m_transform && readonly;
+ }
+
+ setMemoryAllocator(alloc);
+
+ if (m_output) {
+ ComPointer<IMemInputPin> input(m_output, IID_IMemInputPin);
+ input->NotifyAllocator(alloc, m_shouldDuplicateSamples);
+ }
+
+ return S_OK;
+ }
+
+ STDMETHODIMP QMemInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *prop)
+ {
+ if (!prop) {
+ return E_POINTER;
+ }
+
+ //we have no particular requirements
+ return E_NOTIMPL;
+ }
+
+ STDMETHODIMP QMemInputPin::Receive(IMediaSample *sample)
+ {
+ QMutexLocker locker(&m_mutexReceive);
+ if (!sample) {
+ return E_POINTER;
+ }
+
+ if (filterState() == State_Stopped) {
+ return VFW_E_WRONG_STATE;
+ }
+
+ if (isFlushing()) {
+ return S_FALSE; //we are still flushing
+ }
+
+ if (!m_shouldDuplicateSamples) {
+ //we do it just once
+ HRESULT hr = m_parent->processSample(sample);
+ if (!SUCCEEDED(hr)) {
+ return hr;
+ }
+ }
+
+ if (m_output) {
+ IMediaSample *outSample = m_shouldDuplicateSamples ?
+ duplicateSampleForOutput(sample, m_output->memoryAllocator())
+ : sample;
+
+ if (m_shouldDuplicateSamples) {
+ m_parent->processSample(outSample);
+ }
+
+ ComPointer<IMemInputPin> input(m_output->connected(), IID_IMemInputPin);
+ if (input) {
+ input->Receive(outSample);
+ }
+
+ if (m_shouldDuplicateSamples) {
+ outSample->Release();
+ }
+ }
+ return S_OK;
+ }
+
+ STDMETHODIMP QMemInputPin::ReceiveMultiple(IMediaSample **samples,long count,long *nbDone)
+ {
+ //no need to lock here: there is no access to member data
+ if (!samples || !nbDone) {
+ return E_POINTER;
+ }
+
+ *nbDone = 0; //initialization
+ while( *nbDone != count) {
+ HRESULT hr = Receive(samples[*nbDone]);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ (*nbDone)++;
+ }
+
+ return S_OK;
+ }
+
+ STDMETHODIMP QMemInputPin::ReceiveCanBlock()
+ {
+ //we test the output to see if it can block
+ if (m_output) {
+ ComPointer<IMemInputPin> meminput(m_output->connected(), IID_IMemInputPin);
+ if (meminput && meminput->ReceiveCanBlock() != S_FALSE) {
+ return S_OK;
+ }
+ }
+ return S_FALSE;
+ }
+
+
+ ALLOCATOR_PROPERTIES QMemInputPin::getDefaultAllocatorProperties() const
+ {
+ //those values reduce buffering a lot (good for the volume effect)
+ ALLOCATOR_PROPERTIES prop = {4096, 1, 1, 0};
+ return prop;
+ }
+
+
+ IMediaSample *QMemInputPin::duplicateSampleForOutput(IMediaSample *sample, IMemAllocator *alloc)
+ {
+ LONG length = sample->GetActualDataLength();
+
+ HRESULT hr = alloc->Commit();
+ if (hr == HRESULT(VFW_E_SIZENOTSET)) {
+ ALLOCATOR_PROPERTIES prop = getDefaultAllocatorProperties();
+ prop.cbBuffer = qMax(prop.cbBuffer, length);
+ ALLOCATOR_PROPERTIES actual;
+ //we just try to set the properties...
+ alloc->SetProperties(&prop, &actual);
+ hr = alloc->Commit();
+ }
+
+ Q_ASSERT(SUCCEEDED(hr));
+
+ IMediaSample *out;
+ hr = alloc->GetBuffer(&out, 0, 0, AM_GBF_NOTASYNCPOINT);
+ Q_ASSERT(SUCCEEDED(hr));
+
+ //let's copy the sample
+ {
+ REFERENCE_TIME start, end;
+ sample->GetTime(&start, &end);
+ out->SetTime(&start, &end);
+ }
+
+ hr = out->SetActualDataLength(length);
+ Q_ASSERT(SUCCEEDED(hr));
+ hr = out->SetDiscontinuity(sample->IsDiscontinuity());
+ Q_ASSERT(SUCCEEDED(hr));
+
+ {
+ LONGLONG start, end;
+ hr = sample->GetMediaTime(&start, &end);
+ if (hr != HRESULT(VFW_E_MEDIA_TIME_NOT_SET)) {
+ hr = out->SetMediaTime(&start, &end);
+ Q_ASSERT(SUCCEEDED(hr));
+ }
+ }
+
+ AM_MEDIA_TYPE *type = 0;
+ hr = sample->GetMediaType(&type);
+ Q_ASSERT(SUCCEEDED(hr));
+ hr = out->SetMediaType(type);
+ Q_ASSERT(SUCCEEDED(hr));
+
+ hr = out->SetPreroll(sample->IsPreroll());
+ Q_ASSERT(SUCCEEDED(hr));
+ hr = out->SetSyncPoint(sample->IsSyncPoint());
+ Q_ASSERT(SUCCEEDED(hr));
+
+ BYTE *dest = 0, *src = 0;
+ hr = out->GetPointer(&dest);
+ Q_ASSERT(SUCCEEDED(hr));
+ hr = sample->GetPointer(&src);
+ Q_ASSERT(SUCCEEDED(hr));
+
+ qMemCopy(dest, src, sample->GetActualDataLength());
+
+ return out;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.h b/src/3rdparty/phonon/ds9/qmeminputpin.h
new file mode 100644
index 0000000..d74c451
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qmeminputpin.h
@@ -0,0 +1,77 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_QMEMINPUTPIN_H
+#define PHONON_QMEMINPUTPIN_H
+
+
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include "qpin.h"
+
+#include <dshow.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class QBaseFilter;
+
+ //this class will be used for our effects
+ class QMemInputPin : public QPin, public IMemInputPin
+ {
+ public:
+ QMemInputPin(QBaseFilter *, const QVector<AM_MEDIA_TYPE> &, bool transform, QPin *output);
+ ~QMemInputPin();
+
+ //reimplementation from IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void** out);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ //reimplementation from IPin
+ STDMETHODIMP ReceiveConnection(IPin *,const AM_MEDIA_TYPE *);
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
+ STDMETHODIMP EndOfStream();
+ STDMETHODIMP NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate);
+
+ //reimplementation from IMemAllocator
+ STDMETHODIMP GetAllocator(IMemAllocator **);
+ STDMETHODIMP NotifyAllocator(IMemAllocator *,BOOL);
+ STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *);
+ STDMETHODIMP Receive(IMediaSample *);
+ STDMETHODIMP ReceiveMultiple(IMediaSample **,long,long *);
+ STDMETHODIMP ReceiveCanBlock();
+
+ private:
+ IMediaSample *duplicateSampleForOutput(IMediaSample *, IMemAllocator *);
+ ALLOCATOR_PROPERTIES getDefaultAllocatorProperties() const;
+
+ bool m_shouldDuplicateSamples;
+ const bool m_transform; //defines if the pin is transforming the samples
+ QPin* const m_output;
+ QMutex m_mutexReceive;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/ds9/qpin.cpp b/src/3rdparty/phonon/ds9/qpin.cpp
new file mode 100644
index 0000000..b4afd10
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qpin.cpp
@@ -0,0 +1,632 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "qbasefilter.h"
+#include "qpin.h"
+#include "compointer.h"
+
+#include <QtCore/QMutex>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+
+ static const AM_MEDIA_TYPE defaultMediaType = { MEDIATYPE_NULL, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
+
+ class QEnumMediaTypes : public IEnumMediaTypes
+ {
+ public:
+ QEnumMediaTypes(QPin *pin) : m_refCount(1), m_pin(pin), m_index(0)
+ {
+ m_pin->AddRef();
+ }
+
+ ~QEnumMediaTypes()
+ {
+ m_pin->Release();
+ }
+
+ STDMETHODIMP QueryInterface(const IID &iid,void **out)
+ {
+ if (!out) {
+ return E_POINTER;
+ }
+
+ HRESULT hr = S_OK;
+ if (iid == IID_IEnumMediaTypes) {
+ *out = static_cast<IEnumMediaTypes*>(this);
+ } else if (iid == IID_IUnknown) {
+ *out = static_cast<IUnknown*>(this);
+ } else {
+ *out = 0;
+ hr = E_NOINTERFACE;
+ }
+
+ if (hr == S_OK) {
+ AddRef();
+ }
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_refCount);
+ }
+
+ STDMETHODIMP_(ULONG) Release()
+ {
+ ULONG refCount = InterlockedDecrement(&m_refCount);
+ if (refCount == 0) {
+ delete this;
+ }
+
+ return refCount;
+ }
+
+ STDMETHODIMP Next(ULONG count, AM_MEDIA_TYPE **out, ULONG *fetched)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!out) {
+ return E_POINTER;
+ }
+
+ if (!fetched && count > 1) {
+ return E_INVALIDARG;
+ }
+
+ uint nbFetched = 0;
+ while (nbFetched < count && m_index < m_pin->mediaTypes().count()) {
+ //the caller will deallocate the memory
+ *out = static_cast<AM_MEDIA_TYPE *>(::CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
+ const AM_MEDIA_TYPE original = m_pin->mediaTypes().at(m_index);
+ **out = QPin::copyMediaType(original);
+ nbFetched++;
+ m_index++;
+ out++;
+ }
+
+ if (fetched) {
+ *fetched = nbFetched;
+ }
+
+ return nbFetched == count ? S_OK : S_FALSE;
+ }
+
+ STDMETHODIMP Skip(ULONG count)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_index = qMin(m_index + int(count), m_pin->mediaTypes().count());
+ return (m_index == m_pin->mediaTypes().count()) ? S_FALSE : S_OK;
+ }
+
+ STDMETHODIMP Reset()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_index = 0;
+ return S_OK;
+ }
+
+ STDMETHODIMP Clone(IEnumMediaTypes **out)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!out) {
+ return E_POINTER;
+ }
+
+ *out = new QEnumMediaTypes(m_pin);
+ (*out)->Skip(m_index);
+ return S_OK;
+ }
+
+
+ private:
+ LONG m_refCount;
+ QPin *m_pin;
+ int m_index;
+ QMutex m_mutex;
+ };
+
+
+ QPin::QPin(QBaseFilter *parent, PIN_DIRECTION dir, const QVector<AM_MEDIA_TYPE> &mt) :
+ m_parent(parent), m_flushing(false), m_refCount(1), m_connected(0),
+ m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType),
+ m_memAlloc(0)
+ {
+ Q_ASSERT(m_parent);
+ m_parent->addPin(this);
+ }
+
+ QPin::~QPin()
+ {
+ m_parent->removePin(this);
+ setMemoryAllocator(0);
+ freeMediaType(m_connectedType);
+ }
+
+ //reimplementation from IUnknown
+ STDMETHODIMP QPin::QueryInterface(REFIID iid, void**out)
+ {
+ if (!out) {
+ return E_POINTER;
+ }
+
+ HRESULT hr = S_OK;
+
+ if (iid == IID_IPin) {
+ *out = static_cast<IPin*>(this);
+ } else if (iid == IID_IUnknown) {
+ *out = static_cast<IUnknown*>(this);
+ } else if (m_direction == PINDIR_OUTPUT && (iid == IID_IMediaSeeking || iid == IID_IMediaPosition)) {
+ return m_parent->QueryInterface(iid, out);
+ } else {
+ *out = 0;
+ hr = E_NOINTERFACE;
+ }
+
+ if (hr == S_OK) {
+ AddRef();
+ }
+ return hr;
+ }
+
+ STDMETHODIMP_(ULONG) QPin::AddRef()
+ {
+ return InterlockedIncrement(&m_refCount);
+ }
+
+ STDMETHODIMP_(ULONG) QPin::Release()
+ {
+ ULONG refCount = InterlockedDecrement(&m_refCount);
+ if (refCount == 0) {
+ delete this;
+ }
+
+ return refCount;
+ }
+
+ //this is called on the input pins
+ STDMETHODIMP QPin::ReceiveConnection(IPin *pin, const AM_MEDIA_TYPE *type)
+ {
+ if (!pin ||!type) {
+ return E_POINTER;
+ }
+
+ if (connected()) {
+ return VFW_E_ALREADY_CONNECTED;
+ }
+
+ if (filterState() != State_Stopped) {
+ return VFW_E_NOT_STOPPED;
+ }
+
+ if (QueryAccept(type) != S_OK) {
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ }
+
+ setConnected(pin);
+ setConnectedType(*type);
+
+ return S_OK;
+ }
+
+ //this is called on the output pins
+ STDMETHODIMP QPin::Connect(IPin *pin, const AM_MEDIA_TYPE *type)
+ {
+ if (!pin) {
+ return E_POINTER;
+ }
+
+ if (connected()) {
+ return VFW_E_ALREADY_CONNECTED;
+ }
+
+ if (filterState() != State_Stopped) {
+ return VFW_E_NOT_STOPPED;
+ }
+
+ HRESULT hr = S_OK;
+
+ setConnected(pin);
+ if (!type) {
+
+ //let(s first try the output pin's mediaTypes
+ if (checkOutputMediaTypesConnection(pin) != S_OK &&
+ checkOwnMediaTypesConnection(pin) != S_OK) {
+ hr = VFW_E_NO_ACCEPTABLE_TYPES;
+ }
+ } else if (QueryAccept(type) == S_OK) {
+ setConnectedType(*type);
+ hr = pin->ReceiveConnection(this, type);
+ } else {
+ hr = VFW_E_TYPE_NOT_ACCEPTED;
+ }
+
+ if (FAILED(hr)) {
+ setConnected(0);
+ setConnectedType(defaultMediaType);
+ } else {
+ ComPointer<IMemInputPin> input(pin, IID_IMemInputPin);
+ if (input) {
+ ComPointer<IMemAllocator> alloc;
+ input->GetAllocator(alloc.pparam());
+ if (alloc) {
+ //be default we take the allocator from the input pin
+ //we have no reason to force using our own
+ setMemoryAllocator(alloc);
+ }
+ }
+ if (memoryAllocator() == 0) {
+ ALLOCATOR_PROPERTIES prop;
+ if (input && input->GetAllocatorRequirements(&prop) == S_OK) {
+ createDefaultMemoryAllocator(&prop);
+ } else {
+ createDefaultMemoryAllocator();
+ }
+ }
+
+ Q_ASSERT(memoryAllocator() != 0);
+ if (input) {
+ input->NotifyAllocator(memoryAllocator(), TRUE); //TRUE is arbitrarily chosen here
+ }
+
+ }
+
+ return hr;
+ }
+
+ STDMETHODIMP QPin::Disconnect()
+ {
+ if (!connected()) {
+ return S_FALSE;
+ }
+
+ if (filterState() != State_Stopped) {
+ return VFW_E_NOT_STOPPED;
+ }
+
+ setConnected(0);
+ setConnectedType(defaultMediaType);
+ setMemoryAllocator(0);
+ return S_OK;
+ }
+
+ STDMETHODIMP QPin::ConnectedTo(IPin **other)
+ {
+ if (!other) {
+ return E_POINTER;
+ }
+
+ *other = connected(true);
+ if (!(*other)) {
+ return VFW_E_NOT_CONNECTED;
+ }
+
+ return S_OK;
+ }
+
+ STDMETHODIMP QPin::ConnectionMediaType(AM_MEDIA_TYPE *type)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!type) {
+ return E_POINTER;
+ }
+
+ *type = copyMediaType(m_connectedType);
+ if (!m_connected) {
+ return VFW_E_NOT_CONNECTED;
+ } else {
+ return S_OK;
+ }
+ }
+
+ STDMETHODIMP QPin::QueryPinInfo(PIN_INFO *info)
+ {
+ if (!info) {
+ return E_POINTER;
+ }
+
+ info->dir = m_direction;
+ info->pFilter = m_parent;
+ m_parent->AddRef();
+ info->achName[0] = 0;
+ return S_OK;
+ }
+
+ STDMETHODIMP QPin::QueryDirection(PIN_DIRECTION *dir)
+ {
+ if (!dir) {
+ return E_POINTER;
+ }
+
+ *dir = m_direction;
+ return S_OK;
+ }
+
+ STDMETHODIMP QPin::QueryId(LPWSTR *id)
+ {
+ if (!id) {
+ return E_POINTER;
+ }
+
+ *id = static_cast<LPWSTR>(::CoTaskMemAlloc(2));
+ *id[0] = 0;
+ return S_OK;
+ }
+
+ STDMETHODIMP QPin::QueryAccept(const AM_MEDIA_TYPE *type)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!type) {
+ return E_POINTER;
+ }
+
+ for (int i = 0; i < m_mediaTypes.count(); ++i) {
+ const AM_MEDIA_TYPE &current = m_mediaTypes.at(i);
+ if ( (type->majortype == current.majortype) &&
+ (current.subtype == MEDIASUBTYPE_NULL || type->subtype == current.subtype) &&
+ (type->majortype == MEDIATYPE_Stream || type->formattype != GUID_NULL || current.formattype != GUID_NULL) &&
+ (current.formattype == GUID_NULL || type->formattype == current.formattype)
+ ) {
+ return S_OK;
+ }
+ }
+ return S_FALSE;
+ }
+
+
+ STDMETHODIMP QPin::EnumMediaTypes(IEnumMediaTypes **emt)
+ {
+ if (!emt) {
+ return E_POINTER;
+ }
+
+ *emt = new QEnumMediaTypes(this);
+ return S_OK;
+ }
+
+
+ STDMETHODIMP QPin::EndOfStream()
+ {
+ return E_UNEXPECTED;
+ }
+
+ STDMETHODIMP QPin::BeginFlush()
+ {
+ return E_UNEXPECTED;
+ }
+
+ STDMETHODIMP QPin::EndFlush()
+ {
+ return E_UNEXPECTED;
+ }
+
+ STDMETHODIMP QPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_direction == PINDIR_OUTPUT && m_connected) {
+ //we deliver this downstream
+ m_connected->NewSegment(start, stop, rate);
+ }
+ return S_OK;
+ }
+
+ STDMETHODIMP QPin::QueryInternalConnections(IPin **, ULONG*)
+ {
+ //this is not implemented on purpose (the input pins are connected to all the output pins)
+ return E_NOTIMPL;
+ }
+
+
+ HRESULT QPin::checkOutputMediaTypesConnection(IPin *pin)
+ {
+ ComPointer<IEnumMediaTypes> emt;
+ HRESULT hr = pin->EnumMediaTypes(emt.pparam());
+ if (hr != S_OK) {
+ return hr;
+ }
+
+ AM_MEDIA_TYPE *type = 0;
+ while (emt->Next(1, &type, 0) == S_OK) {
+ if (QueryAccept(type) == S_OK) {
+ setConnectedType(*type);
+ if (pin->ReceiveConnection(this, type) == S_OK) {
+ freeMediaType(type);
+ return S_OK;
+ } else {
+ setConnectedType(defaultMediaType);
+ freeMediaType(type);
+ }
+ }
+ }
+
+ //we didn't find a suitable type
+ return S_FALSE;
+ }
+
+ HRESULT QPin::checkOwnMediaTypesConnection(IPin *pin)
+ {
+ for(int i = 0; i < m_mediaTypes.count(); ++i) {
+ const AM_MEDIA_TYPE &current = m_mediaTypes.at(i);
+ setConnectedType(current);
+ HRESULT hr = pin->ReceiveConnection(this, &current);
+ if (hr == S_OK) {
+ return S_OK;
+ }
+ }
+
+ //we didn't find a suitable type
+ return S_FALSE;
+ }
+
+ void QPin::freeMediaType(const AM_MEDIA_TYPE &type)
+ {
+ if (type.cbFormat) {
+ ::CoTaskMemFree(type.pbFormat);
+ }
+ if (type.pUnk) {
+ type.pUnk->Release();
+ }
+ }
+
+ void QPin::freeMediaType(AM_MEDIA_TYPE *type)
+ {
+ freeMediaType(*type);
+ ::CoTaskMemFree(type);
+ }
+
+ //addition
+
+ PIN_DIRECTION QPin::direction() const
+ {
+ return m_direction;
+ }
+
+ void QPin::setConnectedType(const AM_MEDIA_TYPE &type)
+ {
+ QMutexLocker locker(&m_mutex);
+
+ //1st we free memory
+ freeMediaType(m_connectedType);
+
+ m_connectedType = copyMediaType(type);
+ }
+
+ const AM_MEDIA_TYPE &QPin::connectedType() const
+ {
+ QMutexLocker locker(&m_mutex);
+ return m_connectedType;
+ }
+
+ void QPin::setConnected(IPin *pin)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (pin) {
+ pin->AddRef();
+ }
+ if (m_connected) {
+ m_connected->Release();
+ }
+ m_connected = pin;
+ }
+
+ IPin *QPin::connected(bool addref) const
+ {
+ QMutexLocker locker(&m_mutex);
+ if (addref && m_connected) {
+ m_connected->AddRef();
+ }
+ return m_connected;
+ }
+
+ bool QPin::isFlushing() const
+ {
+ QMutexLocker locker(&m_mutex);
+ return m_flushing;
+ }
+
+ FILTER_STATE QPin::filterState() const
+ {
+ FILTER_STATE fstate = State_Stopped;
+ m_parent->GetState(0, &fstate);
+ return fstate;
+ }
+
+ QVector<AM_MEDIA_TYPE> QPin::mediaTypes() const
+ {
+ QMutexLocker locker(&m_mutex);
+ return m_mediaTypes;
+ }
+
+ HRESULT QPin::setAcceptedMediaType(const AM_MEDIA_TYPE &mt)
+ {
+ const QVector<AM_MEDIA_TYPE> oldMediaTypes = m_mediaTypes;
+ m_mediaTypes = QVector<AM_MEDIA_TYPE>() << mt;
+
+ HRESULT hr = S_OK;
+
+ IPin *conn = connected();
+ if (conn) {
+ //try to reconnect to redefine the media type
+ conn->Disconnect();
+ Disconnect();
+ hr = Connect(conn, 0);
+ if (FAILED(hr)) {
+ m_mediaTypes = oldMediaTypes;
+ Connect(conn, 0); //just redo the connection with the old media types
+ }
+ }
+ return hr;
+ }
+
+ void QPin::createDefaultMemoryAllocator(ALLOCATOR_PROPERTIES *prop)
+ {
+ ComPointer<IMemAllocator> alloc(CLSID_MemoryAllocator, IID_IMemAllocator);
+ if (prop) {
+ alloc->SetProperties(prop, 0);
+ }
+ setMemoryAllocator(alloc);
+ }
+
+ void QPin::setMemoryAllocator(IMemAllocator *alloc)
+ {
+ QMutexLocker locker(&m_mutex);
+ if (alloc) {
+ alloc->AddRef();
+ }
+ if (m_memAlloc) {
+ m_memAlloc->Release();
+ }
+ m_memAlloc = alloc;
+ }
+
+ IMemAllocator *QPin::memoryAllocator(bool addref) const
+ {
+ QMutexLocker locker(&m_mutex);
+ if (addref && m_memAlloc) {
+ m_memAlloc->AddRef();
+ }
+ return m_memAlloc;
+ }
+
+ AM_MEDIA_TYPE QPin::copyMediaType(const AM_MEDIA_TYPE &type)
+ {
+ AM_MEDIA_TYPE ret = type;
+
+ //make a deep copy here
+ if (ret.cbFormat == 0 || ret.pbFormat == 0) {
+ ret.cbFormat = 0;
+ ret.pbFormat = 0;
+ ret.formattype = GUID_NULL;
+ } else {
+ ret.pbFormat = reinterpret_cast<BYTE*>(::CoTaskMemAlloc(type.cbFormat));
+ qMemCopy(ret.pbFormat, type.pbFormat, type.cbFormat);
+ }
+
+ if (type.pUnk) {
+ type.pUnk->AddRef();
+ }
+ return ret;
+ }
+
+
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/qpin.h b/src/3rdparty/phonon/ds9/qpin.h
new file mode 100644
index 0000000..280ad61
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/qpin.h
@@ -0,0 +1,120 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_QPIN_H
+#define PHONON_QPIN_H
+
+#include "phononds9_namespace.h"
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtCore/QMutex>
+
+#include <dshow.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class QBaseFilter;
+
+ //this is the base class for our self-implemented Pins
+ class QPin : public IPin
+ {
+ public:
+ QPin(QBaseFilter *parent, PIN_DIRECTION dir, const QVector<AM_MEDIA_TYPE> &mt);
+ virtual ~QPin();
+
+ //reimplementation from IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void** out);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ //reimplementation from IPin
+ STDMETHODIMP Connect(IPin *,const AM_MEDIA_TYPE *);
+ STDMETHODIMP ReceiveConnection(IPin *,const AM_MEDIA_TYPE *);
+ STDMETHODIMP Disconnect();
+ STDMETHODIMP ConnectedTo(IPin **);
+ STDMETHODIMP ConnectionMediaType(AM_MEDIA_TYPE *);
+ STDMETHODIMP QueryPinInfo(PIN_INFO *);
+ STDMETHODIMP QueryDirection(PIN_DIRECTION *);
+ STDMETHODIMP QueryId(LPWSTR*);
+ STDMETHODIMP QueryAccept(const AM_MEDIA_TYPE*);
+ STDMETHODIMP EnumMediaTypes(IEnumMediaTypes **);
+ STDMETHODIMP QueryInternalConnections(IPin **, ULONG*);
+ STDMETHODIMP EndOfStream();
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
+ STDMETHODIMP NewSegment(REFERENCE_TIME, REFERENCE_TIME, double);
+
+ QVector<AM_MEDIA_TYPE> mediaTypes() const;
+
+ HRESULT setAcceptedMediaType(const AM_MEDIA_TYPE &);
+
+ bool isFlushing() const;
+ void setConnectedType(const AM_MEDIA_TYPE &type);
+ const AM_MEDIA_TYPE &connectedType() const;
+ void setConnected(IPin *pin);
+ IPin *connected(bool = false) const;
+ void setMemoryAllocator(IMemAllocator *alloc);
+ IMemAllocator *memoryAllocator(bool = false) const;
+ void createDefaultMemoryAllocator(ALLOCATOR_PROPERTIES * = 0);
+ PIN_DIRECTION direction() const;
+
+ FILTER_STATE filterState() const;
+
+ static AM_MEDIA_TYPE copyMediaType(const AM_MEDIA_TYPE &type);
+ static void freeMediaType(AM_MEDIA_TYPE *type);
+ static void freeMediaType(const AM_MEDIA_TYPE &type);
+
+ protected:
+ //this can be used by sub-classes
+ mutable QMutex m_mutex;
+ QBaseFilter * const m_parent;
+ bool m_flushing;
+
+ private:
+ HRESULT checkOutputMediaTypesConnection(IPin *pin);
+ HRESULT checkOwnMediaTypesConnection(IPin *pin);
+
+ LONG m_refCount;
+ IPin *m_connected;
+ const PIN_DIRECTION m_direction;
+ QVector<AM_MEDIA_TYPE> m_mediaTypes; //accepted media types
+ AM_MEDIA_TYPE m_connectedType;
+ IMemAllocator *m_memAlloc;
+ };
+
+ //utility function
+ class QAMMediaType : public AM_MEDIA_TYPE
+ {
+ public:
+ ~QAMMediaType()
+ {
+ QPin::freeMediaType(*this);
+ }
+
+ };
+
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //PHONON_QPIN_H
diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.cpp b/src/3rdparty/phonon/ds9/videorenderer_default.cpp
new file mode 100644
index 0000000..0045a49
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_default.cpp
@@ -0,0 +1,153 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "videorenderer_default.h"
+
+#ifndef QT_NO_PHONON_VIDEO
+
+#include <QtGui/QWidget>
+#include <QtGui/QPainter>
+
+#include <uuids.h>
+
+QT_BEGIN_NAMESPACE
+
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ VideoRendererDefault::~VideoRendererDefault()
+ {
+ }
+
+ bool VideoRendererDefault::isNative() const
+ {
+ return true;
+ }
+
+
+ VideoRendererDefault::VideoRendererDefault(QWidget *target) : m_target(target)
+ {
+ m_target->setAttribute(Qt::WA_PaintOnScreen, true);
+ m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter);
+ }
+
+ QSize VideoRendererDefault::videoSize() const
+ {
+ LONG w = 0,
+ h = 0;
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->GetVideoSize( &w, &h);
+ }
+ return QSize(w, h);
+ }
+
+ void VideoRendererDefault::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/)
+ {
+ //nothing to do here: the renderer paints everything
+ }
+
+ void VideoRendererDefault::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
+ Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ if (!isActive()) {
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->SetDestinationPosition(0, 0, 0, 0);
+ }
+ return;
+ }
+
+ ComPointer<IVideoWindow> video(m_filter, IID_IVideoWindow);
+
+ OAHWND owner;
+ HRESULT hr = video->get_Owner(&owner);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ const OAHWND newOwner = reinterpret_cast<OAHWND>(m_target->winId());
+ if (owner != newOwner) {
+ video->put_Owner(newOwner);
+ video->put_MessageDrain(newOwner);
+ video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+ }
+
+ //make sure the widget takes the whole size of the parent
+ video->SetWindowPosition(0, 0, size.width(), size.height());
+
+ const QSize vsize = videoSize();
+ internalNotifyResize(size, vsize, aspectRatio, scaleMode);
+
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight);
+ }
+ }
+
+ void VideoRendererDefault::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/)
+ {
+ //this can't be supported for the default renderer
+ }
+
+ QImage VideoRendererDefault::snapshot() const
+ {
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ LONG bufferSize = 0;
+ //1st we get the buffer size
+ basic->GetCurrentImage(&bufferSize, 0);
+
+ QByteArray buffer;
+ buffer.resize(bufferSize);
+ HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast<long*>(buffer.data()));
+
+ if (SUCCEEDED(hr)) {
+
+ const BITMAPINFOHEADER *bmi = reinterpret_cast<const BITMAPINFOHEADER*>(buffer.constData());
+
+ const int w = qAbs(bmi->biWidth),
+ h = qAbs(bmi->biHeight);
+
+ // Create image and copy data into image.
+ QImage ret(w, h, QImage::Format_RGB32);
+
+ if (!ret.isNull()) {
+ const char *data = buffer.constData() + bmi->biSize;
+ const int bytes_per_line = w * sizeof(QRgb);
+ for (int y = h - 1; y >= 0; --y) {
+ qMemCopy(ret.scanLine(y), //destination
+ data, //source
+ bytes_per_line);
+ data += bytes_per_line;
+ }
+ }
+ return ret;
+ }
+ }
+ return QImage();
+ }
+
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.h b/src/3rdparty/phonon/ds9/videorenderer_default.h
new file mode 100644
index 0000000..43768d9
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_default.h
@@ -0,0 +1,55 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_VIDEORENDERER_DEFAULT_H
+#define PHONON_VIDEORENDERER_DEFAULT_H
+
+#include "abstractvideorenderer.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class VideoRendererDefault : public AbstractVideoRenderer
+ {
+ public:
+ VideoRendererDefault(QWidget *target);
+ ~VideoRendererDefault();
+
+ //Implementation from AbstractVideoRenderer
+ void repaintCurrentFrame(QWidget *target, const QRect &rect);
+ void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode);
+ QSize videoSize() const;
+ QImage snapshot() const;
+ void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation);
+ bool isNative() const;
+ private:
+ QWidget *m_target;
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp
new file mode 100644
index 0000000..ff39ecc
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp
@@ -0,0 +1,219 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "videorenderer_evr.h"
+#include "qevr9.h"
+
+#ifndef QT_NO_PHONON_VIDEO
+
+#include <QtGui/QWidget>
+#include <QtGui/QPainter>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ //we have to define them here because not all compilers/sdk have them
+ static const GUID MR_VIDEO_RENDER_SERVICE = {0x1092a86c, 0xab1a, 0x459a, {0xa3, 0x36, 0x83, 0x1f, 0xbc, 0x4d, 0x11, 0xff} };
+ static const GUID MR_VIDEO_MIXER_SERVICE = { 0x73cd2fc, 0x6cf4, 0x40b7, {0x88, 0x59, 0xe8, 0x95, 0x52, 0xc8, 0x41, 0xf8} };
+ static const IID IID_IMFVideoDisplayControl = {0xa490b1e4, 0xab84, 0x4d31, {0xa1, 0xb2, 0x18, 0x1e, 0x03, 0xb1, 0x07, 0x7a} };
+ static const IID IID_IMFVideoMixerControl = {0xA5C6C53F, 0xC202, 0x4aa5, {0x96, 0x95, 0x17, 0x5B, 0xA8, 0xC5, 0x08, 0xA5} };
+ static const IID IID_IMFVideoProcessor = {0x6AB0000C, 0xFECE, 0x4d1f, {0xA2, 0xAC, 0xA9, 0x57, 0x35, 0x30, 0x65, 0x6E} };
+ static const IID IID_IMFGetService = {0xFA993888, 0x4383, 0x415A, {0xA9, 0x30, 0xDD, 0x47, 0x2A, 0x8C, 0xF6, 0xF7} };
+ static const GUID CLSID_EnhancedVideoRenderer = {0xfa10746c, 0x9b63, 0x4b6c, {0xbc, 0x49, 0xfc, 0x30, 0xe, 0xa5, 0xf2, 0x56} };
+
+ template <typename T> ComPointer<T> getService(const Filter &filter, REFGUID guidService, REFIID riid)
+ {
+ //normally we should use IID_IMFGetService but this introduces another dependency
+ //so here we simply define our own IId with the same value
+ ComPointer<T> ret;
+ ComPointer<IMFGetService> getService(filter, IID_IMFGetService);
+ if (getService) {
+ getService->GetService(guidService, riid, reinterpret_cast<void**>(ret.pparam()));
+ }
+ return ret;
+ }
+
+ VideoRendererEVR::~VideoRendererEVR()
+ {
+ }
+
+ bool VideoRendererEVR::isNative() const
+ {
+ return true;
+ }
+
+ VideoRendererEVR::VideoRendererEVR(QWidget *target) : m_target(target)
+ {
+ if (QSysInfo::WindowsVersion < QSysInfo::WV_VISTA)
+ return;
+ m_filter = Filter(CLSID_EnhancedVideoRenderer, IID_IBaseFilter);
+ if (!m_filter) {
+ return;
+ }
+
+ ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
+ if (!filterControl ||
+ FAILED(filterControl->SetVideoWindow(reinterpret_cast<HWND>(target->winId()))) ||
+ FAILED(filterControl->SetAspectRatioMode(MFVideoARMode_None)) || // We're in control of the size
+ !getService<IMFVideoMixerControl>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoMixerControl) ||
+ !getService<IMFVideoProcessor>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoProcessor)) {
+ m_filter = Filter(); //will release the interface
+ }
+ }
+
+ QImage VideoRendererEVR::snapshot() const
+ {
+ // This will always capture black areas where no video is drawn, if any are present.
+ // Due to the hack in notifyResize()
+ ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
+ if (filterControl) {
+ BITMAPINFOHEADER bmi;
+ BYTE *buffer = 0;
+ DWORD bufferSize;
+ LONGLONG timeStamp;
+
+ bmi.biSize = sizeof(BITMAPINFOHEADER);
+
+ HRESULT hr = filterControl->GetCurrentImage(&bmi, &buffer, &bufferSize, &timeStamp);
+ if (SUCCEEDED(hr)) {
+
+ const int w = qAbs(bmi.biWidth),
+ h = qAbs(bmi.biHeight);
+
+ // Create image and copy data into image.
+ QImage ret(w, h, QImage::Format_RGB32);
+
+ if (!ret.isNull()) {
+ uchar *data = buffer;
+ const int bytes_per_line = w * sizeof(QRgb);
+ for (int y = h - 1; y >= 0; --y) {
+ qMemCopy(ret.scanLine(y), //destination
+ data, //source
+ bytes_per_line);
+ data += bytes_per_line;
+ }
+ }
+ ::CoTaskMemFree(buffer);
+ return ret;
+ }
+ }
+ return QImage();
+ }
+
+ QSize VideoRendererEVR::videoSize() const
+ {
+ SIZE nativeSize;
+ SIZE aspectRatioSize;
+
+ ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
+
+ filterControl->GetNativeVideoSize(&nativeSize, &aspectRatioSize);
+
+ return QSize(nativeSize.cx, nativeSize.cy);
+ }
+
+ void VideoRendererEVR::repaintCurrentFrame(QWidget *target, const QRect &rect)
+ {
+ // repaint the video
+ ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
+ // All failed results can be safely ignored
+ filterControl->RepaintVideo();
+ }
+
+ void VideoRendererEVR::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
+ Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ if (!isActive()) {
+ RECT dummyRect = { 0, 0, 0, 0};
+ ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
+ filterControl->SetVideoPosition(0, &dummyRect);
+ return;
+ }
+
+ const QSize vsize = videoSize();
+ internalNotifyResize(size, vsize, aspectRatio, scaleMode);
+
+ RECT dstRectWin = { 0, 0, size.width(), size.height()};
+
+ // Resize the Stream output rect instead of the destination rect.
+ // Hacky workaround for flicker in the areas outside of the destination rect
+ // This way these areas don't exist
+ MFVideoNormalizedRect streamOutputRect = { float(m_dstX) / float(size.width()), float(m_dstY) / float(size.height()),
+ float(m_dstWidth + m_dstX) / float(size.width()), float(m_dstHeight + m_dstY) / float(size.height())};
+
+ ComPointer<IMFVideoMixerControl> filterMixer = getService<IMFVideoMixerControl>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoMixerControl);
+ ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
+
+ filterMixer->SetStreamOutputRect(0, &streamOutputRect);
+ filterControl->SetVideoPosition(0, &dstRectWin);
+ }
+
+ void VideoRendererEVR::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first();
+ OutputPin source;
+ if (FAILED(sink->ConnectedTo(source.pparam()))) {
+ return; //it must be connected to work
+ }
+
+ // Get the "Video Processor" (used for brightness/contrast/saturation/hue)
+ ComPointer<IMFVideoProcessor> processor = getService<IMFVideoProcessor>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoProcessor);
+ Q_ASSERT(processor);
+
+ DXVA2_ValueRange contrastRange;
+ DXVA2_ValueRange brightnessRange;
+ DXVA2_ValueRange saturationRange;
+ DXVA2_ValueRange hueRange;
+
+ if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &contrastRange)))
+ return;
+ if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &brightnessRange)))
+ return;
+ if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &saturationRange)))
+ return;
+ if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Hue, &hueRange)))
+ return;
+
+ DXVA2_ProcAmpValues values;
+
+ values.Contrast = DXVA2FloatToFixed(((contrast < 0
+ ? DXVA2FixedToFloat(contrastRange.MinValue) : DXVA2FixedToFloat(contrastRange.MaxValue))
+ - DXVA2FixedToFloat(contrastRange.DefaultValue)) * qAbs(contrast) + DXVA2FixedToFloat(contrastRange.DefaultValue));
+ values.Brightness = DXVA2FloatToFixed(((brightness < 0
+ ? DXVA2FixedToFloat(brightnessRange.MinValue) : DXVA2FixedToFloat(brightnessRange.MaxValue))
+ - DXVA2FixedToFloat(brightnessRange.DefaultValue)) * qAbs(brightness) + DXVA2FixedToFloat(brightnessRange.DefaultValue));
+ values.Saturation = DXVA2FloatToFixed(((saturation < 0
+ ? DXVA2FixedToFloat(saturationRange.MinValue) : DXVA2FixedToFloat(saturationRange.MaxValue))
+ - DXVA2FixedToFloat(saturationRange.DefaultValue)) * qAbs(saturation) + DXVA2FixedToFloat(saturationRange.DefaultValue));
+ values.Hue = DXVA2FloatToFixed(((hue < 0
+ ? DXVA2FixedToFloat(hueRange.MinValue) : DXVA2FixedToFloat(hueRange.MaxValue))
+ - DXVA2FixedToFloat(hueRange.DefaultValue)) * qAbs(hue) + DXVA2FixedToFloat(hueRange.DefaultValue));
+
+ //finally set the settings
+ processor->SetProcAmpValues(DXVA2_ProcAmp_Contrast | DXVA2_ProcAmp_Brightness | DXVA2_ProcAmp_Saturation | DXVA2_ProcAmp_Hue, &values);
+
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.h b/src/3rdparty/phonon/ds9/videorenderer_evr.h
new file mode 100644
index 0000000..229c36d
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_evr.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_VIDEORENDERER_EVR_H
+#define PHONON_VIDEORENDERER_EVR_H
+
+#include "abstractvideorenderer.h"
+#include "compointer.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class VideoRendererEVR : public AbstractVideoRenderer
+ {
+ public:
+ VideoRendererEVR(QWidget *target);
+ ~VideoRendererEVR();
+
+ //Implementation from AbstractVideoRenderer
+ void repaintCurrentFrame(QWidget *target, const QRect &rect);
+ void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode);
+ QSize videoSize() const;
+ QImage snapshot() const;
+ void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation);
+ bool isNative() const;
+ private:
+ QWidget *m_target;
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp
new file mode 100644
index 0000000..9c7993c
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp
@@ -0,0 +1,1008 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "videorenderer_soft.h"
+
+#ifndef QT_NO_PHONON_VIDEO
+
+#include "qmeminputpin.h"
+#include "qbasefilter.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QPaintEngine>
+#include <QtGui/QApplication>
+#include <QtCore/QTime>
+
+#define _USE_MATH_DEFINES //for pi
+#include <QtCore/qmath.h> //for sin and cos
+/* M_PI is a #define that may or may not be handled in <cmath> */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327950288419717
+#endif
+
+#include <dvdmedia.h> //for VIDEOINFOHEADER2
+
+//this will make a display every second of how many frames were pocessed and actually displayed
+//#define FPS_COUNTER
+
+#ifdef Q_OS_WINCE
+#define QT_NO_OPENGL
+#endif
+
+#ifndef QT_NO_OPENGL
+#include <GL/gl.h>
+#ifndef GL_FRAGMENT_PROGRAM_ARB
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#endif
+
+// support old OpenGL installations (1.2)
+// assume that if TEXTURE0 isn't defined, none are
+#ifndef GL_TEXTURE0
+# define GL_TEXTURE0 0x84C0
+# define GL_TEXTURE1 0x84C1
+# define GL_TEXTURE2 0x84C2
+#endif
+
+// arbfp1 fragment program for converting yuv (YV12) to rgb
+static const char yv12ToRgb[] =
+"!!ARBfp1.0"
+"PARAM c[5] = { program.local[0..1],"
+"{ 1.164, 0, 1.596, 0.5 },"
+"{ 0.0625, 1.164, -0.391, -0.81300002 },"
+"{ 1.164, 2.0179999, 0 } };"
+"TEMP R0;"
+"TEX R0.x, fragment.texcoord[0], texture[1], 2D;"
+"ADD R0.y, R0.x, -c[2].w;"
+"TEX R0.x, fragment.texcoord[0], texture[2], 2D;"
+"ADD R0.x, R0, -c[2].w;"
+"MUL R0.z, R0.y, c[0].w;"
+"MAD R0.z, R0.x, c[0], R0;"
+"MUL R0.w, R0.x, c[0];"
+"MUL R0.z, R0, c[0].y;"
+"TEX R0.x, fragment.texcoord[0], texture[0], 2D;"
+"MAD R0.y, R0, c[0].z, R0.w;"
+"ADD R0.x, R0, -c[3];"
+"MUL R0.y, R0, c[0];"
+"MUL R0.z, R0, c[1].x;"
+"MAD R0.x, R0, c[0].y, c[0];"
+"MUL R0.y, R0, c[1].x;"
+"DP3 result.color.x, R0, c[2];"
+"DP3 result.color.y, R0, c[3].yzww;"
+"DP3 result.color.z, R0, c[4];"
+"MOV result.color.w, c[1].y;"
+"END";
+
+static const char yuy2ToRgb[] =
+"!!ARBfp1.0"
+"PARAM c[5] = { program.local[0..1],"
+"{ 0.5, 2, 1, 0.0625 },"
+"{ 1.164, 0, 1.596, 2.0179999 },"
+"{ 1.164, -0.391, -0.81300002 } };"
+"TEMP R0;"
+"TEMP R1;"
+"TEMP R2;"
+"FLR R1.z, fragment.texcoord[0].x;"
+"ADD R0.x, R1.z, c[2];"
+"ADD R1.z, fragment.texcoord[0].x, -R1;"
+"MUL R1.x, fragment.texcoord[0].z, R0;"
+"MOV R1.y, fragment.texcoord[0];"
+"TEX R0, R1, texture[0], 2D;"
+"ADD R1.y, R0.z, -R0.x;"
+"MUL R2.x, R1.z, R1.y;"
+"MAD R0.x, R2, c[2].y, R0;"
+"MOV R1.y, fragment.texcoord[0];"
+"ADD R1.x, fragment.texcoord[0].z, R1;"
+"TEX R1.xyw, R1, texture[0], 2D;"
+"ADD R2.x, R1, -R0.z;"
+"MAD R1.x, R1.z, c[2].y, -c[2].z;"
+"MAD R0.z, R1.x, R2.x, R0;"
+"ADD R1.xy, R1.ywzw, -R0.ywzw;"
+"ADD R0.z, R0, -R0.x;"
+"SGE R1.w, R1.z, c[2].x;"
+"MAD R0.x, R1.w, R0.z, R0;"
+"MAD R0.yz, R1.z, R1.xxyw, R0.xyww;"
+"ADD R0.xyz, R0, -c[2].wxxw;"
+"MUL R0.w, R0.y, c[0];"
+"MAD R0.w, R0.z, c[0].z, R0;"
+"MUL R0.z, R0, c[0].w;"
+"MAD R0.y, R0, c[0].z, R0.z;"
+"MUL R0.w, R0, c[0].y;"
+"MUL R0.y, R0, c[0];"
+"MUL R0.z, R0.w, c[1].x;"
+"MAD R0.x, R0, c[0].y, c[0];"
+"MUL R0.y, R0, c[1].x;"
+"DP3 result.color.x, R0, c[3];"
+"DP3 result.color.y, R0, c[4];"
+"DP3 result.color.z, R0, c[3].xwyw;"
+"MOV result.color.w, c[1].y;"
+"END";
+
+#endif //QT_NO_OPENGL
+
+#define CLIP_SHIFT_RIGHT_8(c) ((c) < 0 ? 0 : (c) > 0xffff ? 0xff : (c) >> 8)
+#define CLIP_SHIFT_LEFT_8(c) ((c) < 0 ? 0 : (c) > 0xffff ? 0xff0000 : ( ((c) << 8) & 0xff0000) )
+#define CLIP_NO_SHIFT(c) ((c) < 0 ? 0 : (c) > 0xffff ? 0xff00 : ((c) & 0xff00) )
+#define CLIPPED_PIXEL(base, r, g, b) (0xff000000u | CLIP_SHIFT_LEFT_8(base+r) | CLIP_NO_SHIFT(base+g) | CLIP_SHIFT_RIGHT_8(base+b))
+#define CLIPPED_PIXEL2(r, g, b) (0xff000000u | CLIP_SHIFT_LEFT_8(r) | CLIP_NO_SHIFT(g) | CLIP_SHIFT_RIGHT_8(b))
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ static const QVector<AM_MEDIA_TYPE> videoMediaTypes()
+ {
+ AM_MEDIA_TYPE mt = { MEDIATYPE_Video, MEDIASUBTYPE_YV12, 0, 0, 0, GUID_NULL, 0, 0, 0 };
+
+ QVector<AM_MEDIA_TYPE> ret;
+
+ //we add all the subtypes we support
+ ret << mt; //YV12
+ mt.subtype = MEDIASUBTYPE_YUY2;
+ ret << mt; //YUY2
+ mt.subtype = MEDIASUBTYPE_RGB32;
+ ret << mt; //RGB32
+
+ return ret;
+ }
+
+ class VideoRendererSoftFilter : public QBaseFilter
+ {
+ public:
+ VideoRendererSoftFilter(VideoRendererSoft *renderer);
+
+ ~VideoRendererSoftFilter();
+
+ QSize videoSize() const;
+
+#ifndef QT_NO_OPENGL
+ void freeGLResources()
+ {
+ if (m_usingOpenGL) {
+ //let's reinitialize those values
+ m_usingOpenGL = false;
+ //to be sure we recreate it
+ if (m_textureUploaded) {
+ glDeleteTextures(3, m_texture);
+ m_textureUploaded = false;
+ }
+ }
+ m_checkedPrograms = false;
+ }
+#endif // QT_NO_OPENGL
+
+ void freeResources()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_sampleBuffer = ComPointer<IMediaSample>();
+#ifndef QT_NO_OPENGL
+ freeGLResources();
+ m_textureUploaded = false;
+#endif // QT_NO_OPENGL
+ }
+
+ void endOfStream()
+ {
+ //received from the input pin
+ ::SetEvent(m_receiveCanWait); //unblocks the flow
+
+ //we send the message to the graph
+ ComPointer<IMediaEventSink> sink(graph(), IID_IMediaEventSink);
+ if (sink) {
+ sink->Notify(EC_COMPLETE, S_OK,
+ reinterpret_cast<LONG_PTR>(static_cast<IBaseFilter*>(this)));
+ }
+ }
+
+ void freeMediaSample()
+ {
+ QMutexLocker locker(&m_mutex);
+ m_sampleBuffer = ComPointer<IMediaSample>();
+ }
+
+ void beginFlush()
+ {
+ freeMediaSample();
+ ::SetEvent(m_receiveCanWait); //unblocks the flow
+ }
+
+ void endFlush()
+ {
+ if (m_inputPin->connected() == 0) {
+ ::SetEvent(m_receiveCanWait); //unblock the flow in receive
+ } else {
+ ::ResetEvent(m_receiveCanWait); //block the flow again
+ }
+ }
+
+ STDMETHODIMP Stop()
+ {
+ HRESULT hr = QBaseFilter::Stop();
+ beginFlush();
+ return hr;
+ }
+
+ STDMETHODIMP Pause()
+ {
+ HRESULT hr = QBaseFilter::Pause();
+ if (m_inputPin->connected() == 0) {
+ ::SetEvent(m_receiveCanWait); //unblock the flow in receive
+ } else {
+ ::ResetEvent(m_receiveCanWait); //this will block
+ }
+ return hr;
+ }
+
+ STDMETHODIMP Run(REFERENCE_TIME start)
+ {
+ HRESULT hr = QBaseFilter::Run(start);
+ m_start = start;
+
+ if (m_inputPin->connected() == 0) {
+ endOfStream();
+ } else {
+ ::SetEvent(m_receiveCanWait); //unblocks the flow (this event will block then again)
+ }
+
+#ifdef FPS_COUNTER
+ fpsTime.restart();
+ nbFramesProcessed = 0;
+ nbFramesDisplayed = 0;
+#endif
+
+ return hr;
+ }
+
+ HRESULT processSample(IMediaSample *sample);
+
+ void applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ //let's normalize the values
+ m_brightness = brightness * 128;
+ m_contrast = contrast + 1.;
+ m_hue = hue * M_PI;
+ m_saturation = saturation + 1.;
+ }
+
+ QImage currentImage() const
+ {
+ return m_currentImage;
+ }
+
+ void setCurrentImage(const QImage &image)
+ {
+ QMutexLocker locker(&m_mutex);
+ m_currentImage = image;
+ }
+
+ //the following function is called from the GUI thread
+ void repaintCurrentFrame(QPainter &painter, const QRect &r);
+
+
+ protected:
+ static void convertYV12toRGB(const uchar *data, const QSize &s, QImage &dest,
+ qreal brightness, qreal contrast, qreal hue, qreal saturation);
+ static void convertYUY2toRGB(const uchar *data, const QSize &s, QImage &dest,
+ qreal brightness, qreal contrast, qreal hue, qreal saturation);
+ static void normalizeRGB(const uchar *data, const QSize &s, QImage &destImage);
+
+ private:
+ QPin *const m_inputPin;
+ ComPointer<IMediaSample> m_sampleBuffer;
+ QImage m_currentImage;
+
+
+ VideoRendererSoft *m_renderer;
+ mutable QMutex m_mutex;
+ REFERENCE_TIME m_start;
+ HANDLE m_renderEvent, m_receiveCanWait; // Signals sample to render
+ QSize m_size;
+
+ //mixer settings
+ qreal m_brightness,
+ m_contrast,
+ m_hue,
+ m_saturation;
+
+#ifdef FPS_COUNTER
+ QTime fpsTime;
+ int nbFramesProcessed;
+ int nbFramesDisplayed;
+#endif
+
+#ifndef QT_NO_OPENGL
+ enum Program
+ {
+ YV12toRGB = 0,
+ YUY2toRGB = 1,
+ ProgramCount = 2
+ };
+
+ void updateTexture();
+ bool checkGLPrograms();
+
+ // ARB_fragment_program
+ 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;
+ _glActiveTexture glActiveTexture;
+
+ bool m_checkedPrograms;
+ bool m_usingOpenGL;
+ bool m_textureUploaded;
+ GLuint m_program[2];
+ GLuint m_texture[3];
+#endif
+ };
+
+ class VideoRendererSoftPin : public QMemInputPin
+ {
+ public:
+ VideoRendererSoftPin(VideoRendererSoftFilter *parent) :
+ QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/, 0),
+ m_renderer(parent)
+ {
+ }
+
+ STDMETHODIMP EndOfStream()
+ {
+ m_renderer->endOfStream();
+ return QMemInputPin::EndOfStream();
+ }
+
+ STDMETHODIMP ReceiveCanBlock()
+ {
+ //yes, it can block
+ return S_OK;
+ }
+
+ STDMETHODIMP BeginFlush()
+ {
+ m_renderer->beginFlush();
+ return QMemInputPin::BeginFlush();
+ }
+
+ STDMETHODIMP EndFlush()
+ {
+ m_renderer->endFlush();
+ return QMemInputPin::EndFlush();
+ }
+
+
+ STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *prop)
+ {
+ if (!prop) {
+ return E_POINTER;
+ }
+
+ //we need 2 buffers
+ prop->cBuffers = 2;
+ return S_OK;
+ }
+
+
+ STDMETHODIMP NotifyAllocator(IMemAllocator *alloc, BOOL readonly)
+ {
+ if (!alloc) {
+ return E_POINTER;
+ }
+ ALLOCATOR_PROPERTIES prop;
+ HRESULT hr = alloc->GetProperties(&prop);
+ if (SUCCEEDED(hr) && prop.cBuffers == 1) {
+ //we ask to get 2 buffers so that we don't block the flow
+ //when we addref the mediasample
+ prop.cBuffers = 2;
+ ALLOCATOR_PROPERTIES dummy;
+ alloc->SetProperties(&prop, &dummy);
+ }
+
+ return QMemInputPin::NotifyAllocator(alloc, readonly);
+ }
+
+
+
+ private:
+ VideoRendererSoftFilter * const m_renderer;
+
+ };
+
+ VideoRendererSoftFilter::VideoRendererSoftFilter(VideoRendererSoft *renderer) :
+ QBaseFilter(CLSID_NULL), m_inputPin(new VideoRendererSoftPin(this)),
+ m_renderer(renderer), m_start(0)
+#ifndef QT_NO_OPENGL
+ , m_checkedPrograms(false), m_usingOpenGL(false), m_textureUploaded(false)
+#endif
+ {
+ m_renderEvent = ::CreateEvent(0, 0, 0, 0);
+ m_receiveCanWait = ::CreateEvent(0, 0, 0, 0);
+ //simply initialize the array with default values
+ applyMixerSettings(0., 0., 0., 0.);
+#ifndef QT_NO_OPENGL
+#endif
+ }
+
+ VideoRendererSoftFilter::~VideoRendererSoftFilter()
+ {
+ ::CloseHandle(m_renderEvent);
+ ::CloseHandle(m_receiveCanWait);
+ //this frees up resources
+ freeResources();
+ }
+
+ QSize VideoRendererSoftFilter::videoSize() const
+ {
+ QSize ret;
+ const AM_MEDIA_TYPE &mt = m_inputPin->connectedType();
+ if (mt.pbFormat && mt.pbFormat) {
+ if (mt.formattype == FORMAT_VideoInfo) {
+ const VIDEOINFOHEADER *header = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
+ const int h = qAbs(header->bmiHeader.biHeight),
+ w = qAbs(header->bmiHeader.biWidth);
+ ret = QSize(w, h);
+ } else if (mt.formattype == FORMAT_VideoInfo2) {
+ const VIDEOINFOHEADER2 *header = reinterpret_cast<VIDEOINFOHEADER2*>(mt.pbFormat);
+ const int h = qAbs(header->bmiHeader.biHeight),
+ w = qAbs(header->bmiHeader.biWidth);
+ ret = QSize(w, h);
+ }
+ }
+ return ret;
+ }
+
+
+ HRESULT VideoRendererSoftFilter::processSample(IMediaSample *sample)
+ {
+#ifdef FPS_COUNTER
+ if (fpsTime.elapsed() > 1000) {
+ qDebug("FPS_COUNTER: processed=%d, displayed=%d (%d)", nbFramesProcessed, nbFramesDisplayed, fpsTime.elapsed());
+ nbFramesProcessed = 0;
+ nbFramesDisplayed = 0;
+ fpsTime.restart();
+
+ }
+#endif
+
+ AM_MEDIA_TYPE *type = 0;
+ if (sample->GetMediaType(&type) == S_OK) {
+ //let's update the media type of the input pin
+ m_inputPin->setConnectedType(*type);
+ }
+
+
+ const AM_MEDIA_TYPE &mt = m_inputPin->connectedType();
+
+ if (mt.pbFormat == 0 || mt.cbFormat == 0) {
+ return VFW_E_INVALIDMEDIATYPE;
+ }
+
+ m_size = videoSize();
+ if (!m_size.isValid()) {
+ return VFW_E_INVALIDMEDIATYPE;
+ }
+
+#ifdef FPS_COUNTER
+ nbFramesProcessed++;
+#endif
+
+ REFERENCE_TIME start = 0, stop = 0;
+ HRESULT hr = sample->GetTime(&start, &stop);
+
+ ComPointer<IReferenceClock> clock;
+ GetSyncSource(clock.pparam());
+
+ const bool playing = SUCCEEDED(hr) && state() == State_Running && clock;
+
+ if (playing) {
+ REFERENCE_TIME current;
+ clock->GetTime(&current);
+
+ DWORD_PTR advise;
+
+ //let's synchronize here
+ clock->AdviseTime(m_start, start,
+ reinterpret_cast<HEVENT>(m_renderEvent), &advise);
+
+ HANDLE handles[] = {m_receiveCanWait, m_renderEvent};
+ if (::WaitForMultipleObjects(2, handles, false, INFINITE) == WAIT_OBJECT_0) {
+ if (state() != State_Stopped && !m_inputPin->isFlushing()) {
+ ::ResetEvent(m_receiveCanWait);
+ }
+ }
+ }
+
+
+ //the let's lock the sample to be used in the GUI thread
+ {
+ QMutexLocker locker(&m_mutex);
+ sample->AddRef();
+ m_sampleBuffer = ComPointer<IMediaSample>(sample);
+ }
+
+ //image is updated: we should update the widget
+ //we should never call directly members of target due to thread-safety
+ QApplication::postEvent(m_renderer, new QEvent(QEvent::UpdateRequest));
+
+ if (!playing) {
+ //useless to test the return value of WaitForSingleObject: timeout can't happen
+ ::WaitForSingleObject(m_receiveCanWait, INFINITE);
+ if (state() != State_Stopped && !m_inputPin->isFlushing()) {
+ ::ResetEvent(m_receiveCanWait);
+ }
+ }
+
+ //everything should be ok
+ return S_OK;
+ }
+
+#ifndef QT_NO_OPENGL
+ bool VideoRendererSoftFilter::checkGLPrograms()
+ {
+ if (!m_checkedPrograms) {
+ m_checkedPrograms = true;
+
+ glProgramStringARB = (_glProgramStringARB) wglGetProcAddress("glProgramStringARB");
+ glBindProgramARB = (_glBindProgramARB) wglGetProcAddress("glBindProgramARB");
+ glDeleteProgramsARB = (_glDeleteProgramsARB) wglGetProcAddress("glDeleteProgramsARB");
+ glGenProgramsARB = (_glGenProgramsARB) wglGetProcAddress("glGenProgramsARB");
+ glProgramLocalParameter4fARB = (_glProgramLocalParameter4fARB) wglGetProcAddress("glProgramLocalParameter4fARB");
+ glActiveTexture = (_glActiveTexture) wglGetProcAddress("glActiveTexture");
+
+ //we check only once if the widget is drawn using opengl
+ if (glProgramStringARB && glBindProgramARB && glDeleteProgramsARB &&
+ glGenProgramsARB && glActiveTexture && glProgramLocalParameter4fARB) {
+ glGenProgramsARB(2, m_program);
+
+ const char *code[] = {yv12ToRgb, yuy2ToRgb};
+
+ bool error = false;
+ for(int i = 0; i < ProgramCount && !error; ++i) {
+
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_program[i]);
+
+ const GLbyte *gl_src = reinterpret_cast<const GLbyte *>(code[i]);
+ glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(code[i]), gl_src);
+
+ if (glGetError() != GL_NO_ERROR) {
+ error = true;
+ }
+ }
+
+ if (error) {
+ glDeleteProgramsARB(2, m_program);
+ } else {
+ //everything went fine we store the context here (we support YV12 and YUY2)
+ m_usingOpenGL = m_inputPin->connectedType().subtype == MEDIASUBTYPE_YV12
+ || m_inputPin->connectedType().subtype == MEDIASUBTYPE_YUY2;
+ //those "textures" will be used as byte streams
+ //to pass Y, U and V data to the graphics card
+ glGenTextures(3, m_texture);
+ }
+ }
+ }
+ return m_usingOpenGL;
+ }
+
+ void VideoRendererSoftFilter::updateTexture()
+ {
+ if (!m_sampleBuffer) {
+ return; //the texture is already up2date or their is no data yet
+ }
+
+ uchar *data = 0;
+ m_sampleBuffer->GetPointer(&data);
+
+ if (m_inputPin->connectedType().subtype == MEDIASUBTYPE_YV12) {
+ int w[3] = { m_size.width(), m_size.width()/2, m_size.width()/2 };
+ int h[3] = { m_size.height(), m_size.height()/2, m_size.height()/2 };
+ int offs[3] = { 0, m_size.width()*m_size.height(), m_size.width()*m_size.height()*5/4 };
+
+ for (int i = 0; i < 3; ++i) {
+ glBindTexture(GL_TEXTURE_2D, m_texture[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w[i], h[i], 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, data + offs[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_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+ } else { //m_inputPin->connectedType().subtype == MEDIASUBTYPE_YUY2
+ //we upload 1 texture
+ glBindTexture(GL_TEXTURE_2D, m_texture[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.width() / 2, m_size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ }
+ m_sampleBuffer = ComPointer<IMediaSample>();
+ m_textureUploaded = true;
+ }
+#endif
+
+ void VideoRendererSoftFilter::repaintCurrentFrame(QPainter &painter, const QRect &r)
+ {
+ QMutexLocker locker(&m_mutex);
+
+#ifdef FPS_COUNTER
+ nbFramesDisplayed++;
+#endif
+
+
+#ifndef QT_NO_OPENGL
+ if (painter.paintEngine() &&
+ (painter.paintEngine()->type() == QPaintEngine::OpenGL || painter.paintEngine()->type() == QPaintEngine::OpenGL2)
+ && checkGLPrograms()) {
+
+ //for now we only support YUV (both YV12 and YUY2)
+ updateTexture();
+
+ if (!m_textureUploaded) {
+ //we simply fill the whole video with content
+ //the callee has already set the brush
+ painter.drawRect(r);
+ return;
+ }
+
+ //let's draw the texture
+ painter.beginNativePainting();
+
+ //Let's pass the other arguments
+ const Program prog = (m_inputPin->connectedType().subtype == MEDIASUBTYPE_YV12) ? YV12toRGB : YUY2toRGB;
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_program[prog]);
+ //loading the parameters
+ glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, m_brightness / 256., m_contrast, qCos(m_hue), qSin(m_hue));
+ glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, m_saturation, painter.opacity() /*alpha */, 0. /*dummy*/, 0. /*dummy*/);
+
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+
+ const float v_array[] = { r.left(), r.top(), r.right()+1, r.top(), r.right()+1, r.bottom()+1, r.left(), r.bottom()+1 };
+
+ float tx_array[12] = {0., 0., 0., 1.,
+ 0., 0., 1., 1.,
+ 0., 0., 1., 0.};
+
+ if (prog == YUY2toRGB) {
+ const float w = m_size.width() / 2,
+ iw = 1. / w;
+
+ tx_array[3] = w;
+ tx_array[6] = w;
+
+ for (int i = 0; i < 4; ++i) {
+ tx_array[3*i + 2] = iw;
+ }
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_texture[0]);
+
+ if (prog == YV12toRGB) {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, m_texture[2]);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, m_texture[1]);
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+
+ glVertexPointer(2, GL_FLOAT, 0, v_array);
+ glTexCoordPointer(3, GL_FLOAT, 0, tx_array);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDrawArrays(GL_QUADS, 0, 4);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ glDisable(GL_FRAGMENT_PROGRAM_ARB);
+ painter.endNativePainting();
+ return;
+ } else
+#endif
+ if (m_sampleBuffer) {
+ //we need to get the sample data
+ uchar *data = 0;
+ m_sampleBuffer->GetPointer(&data);
+
+
+ //let's update the current image
+ if (m_inputPin->connectedType().subtype == MEDIASUBTYPE_YV12) {
+ convertYV12toRGB(data, m_size, m_currentImage,
+ m_brightness, m_contrast, m_hue, m_saturation);
+ } else if (m_inputPin->connectedType().subtype == MEDIASUBTYPE_YUY2) {
+ convertYUY2toRGB(data, m_size, m_currentImage,
+ m_brightness, m_contrast, m_hue, m_saturation);
+ } else if (m_inputPin->connectedType().subtype == MEDIASUBTYPE_RGB32) {
+ normalizeRGB(data, m_size, m_currentImage);
+ }
+ m_sampleBuffer = ComPointer<IMediaSample>();
+ }
+
+ if (m_currentImage.isNull()) {
+ //we simply fill the whole video with content
+ //the callee has alrtead set the brush
+ painter.drawRect(r);
+ } else {
+ painter.drawImage(0, 0, m_currentImage);
+ }
+ }
+
+
+ void VideoRendererSoftFilter::normalizeRGB(const uchar *data, const QSize &s, QImage &destImage)
+ {
+ const int w = s.width(),
+ h = s.height();
+ if (destImage.size() != s) {
+ destImage = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ }
+ if (destImage.isNull()) {
+ return; //the system can't allocate the memory for the image drawing
+ }
+
+ const QRgb *rgb = reinterpret_cast<const QRgb*>(data);
+
+ //this sets the alpha channel to 0xff and flip the image vertically
+ for (int y = h - 1; y >= 0; --y) {
+ QRgb *dest = reinterpret_cast<QRgb*>(destImage.scanLine(y));
+ for(int i = w; i > 0; --i, ++rgb, ++dest) {
+ *dest = *rgb | (0xff << 24); //we force the alpha channel to 0xff
+ }
+ }
+ }
+
+
+ //we render data interpreted as YV12 into m_renderbuffer
+ void VideoRendererSoftFilter::convertYV12toRGB(const uchar *data, const QSize &s, QImage &destImage,
+ qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ const int w = s.width(),
+ h = s.height();
+
+ //let's cache some computation
+ const int cosHx256 = qRound(qCos(hue) * contrast * saturation * 256),
+ sinHx256 = qRound(qSin(hue) * contrast * saturation * 256);
+
+ int Yvalue[256];
+ for(int i = 0;i<256;++i) {
+ Yvalue[i] = qRound(((i - 16) * contrast + brightness) * 298 + 128);
+ }
+
+
+ if (destImage.size() != s) {
+ destImage = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ }
+
+ if (destImage.isNull()) {
+ return; //the system can't allocate the memory for the image drawing
+ }
+
+ QRgb *dest = reinterpret_cast<QRgb*>(destImage.bits());
+ const uchar *dataY = data,
+ *dataV = data + (w*h),
+ *dataU = dataV + (w*h)/4;
+
+ uint *line1 = dest,
+ *line2 = dest + w;
+
+ for(int l = (h >> 1); l > 0; --l) {
+ //we treat 2 lines by 2 lines
+
+ for(int x = (w >> 1); x > 0; --x) {
+
+ const int u = *dataU++ - 128,
+ v = *dataV++ - 128;
+ const int d = (u * cosHx256 + v * sinHx256) >> 8,
+ e = (v * cosHx256 + u * sinHx256) >> 8;
+
+ const int compRed = 409 * e,
+ compGreen = -100 * d - 208 * e,
+ compBlue = 516 * d;
+
+ const int y21 = Yvalue[ dataY[w] ],
+ y11 = Yvalue[ *dataY++ ],
+ y22 = Yvalue[ dataY[w] ],
+ y12 = Yvalue[ *dataY++ ];
+
+ //1st line 1st pixel
+ *line1++ = CLIPPED_PIXEL(y11, compRed, compGreen, compBlue);
+
+ //1st line, 2nd pixel
+ *line1++ = CLIPPED_PIXEL(y12, compRed, compGreen, compBlue);
+
+ //2nd line 1st pixel
+ *line2++ = CLIPPED_PIXEL(y21, compRed, compGreen, compBlue);
+
+ //2nd line 2nd pixel
+ *line2++ = CLIPPED_PIXEL(y22, compRed, compGreen, compBlue);
+
+ } //for
+
+ //end of the line
+ dataY += w;
+ line1 = line2;
+ line2 += w;
+
+ } //for
+
+ }
+
+ //we render data interpreted as YUY2 into m_renderbuffer
+ void VideoRendererSoftFilter::convertYUY2toRGB(const uchar *data, const QSize &s, QImage &destImage,
+ qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ const int w = s.width(),
+ h = s.height();
+
+ //let's cache some computation
+ int Yvalue[256];
+ for(int i = 0;i<256;++i) {
+ Yvalue[i] = qRound(((i - 16) * contrast + brightness) * 298 + 128);
+ }
+
+ const int cosHx256 = qRound(qCos(hue) * contrast * saturation * 256),
+ sinHx256 = qRound(qSin(hue) * contrast * saturation * 256);
+
+ if (destImage.size() != s) {
+ //this will only allocate memory when needed
+ destImage = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
+ }
+ if (destImage.isNull()) {
+ return; //the system can't allocate the memory for the image drawing
+ }
+
+ QRgb *dest = reinterpret_cast<QRgb*>(destImage.bits());
+
+ //the number of iterations is width * height / 2 because we treat 2 pixels at each iterations
+ for (int c = w * h / 2; c > 0 ; --c) {
+
+ //the idea of that algorithm comes from
+ //http://msdn2.microsoft.com/en-us/library/ms867704.aspx#yuvformats_identifying_yuv_formats_in_directshow
+
+ //we treat 2 pixels by 2 pixels (we start reading 2 pixels info ie. "YUYV"
+ const int y1 = Yvalue[*data++],
+ u = *data++ - 128,
+ y2 = Yvalue[*data++],
+ v = *data++ - 128;
+
+ const int d = (u * cosHx256 + v * sinHx256) >> 8,
+ e = (v * cosHx256 + u * sinHx256) >> 8;
+
+ const int compRed = 409 * e,
+ compGreen = -100 * d - 208 * e,
+ compBlue = 516 * d;
+
+ //first pixel
+ *dest++ = CLIPPED_PIXEL(y1, compRed, compGreen, compBlue);
+
+ //second pixel
+ *dest++ = CLIPPED_PIXEL(y2, compRed, compGreen, compBlue);
+ }
+ }
+
+
+ VideoRendererSoft::VideoRendererSoft(QWidget *target) :
+ m_renderer(new VideoRendererSoftFilter(this)), m_target(target)
+ {
+ m_filter = Filter(m_renderer);
+ }
+
+ VideoRendererSoft::~VideoRendererSoft()
+ {
+ }
+
+
+ bool VideoRendererSoft::isNative() const
+ {
+ return false;
+ }
+
+
+ void VideoRendererSoft::repaintCurrentFrame(QWidget *target, const QRect &rect)
+ {
+ QPainter painter(target);
+
+ QColor backColor = target->palette().color(target->backgroundRole());
+ painter.setBrush(backColor);
+ painter.setPen(Qt::NoPen);
+ if (!m_videoRect.contains(rect)) {
+ //we repaint the borders only when needed
+ const QVector<QRect> reg = (QRegion(rect) - m_videoRect).rects();
+ for (int i = 0; i < reg.count(); ++i) {
+ painter.drawRect(reg.at(i));
+ }
+ }
+
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+ painter.setTransform(m_transform, true);
+ QSize vsize = videoSize();
+ m_renderer->repaintCurrentFrame(painter, QRect(0,0, vsize.width(), vsize.height()));
+ }
+
+ void VideoRendererSoft::notifyResize(const QSize &size,
+ Phonon::VideoWidget::AspectRatio aspectRatio, Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ const QSize vsize = videoSize();
+ internalNotifyResize(size, vsize, aspectRatio, scaleMode);
+
+ m_transform.reset();
+
+ if (vsize.isValid() && size.isValid()) {
+ m_transform.translate(m_dstX, m_dstY);
+ const qreal sx = qreal(m_dstWidth) / qreal(vsize.width()),
+ sy = qreal(m_dstHeight) / qreal(vsize.height());
+ m_transform.scale(sx, sy);
+ m_videoRect = m_transform.mapRect( QRect(0,0, vsize.width(), vsize.height()));
+ }
+ }
+
+ QSize VideoRendererSoft::videoSize() const
+ {
+ if (m_renderer->pins().first()->connected()) {
+ return m_renderer->videoSize();
+ } else {
+ return m_renderer->currentImage().size();
+ }
+ }
+
+ void VideoRendererSoft::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ m_renderer->applyMixerSettings(brightness, contrast, hue, saturation);
+ }
+
+ QImage VideoRendererSoft::snapshot() const
+ {
+ return m_renderer->currentImage(); //not accurate (especially when using opengl...)
+ }
+
+ void VideoRendererSoft::setSnapshot(const QImage &image)
+ {
+ m_renderer->setCurrentImage(image);
+ }
+
+ bool VideoRendererSoft::event(QEvent *e)
+ {
+ if (e->type() == QEvent::UpdateRequest) {
+ m_target->update(m_videoRect);
+ return true;
+ }
+ return QObject::event(e);
+ }
+
+
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/ds9/videorenderer_soft.h b/src/3rdparty/phonon/ds9/videorenderer_soft.h
new file mode 100644
index 0000000..e47bca6
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_soft.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef PHONON_VIDEORENDERER_SOFT_H
+#define PHONON_VIDEORENDERER_SOFT_H
+
+#include "abstractvideorenderer.h"
+
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class VideoRendererSoftFilter;
+ //this class is used to render evrything in software (like in the Graphics View)
+ class VideoRendererSoft : public AbstractVideoRenderer,
+ public QObject //this is used to receive events
+ {
+ public:
+ VideoRendererSoft(QWidget *);
+ ~VideoRendererSoft();
+
+ //Implementation from AbstractVideoRenderer
+ void repaintCurrentFrame(QWidget *target, const QRect &rect);
+ void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode);
+ QSize videoSize() const;
+ void applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation);
+ bool isNative() const;
+
+ QImage snapshot() const;
+ void setSnapshot(const QImage &);
+
+ protected:
+ bool event(QEvent *);
+
+ private:
+ VideoRendererSoftFilter *m_renderer;
+ QTransform m_transform;
+ QRect m_videoRect; //rectangle where the video is displayed
+ QWidget *m_target;
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+
+#endif
+
+
diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp
new file mode 100644
index 0000000..545b31e
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp
@@ -0,0 +1,222 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include "videorenderer_vmr9.h"
+
+#ifndef QT_NO_PHONON_VIDEO
+
+#include <QtGui/QWidget>
+#include <QtGui/QPainter>
+
+#include <d3d9.h>
+#include <vmr9.h>
+
+QT_BEGIN_NAMESPACE
+
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ VideoRendererVMR9::~VideoRendererVMR9()
+ {
+ }
+
+ bool VideoRendererVMR9::isNative() const
+ {
+ return true;
+ }
+
+
+ VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target)
+ {
+ m_filter = Filter(CLSID_VideoMixingRenderer9, IID_IBaseFilter);
+ if (!m_filter) {
+ return;
+ }
+
+ ComPointer<IVMRFilterConfig9> config(m_filter, IID_IVMRFilterConfig9);
+ Q_ASSERT(config);
+ HRESULT hr = config->SetRenderingMode(VMR9Mode_Windowless);
+ Q_ASSERT(SUCCEEDED(hr));
+ hr = config->SetNumberOfStreams(1); //for now we limit it to 1 input stream
+ Q_ASSERT(SUCCEEDED(hr));
+ ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ windowlessControl->SetVideoClippingWindow(reinterpret_cast<HWND>(target->winId()));
+ windowlessControl->SetAspectRatioMode(VMR9ARMode_None); //we're in control of the size
+ }
+
+ QImage VideoRendererVMR9::snapshot() const
+ {
+ ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ if (windowlessControl) {
+ BYTE *buffer = 0;
+ HRESULT hr = windowlessControl->GetCurrentImage(&buffer);
+ if (SUCCEEDED(hr)) {
+
+ const BITMAPINFOHEADER *bmi = reinterpret_cast<BITMAPINFOHEADER*>(buffer);
+ const int w = qAbs(bmi->biWidth),
+ h = qAbs(bmi->biHeight);
+
+ // Create image and copy data into image.
+ QImage ret(w, h, QImage::Format_RGB32);
+
+ if (!ret.isNull()) {
+ uchar *data = buffer + bmi->biSize;
+ const int bytes_per_line = w * sizeof(QRgb);
+ for (int y = h - 1; y >= 0; --y) {
+ qMemCopy(ret.scanLine(y), //destination
+ data, //source
+ bytes_per_line);
+ data += bytes_per_line;
+ }
+ }
+ ::CoTaskMemFree(buffer);
+ return ret;
+ }
+ }
+ return QImage();
+ }
+
+ QSize VideoRendererVMR9::videoSize() const
+ {
+ LONG w = 0,
+ h = 0;
+ ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ if (windowlessControl) {
+ windowlessControl->GetNativeVideoSize( &w, &h, 0, 0);
+ }
+ return QSize(w, h);
+ }
+
+ void VideoRendererVMR9::repaintCurrentFrame(QWidget *target, const QRect &rect)
+ {
+ HDC hDC = target->getDC();
+ // repaint the video
+ ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+
+ HRESULT hr = windowlessControl ? windowlessControl->RepaintVideo(target->winId(), hDC) : E_POINTER;
+ if (FAILED(hr) || m_dstY > 0 || m_dstX > 0) {
+ const QColor c = target->palette().color(target->backgroundRole());
+ COLORREF color = RGB(c.red(), c.green(), c.blue());
+ HPEN hPen = ::CreatePen(PS_SOLID, 1, color);
+ HBRUSH hBrush = ::CreateSolidBrush(color);
+ ::SelectObject(hDC, hPen);
+ ::SelectObject(hDC, hBrush);
+ // repaint the video
+ if (FAILED(hr)) {
+ //black background : we use the Win32 API to avoid the ghost effect of the backing store
+ ::Rectangle(hDC, 0, 0, target->width(), target->height());
+ } else {
+ if (m_dstY > 0) {
+ ::Rectangle(hDC, 0, 0, target->width(), m_dstY); //top
+ ::Rectangle(hDC, 0, target->height() - m_dstY, target->width(), target->height()); //bottom
+ }
+ if (m_dstX > 0) {
+ ::Rectangle(hDC, 0, m_dstY, m_dstX, m_dstHeight + m_dstY); //left
+ ::Rectangle(hDC, m_dstWidth + m_dstX, m_dstY, target->width(), m_dstHeight + m_dstY); //right
+ }
+ }
+ ::DeleteObject(hPen);
+ ::DeleteObject(hBrush);
+ }
+ target->releaseDC(hDC);
+
+ }
+
+ void VideoRendererVMR9::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
+ Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ if (!isActive()) {
+ RECT dummyRect = { 0, 0, 0, 0};
+ ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ windowlessControl->SetVideoPosition(&dummyRect, &dummyRect);
+ return;
+ }
+
+
+ const QSize vsize = videoSize();
+ internalNotifyResize(size, vsize, aspectRatio, scaleMode);
+
+ RECT dstRectWin = { m_dstX, m_dstY, m_dstWidth + m_dstX, m_dstHeight + m_dstY};
+ RECT srcRectWin = { 0, 0, vsize.width(), vsize.height()};
+
+ ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ if (windowlessControl) {
+ windowlessControl->SetVideoPosition(&srcRectWin, &dstRectWin);
+ }
+ }
+
+ void VideoRendererVMR9::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first();
+ OutputPin source;
+ if (FAILED(sink->ConnectedTo(source.pparam()))) {
+ return; //it must be connected to work
+ }
+
+ //get the mixer (used for brightness/contrast/saturation/hue)
+ ComPointer<IVMRMixerControl9> mixer(m_filter, IID_IVMRMixerControl9);
+ Q_ASSERT(mixer);
+
+ VMR9ProcAmpControl ctrl;
+ ctrl.dwSize = sizeof(ctrl);
+ ctrl.dwFlags = ProcAmpControl9_Contrast | ProcAmpControl9_Brightness | ProcAmpControl9_Saturation | ProcAmpControl9_Hue;
+ VMR9ProcAmpControlRange range;
+ range.dwSize = sizeof(range);
+
+ range.dwProperty = ProcAmpControl9_Contrast;
+ HRESULT hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Contrast = ((contrast < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(contrast) + range.DefaultValue;
+
+ //brightness
+ range.dwProperty = ProcAmpControl9_Brightness;
+ hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Brightness = ((brightness < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(brightness) + range.DefaultValue;
+
+ //saturation
+ range.dwProperty = ProcAmpControl9_Saturation;
+ hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Saturation = ((saturation < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(saturation) + range.DefaultValue;
+
+ //hue
+ range.dwProperty = ProcAmpControl9_Hue;
+ hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Hue = ((hue < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(hue) + range.DefaultValue;
+
+ //finally set the settings
+ mixer->SetProcAmpControl(0, &ctrl);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.h b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h
new file mode 100644
index 0000000..516d79d
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h
@@ -0,0 +1,55 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_VIDEORENDERER_VMR9_H
+#define PHONON_VIDEORENDERER_VMR9_H
+
+#include "abstractvideorenderer.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class VideoRendererVMR9 : public AbstractVideoRenderer
+ {
+ public:
+ VideoRendererVMR9(QWidget *target);
+ ~VideoRendererVMR9();
+
+ //Implementation from AbstractVideoRenderer
+ void repaintCurrentFrame(QWidget *target, const QRect &rect);
+ void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode);
+ QSize videoSize() const;
+ QImage snapshot() const;
+ void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation);
+ bool isNative() const;
+ private:
+ QWidget *m_target;
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp
new file mode 100644
index 0000000..09d42a4
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videowidget.cpp
@@ -0,0 +1,437 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "videowidget.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QPaintEvent>
+#include <QtCore/QTimer>
+#include <QtCore/QSettings>
+
+#include "mediaobject.h"
+
+#ifndef Q_OS_WINCE
+#include "videorenderer_evr.h"
+#include "videorenderer_vmr9.h"
+#else
+#include "videorenderer_default.h"
+#endif
+#include "videorenderer_soft.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ //class used internally to return the widget where the video is shown on
+ class VideoWindow : public QWidget
+ {
+ public:
+ explicit VideoWindow(QWidget *parent, VideoWidget *vw)
+ : QWidget(parent), m_node(vw), m_currentRenderer(0)
+ {
+ //default background color
+ setPalette(QPalette(Qt::black));
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ setAttribute(Qt::WA_PaintOnScreen, true);
+ setAutoFillBackground(false);
+ }
+
+ QPaintEngine* paintEngine() const
+ {
+ return 0;
+ }
+
+ bool isEmbedded() const
+ {
+#if QT_VERSION >= 0x040400
+ return window()->testAttribute(Qt::WA_DontShowOnScreen);
+#else
+ return false;
+#endif
+ }
+
+ bool needsSoftRendering() const
+ {
+ QPaintDevice *dev = QPainter::redirected(this, 0);
+ return (dev && dev != this);
+ }
+
+ void resizeEvent(QResizeEvent *e)
+ {
+ m_node->updateVideoSize();
+ QWidget::resizeEvent(e);
+ }
+
+ AbstractVideoRenderer *currentRenderer() const
+ {
+ return m_currentRenderer;
+ }
+
+ void setCurrentRenderer(AbstractVideoRenderer *renderer)
+ {
+ m_currentRenderer = renderer;
+ //we disallow repaint on that widget for just a fraction of second
+ //this allows better transition between videos
+ setUpdatesEnabled(false);
+ m_flickerFreeTimer.start(20, this);
+ }
+
+ void timerEvent(QTimerEvent *e)
+ {
+ if (e->timerId() == m_flickerFreeTimer.timerId()) {
+ m_flickerFreeTimer.stop();
+ setUpdatesEnabled(true);
+ }
+ QWidget::timerEvent(e);
+ }
+
+ QSize sizeHint() const
+ {
+ return m_currentRenderer->sizeHint().expandedTo(QWidget::sizeHint());
+ }
+
+ void changeEvent(QEvent *e)
+ {
+ checkCurrentRenderingMode();
+ QWidget::changeEvent(e);
+ }
+
+ void setVisible(bool visible)
+ {
+ checkCurrentRenderingMode();
+ QWidget::setVisible(visible);
+ }
+
+ void paintEvent(QPaintEvent *e)
+ {
+ if (!updatesEnabled())
+ return; //this avoids repaint from native events
+ checkCurrentRenderingMode();
+ m_currentRenderer->repaintCurrentFrame(this, e->rect());
+ }
+
+ //this code manages the activation/deactivation of the screensaver
+ /*bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::Resize) {
+ //we disable the screensaver if the video is in fullscreen mode
+ disableScreenSaver(window()->windowState() & Qt::WindowFullScreen);
+ }
+ return QWidget::event(e);
+ }*/
+
+ private:
+ //for fullscreen mode
+ void disableScreenSaver(bool b)
+ {
+ const QLatin1String screenSaverActive("ScreenSaveActive");
+ QSettings settings( QLatin1String("HKEY_CURRENT_USER\\Control Panel\\Desktop"), QSettings::NativeFormat);
+ if (b) {
+ if (m_restoreScreenSaverActive.isNull()) {
+ //we store the value to be able to restore it later
+ m_restoreScreenSaverActive = settings.value(screenSaverActive);
+ settings.setValue(screenSaverActive, QString::number(!b));
+ }
+ } else if (!m_restoreScreenSaverActive.isNull()) {
+ //we restore the previous value
+ settings.setValue(screenSaverActive, m_restoreScreenSaverActive);
+ }
+ }
+
+ void checkCurrentRenderingMode()
+ {
+ if (!m_currentRenderer)
+ return;
+
+ if (m_currentRenderer->isNative()) {
+ if (isEmbedded()) {
+ //we need to switch to software renderer
+ m_currentRenderer = m_node->switchRendering(m_currentRenderer);
+ setAttribute(Qt::WA_PaintOnScreen, false);
+ } else if (needsSoftRendering()) {
+ m_node->performSoftRendering(m_currentRenderer->snapshot());
+ }
+ } else if (!isEmbedded()) {
+ m_currentRenderer = m_node->switchRendering(m_currentRenderer);
+ setAttribute(Qt::WA_PaintOnScreen, false);
+ }
+ }
+
+ VideoWidget *m_node;
+ AbstractVideoRenderer *m_currentRenderer;
+ QVariant m_restoreScreenSaverActive;
+ QBasicTimer m_flickerFreeTimer;
+ };
+
+ VideoWidget::VideoWidget(QWidget *parent)
+ : BackendNode(parent), m_aspectRatio(Phonon::VideoWidget::AspectRatioAuto),
+ m_scaleMode(Phonon::VideoWidget::FitInView),
+ m_brightness(0.), m_contrast(0.), m_hue(0.), m_saturation(0.), m_noNativeRendererSupported(false)
+
+ {
+ //initialisation of the widget
+ m_widget = new VideoWindow(parent, this);
+
+ //initialization of the renderers
+ qMemSet(m_renderers, 0, sizeof(m_renderers));
+
+ for(int i = 0; i< FILTER_COUNT ;++i) {
+ //This might return a non native (ie Qt) renderer in case native is not supported
+ AbstractVideoRenderer *renderer = getRenderer(i, Native, true);
+ m_filters[i] = renderer->getFilter();
+ }
+
+ //by default, we take the first VideoWindow object
+ setCurrentGraph(0);
+ }
+
+ VideoWidget::~VideoWidget()
+ {
+ for (int i = 0; i < 4; ++i) {
+ delete m_renderers[i];
+ }
+ }
+
+ void VideoWidget::notifyVideoLoaded()
+ {
+ updateVideoSize();
+ m_widget->updateGeometry();
+ }
+
+ AbstractVideoRenderer *VideoWidget::switchRendering(AbstractVideoRenderer *current)
+ {
+ const bool toNative = !current->isNative();
+ if (toNative && m_noNativeRendererSupported)
+ return current; //no switch here
+
+ if (!mediaObject())
+ return current;
+
+ //firt we delete the renderer
+ //initialization of the widgets
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ Filter oldFilter = m_filters[i];
+
+ //Let's create a software renderer
+ AbstractVideoRenderer *renderer = getRenderer(i, toNative ? Native : NonNative, true);
+
+ if (m_mediaObject) {
+ m_mediaObject->switchFilters(i, oldFilter, renderer->getFilter());
+ }
+
+ m_filters[i] = renderer->getFilter();
+ }
+
+ return getRenderer(mediaObject()->currentGraph()->index(), toNative ? Native: NonNative);
+ }
+
+ void VideoWidget::performSoftRendering(const QImage &currentImage)
+ {
+ const int graphIndex = mediaObject()->currentGraph()->index();
+ VideoRendererSoft *r = static_cast<VideoRendererSoft*>(getRenderer(graphIndex, NonNative, true /*autocreation*/));
+ r->setSnapshot(currentImage);
+ r->notifyResize(m_widget->size(), m_aspectRatio, m_scaleMode);
+ r->repaintCurrentFrame(m_widget, m_widget->rect());
+
+ }
+
+ void VideoWidget::setCurrentGraph(int index)
+ {
+ for(int i = 0; i < 2; ++i) {
+ if (AbstractVideoRenderer *renderer = getRenderer(i, Native))
+ renderer->setActive(index == i);
+ }
+
+ //be sure to update all the things that needs an update
+ applyMixerSettings();
+ updateVideoSize();
+
+ AbstractVideoRenderer *r = m_widget->currentRenderer();
+
+ //we determine dynamically if it is native or non native
+ r = getRenderer(index, !r || r->isNative() ? Native : NonNative);
+ if (!r)
+ r = getRenderer(index, NonNative);
+ m_widget->setCurrentRenderer(r);
+ }
+
+
+ Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
+ {
+ return m_aspectRatio;
+ }
+
+ void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio)
+ {
+ m_aspectRatio = aspectRatio;
+ updateVideoSize();
+ m_widget->update();
+ }
+
+ Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
+ {
+ return m_scaleMode;
+ }
+
+
+ QWidget *VideoWidget::widget()
+ {
+ return m_widget;
+ }
+
+
+ void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ m_scaleMode = scaleMode;
+ updateVideoSize();
+ m_widget->update();
+ }
+
+ void VideoWidget::setBrightness(qreal b)
+ {
+ m_brightness = b;
+ applyMixerSettings();
+ }
+
+ void VideoWidget::setContrast(qreal c)
+ {
+ m_contrast = c;
+ applyMixerSettings();
+ }
+
+ void VideoWidget::setHue(qreal h)
+ {
+ m_hue = h;
+ applyMixerSettings();
+ }
+
+ void VideoWidget::setSaturation(qreal s)
+ {
+ m_saturation = s;
+ applyMixerSettings();
+ }
+
+ qreal VideoWidget::brightness() const
+ {
+ return m_brightness;
+ }
+
+
+ qreal VideoWidget::contrast() const
+ {
+ return m_contrast;
+ }
+
+ qreal VideoWidget::hue() const
+ {
+ return m_hue;
+ }
+
+ qreal VideoWidget::saturation() const
+ {
+ return m_saturation;
+ }
+
+
+ AbstractVideoRenderer *VideoWidget::getRenderer(int graphIndex, RendererType type, bool autoCreate)
+ {
+ int index = graphIndex * 2 + type;
+ if (m_renderers[index] == 0 && autoCreate) {
+ AbstractVideoRenderer *renderer = 0;
+ if (type == Native) {
+#ifndef Q_OS_WINCE
+ renderer = new VideoRendererEVR(m_widget);
+ if (renderer->getFilter() == 0) {
+ delete renderer;
+ //EVR not present, let's try VMR
+ renderer = new VideoRendererVMR9(m_widget);
+ if (renderer->getFilter() == 0) {
+ //instanciating the renderer might fail
+ m_noNativeRendererSupported = true;
+ delete renderer;
+ renderer = 0;
+ }
+ }
+#else
+ renderer = new VideoRendererDefault(m_widget);
+ if (renderer->getFilter() == 0) {
+ //instanciating the renderer might fail
+ m_noNativeRendererSupported = true;
+ delete renderer;
+ renderer = 0;
+ }
+#endif
+ }
+
+ if (renderer == 0) {
+ type = NonNative;
+ index = graphIndex * 2 + type;
+ if (m_renderers[index] == 0)
+ renderer = new VideoRendererSoft(m_widget); //this always succeeds
+ else
+ renderer = m_renderers[index];
+ }
+
+ m_renderers[index] = renderer;
+
+ //be sure to update all the things that needs an update
+ applyMixerSettings();
+ updateVideoSize();
+
+ }
+ return m_renderers[index];
+ }
+
+ //this must be called whe nthe node is actually connected
+ void VideoWidget::applyMixerSettings() const
+ {
+ for (int i = 0; i < 4; ++i) {
+ if (AbstractVideoRenderer *renderer = m_renderers[i])
+ renderer->applyMixerSettings(m_brightness, m_contrast, m_hue, m_saturation);
+ }
+ }
+
+ void VideoWidget::connected(BackendNode *, const InputPin&)
+ {
+ //in case of a connection, we simply reapply the mixer settings
+ applyMixerSettings();
+ updateVideoSize();
+ }
+
+ void VideoWidget::updateVideoSize() const
+ {
+ for (int i = 0; i < 4; ++i) {
+ if (AbstractVideoRenderer *renderer = m_renderers[i])
+ renderer->notifyResize(m_widget->size(), m_aspectRatio, m_scaleMode);
+ }
+ }
+
+
+
+ }
+}
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+
+#include "moc_videowidget.cpp"
diff --git a/src/3rdparty/phonon/ds9/videowidget.h b/src/3rdparty/phonon/ds9/videowidget.h
new file mode 100644
index 0000000..fc8a6e3
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/videowidget.h
@@ -0,0 +1,96 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_VIDEOWIDGET_H
+#define PHONON_VIDEOWIDGET_H
+
+#include <QtGui/QWidget>
+#include <phonon/videowidgetinterface.h>
+#include "backendnode.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class VideoWindow;
+ class AbstractVideoRenderer;
+
+ class VideoWidget : public BackendNode, public Phonon::VideoWidgetInterface
+ {
+ enum RendererType
+ {
+ Native = 0,
+ NonNative = 1
+ };
+
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VideoWidgetInterface)
+ public:
+ VideoWidget(QWidget *parent = 0);
+ ~VideoWidget();
+
+ Phonon::VideoWidget::AspectRatio aspectRatio() const;
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio);
+ Phonon::VideoWidget::ScaleMode scaleMode() const;
+ void setScaleMode(Phonon::VideoWidget::ScaleMode);
+ qreal brightness() const;
+ void setBrightness(qreal);
+ qreal contrast() const;
+ void setContrast(qreal);
+ qreal hue() const;
+ void setHue(qreal);
+ qreal saturation() const;
+ void setSaturation(qreal);
+
+ void setCurrentGraph(int index);
+
+ QWidget *widget();
+
+ void notifyVideoLoaded();
+ AbstractVideoRenderer *switchRendering(AbstractVideoRenderer *current);
+ void performSoftRendering(const QImage &currentImage);
+
+ //apply contrast/brightness/hue/saturation
+ void applyMixerSettings() const;
+ void updateVideoSize() const;
+
+ protected:
+ virtual void connected(BackendNode *, const InputPin& inpin);
+
+ private:
+ AbstractVideoRenderer *getRenderer(int graphIndex, RendererType type, bool autoCreate = false);
+
+ Phonon::VideoWidget::AspectRatio m_aspectRatio;
+ Phonon::VideoWidget::ScaleMode m_scaleMode;
+
+ VideoWindow *m_widget;
+ qreal m_brightness, m_contrast, m_hue, m_saturation;
+ AbstractVideoRenderer* m_renderers[4];
+ mutable bool m_noNativeRendererSupported;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_VIDEOWIDGET_H
+
+#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/ds9/volumeeffect.cpp b/src/3rdparty/phonon/ds9/volumeeffect.cpp
new file mode 100644
index 0000000..a93b074
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/volumeeffect.cpp
@@ -0,0 +1,285 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "volumeeffect.h"
+#include "qbasefilter.h"
+#include "qmeminputpin.h"
+
+#include <QtCore/qmath.h> //for sqrt
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ /**************************************************************************
+ * curve functions
+ *************************************************************************/
+
+ static qreal curveValueFadeIn3dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
+ {
+ return (fadeStart + fadeDiff * sqrt(completed));
+ }
+ static qreal curveValueFadeOut3dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
+ {
+ return (fadeStart + fadeDiff * (1.0 - sqrt(1.0 - completed)));
+ }
+ // in == out for a linear fade
+ static qreal curveValueFade6dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
+ {
+ return (fadeStart + fadeDiff * completed);
+ }
+ static qreal curveValueFadeIn9dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
+ {
+ return (fadeStart + fadeDiff * pow(completed, 1.5));
+ }
+ static qreal curveValueFadeOut9dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
+ {
+ return (fadeStart + fadeDiff * (1.0 - pow(1.0 - completed, 1.5)));
+ }
+ static qreal curveValueFadeIn12dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
+ {
+ return (fadeStart + fadeDiff * completed * completed);
+ }
+ static qreal curveValueFadeOut12dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
+ {
+ const qreal x = 1.0 - completed;
+ return (fadeStart + fadeDiff * (1.0 - x * x));
+ }
+
+ static const QVector<AM_MEDIA_TYPE> audioMediaType()
+ {
+ QVector<AM_MEDIA_TYPE> ret;
+ AM_MEDIA_TYPE mt = { MEDIATYPE_Audio, MEDIASUBTYPE_PCM, 1, 0, 1, GUID_NULL, 0, 0, 0};
+ ret << mt;
+ return ret;
+ }
+
+ class VolumeMemInputPin : public QMemInputPin
+ {
+ public:
+ VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, QPin *output) : QMemInputPin(parent, mt, true /*transform*/, output)
+ {
+ }
+
+ ~VolumeMemInputPin()
+ {
+ }
+
+ STDMETHODIMP NotifyAllocator(IMemAllocator *alloc, BOOL b)
+ {
+ ALLOCATOR_PROPERTIES prop;
+ HRESULT hr = alloc->GetProperties(&prop);
+ if (SUCCEEDED(hr) && prop.cBuffers > 1) {
+ //this allows to reduce the latency for sound
+ //the problem is that too low numbers makes the whole thing fail...
+ ALLOCATOR_PROPERTIES actual;
+ prop.cBuffers = 1;
+ alloc->SetProperties(&prop, &actual);
+ }
+ return QMemInputPin::NotifyAllocator(alloc, b);
+ }
+
+ };
+
+ class VolumeMemOutputPin : public QPin
+ {
+ public:
+ VolumeMemOutputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt) : QPin(parent, PINDIR_OUTPUT, mt)
+ {
+ }
+
+ ~VolumeMemOutputPin()
+ {
+ }
+
+ };
+
+ class VolumeEffectFilter : public QBaseFilter
+ {
+ public:
+ VolumeEffectFilter(VolumeEffect *);
+
+ //reimplementation
+ virtual HRESULT processSample(IMediaSample *);
+
+ private:
+ void treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency);
+
+ QMemInputPin *m_input;
+ QPin *m_output;
+ VolumeEffect *m_volumeEffect;
+ };
+
+ VolumeEffectFilter::VolumeEffectFilter(VolumeEffect *ve) : QBaseFilter(CLSID_NULL),
+ m_volumeEffect(ve)
+ {
+ QVector<AM_MEDIA_TYPE> mt;
+
+ //creating the output
+ m_output = new VolumeMemOutputPin(this, mt);
+
+ //then creating the input
+ mt << audioMediaType();
+ m_input = new VolumeMemInputPin(this, mt, m_output);
+ }
+
+ void VolumeEffectFilter::treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency)
+ {
+ float volume = m_volumeEffect->volume();
+ if (m_volumeEffect->m_fading) {
+ const qreal lastSample = m_volumeEffect->m_fadeDuration * frequency / 1000;
+ const qreal completed = qreal(m_volumeEffect->m_fadeSamplePosition++) / lastSample;
+
+ if (qFuzzyCompare(completed, qreal(1.))) {
+ m_volumeEffect->setVolume(m_volumeEffect->m_targetVolume);
+ m_volumeEffect->m_fading = false; //we end the fading effect
+ } else {
+ volume = m_volumeEffect->m_fadeCurveFn(m_volumeEffect->m_initialVolume,
+ m_volumeEffect->m_targetVolume - m_volumeEffect->m_initialVolume,
+ completed);
+ }
+ }
+
+ for(int c = 0; c < channelCount; ++c) {
+ switch (sampleSize)
+ {
+ case 2:
+ {
+ short *shortBuffer = reinterpret_cast<short*>(*buffer);
+ *shortBuffer *= qRound(volume);
+ }
+ break;
+ case 1:
+ **buffer *= qRound(volume);
+ break;
+ default:
+ break;
+ }
+
+ *buffer += sampleSize;
+ }
+ }
+
+ HRESULT VolumeEffectFilter::processSample(IMediaSample * ms)
+ {
+ BYTE *buffer = 0;
+ ms->GetPointer(&buffer);
+ if (buffer) {
+ const AM_MEDIA_TYPE &mt = m_output->connectedType();
+ if (mt.formattype != FORMAT_WaveFormatEx) {
+ return VFW_E_INVALIDMEDIATYPE;
+ }
+ WAVEFORMATEX *format = reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat);
+ const int channelCount = format->nChannels;
+ const int sampleSize = format->wBitsPerSample / 8; //...in bytes
+
+
+ const BYTE *end = buffer + ms->GetActualDataLength();
+ while (buffer < end) {
+ treatOneSamplePerChannel(&buffer, sampleSize, channelCount, format->nSamplesPerSec);
+ }
+ }
+
+ return S_OK;
+ }
+
+ VolumeEffect::VolumeEffect(QObject *parent) : Effect(parent),
+ m_volume(1), m_fadeCurve(Phonon::VolumeFaderEffect::Fade3Decibel),
+ m_fading(false), m_initialVolume(0), m_targetVolume(0), m_fadeDuration(0),
+ m_fadeSamplePosition(0)
+ {
+ //creation of the effects
+ for(int i = 0; i < FILTER_COUNT; ++i) {
+ VolumeEffectFilter *f = new VolumeEffectFilter(this);
+ m_filters[i] = Filter(f);
+ }
+ }
+
+ float VolumeEffect::volume() const
+ {
+ return m_volume;
+ }
+
+ void VolumeEffect::setVolume(float newVolume)
+ {
+ m_volume = newVolume;
+ }
+
+ Phonon::VolumeFaderEffect::FadeCurve VolumeEffect::fadeCurve() const
+ {
+ return m_fadeCurve;
+ }
+
+ void VolumeEffect::setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve curve)
+ {
+ m_fadeCurve = curve;
+ }
+
+
+ void VolumeEffect::fadeTo(float vol, int duration)
+ {
+ m_fading = true; //will be set back to false when fading is finished
+ m_targetVolume = vol;
+ m_fadeSamplePosition = 0;
+ m_initialVolume = m_volume;
+ m_fadeDuration = duration;
+
+ //in or out?
+ const bool in = vol > m_volume;
+
+ switch(m_fadeCurve)
+ {
+ case Phonon::VolumeFaderEffect::Fade6Decibel:
+ m_fadeCurveFn = curveValueFade6dB;
+ break;
+ case Phonon::VolumeFaderEffect::Fade9Decibel:
+ if (in) {
+ m_fadeCurveFn = curveValueFadeIn9dB;
+ } else {
+ m_fadeCurveFn = curveValueFadeOut9dB;
+ }
+ break;
+ case Phonon::VolumeFaderEffect::Fade12Decibel:
+ if (in) {
+ m_fadeCurveFn = curveValueFadeIn12dB;
+ } else {
+ m_fadeCurveFn = curveValueFadeOut12dB;
+ }
+ break;
+ case Phonon::VolumeFaderEffect::Fade3Decibel:
+ default:
+ if (in) {
+ m_fadeCurveFn = curveValueFadeIn3dB;
+ } else {
+ m_fadeCurveFn = curveValueFadeOut3dB;
+ }
+ break;
+ }
+ }
+ }
+}
+
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+
+QT_END_NAMESPACE
+
+#include "moc_volumeeffect.cpp"
diff --git a/src/3rdparty/phonon/ds9/volumeeffect.h b/src/3rdparty/phonon/ds9/volumeeffect.h
new file mode 100644
index 0000000..d1b0186
--- /dev/null
+++ b/src/3rdparty/phonon/ds9/volumeeffect.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_VOLUMEEFFECT_H
+#define PHONON_VOLUMEEFFECT_H
+
+#include "effect.h"
+#include <phonon/volumefaderinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ class VolumeEffectFilter;
+ class VolumeEffect : public Effect, public Phonon::VolumeFaderInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VolumeFaderInterface)
+ public:
+ VolumeEffect(QObject *parent);
+
+ //reimplementation
+ virtual float volume() const;
+ virtual void setVolume(float);
+ virtual Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const;
+ virtual void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve);
+ virtual void fadeTo(float, int);
+
+ private:
+ float m_volume;
+
+ //paramaters used to fade
+ Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve;
+
+ bool m_fading; //determines if we should be fading.
+ float m_initialVolume;
+ float m_targetVolume;
+ int m_fadeDuration;
+ int m_fadeSamplePosition;
+ qreal (*m_fadeCurveFn)(const qreal, const qreal, const qreal);
+
+ //allow the filter to get access to that
+ friend class VolumeEffectFilter;
+
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/gstreamer/CMakeLists.txt b/src/3rdparty/phonon/gstreamer/CMakeLists.txt
new file mode 100644
index 0000000..2249ac3
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/CMakeLists.txt
@@ -0,0 +1,92 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+#
+# This library 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, either version 2 or 3 of the License.
+#
+# This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+project(phonon-gstreamer)
+include(ConfigureChecks.cmake)
+
+if (BUILD_PHONON_GSTREAMER)
+ include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${GSTREAMER_INCLUDE_DIR}
+ ${GLIB2_INCLUDE_DIR}
+ ${LIBXML2_INCLUDE_DIR}
+ ${X11_X11_INCLUDE_PATH})
+ add_definitions(-DPHONON_BACKEND_VERSION_4_2)
+
+ # configure plugin api
+ if(USE_INSTALL_PLUGIN)
+ set(PLUGIN_INSTALL_API TRUE)
+ endif(USE_INSTALL_PLUGIN)
+
+ configure_file(phonon-config-gstreamer.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/phonon-config-gstreamer.h )
+
+ set(phonon_gstreamer_SRCS
+ audiooutput.cpp
+ backend.cpp
+ devicemanager.cpp
+ effectmanager.cpp
+ gsthelper.cpp
+ mediaobject.cpp
+ medianode.cpp
+ effect.cpp
+ medianodeevent.cpp
+ videowidget.cpp
+ qwidgetvideosink.cpp
+ streamreader.cpp
+ phononsrc.cpp
+ message.cpp
+ audioeffect.cpp
+ abstractrenderer.cpp
+ widgetrenderer.cpp
+ glrenderer.cpp
+ volumefadereffect.cpp
+ audiodataoutput.cpp
+ )
+
+ if(NOT WIN32)
+ set(phonon_gstreamer_SRCS
+ ${phonon_gstreamer_SRCS}
+ artssink.cpp
+ x11renderer.cpp)
+ macro_optional_find_package(Alsa)
+ macro_ensure_version("0.10.22" ${GSTREAMER_VERSION} GSTREAMER_HAS_NONBLOCKING_ALSASINK)
+ endif(NOT WIN32)
+ if(ALSA_FOUND AND NOT GSTREAMER_HAS_NONBLOCKING_ALSASINK)
+ add_definitions(-DUSE_ALSASINK2)
+ include_directories(${ALSA_INCLUDES})
+ set(phonon_gstreamer_SRCS
+ ${phonon_gstreamer_SRCS}
+ alsasink2.c
+ )
+ endif(ALSA_FOUND AND NOT GSTREAMER_HAS_NONBLOCKING_ALSASINK)
+
+ automoc4_add_library(phonon_gstreamer MODULE ${phonon_gstreamer_SRCS})
+ set_target_properties(phonon_gstreamer PROPERTIES PREFIX "")
+ target_link_libraries(phonon_gstreamer
+ ${QT_QTOPENGL_LIBRARY}
+ ${PHONON_LIBS} ${OPENGL_gl_LIBRARY}
+ ${GSTREAMER_LIBRARIES} ${GSTREAMER_BASE_LIBRARY} ${GSTREAMER_INTERFACE_LIBRARY}
+ ${GSTREAMER_PLUGIN_VIDEO_LIBRARIES} ${GSTREAMER_PLUGIN_AUDIO_LIBRARIES}
+ ${GLIB2_LIBRARIES} ${GOBJECT_LIBRARIES})
+ if(ALSA_FOUND)
+ target_link_libraries(phonon_gstreamer ${ASOUND_LIBRARY})
+ endif(ALSA_FOUND)
+ if(USE_INSTALL_PLUGIN)
+ target_link_libraries(phonon_gstreamer ${GSTREAMER_PLUGIN_PBUTILS_LIBRARIES})
+ endif(USE_INSTALL_PLUGIN)
+
+ install(TARGETS phonon_gstreamer DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/phonon_backend)
+ install(FILES gstreamer.desktop DESTINATION ${SERVICES_INSTALL_DIR}/phononbackends)
+endif (BUILD_PHONON_GSTREAMER)
diff --git a/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake b/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake
new file mode 100644
index 0000000..eaf5b99
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake
@@ -0,0 +1,38 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+#
+# This library 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, either version 2 or 3 of the License.
+#
+# This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+macro_optional_find_package(GStreamer)
+macro_log_feature(GSTREAMER_FOUND "GStreamer" "gstreamer 0.10 is required for the multimedia backend" "http://gstreamer.freedesktop.org/modules/" FALSE "0.10")
+
+macro_optional_find_package(GStreamerPlugins)
+macro_log_feature(GSTREAMER_PLUGIN_VIDEO_LIBRARIES "GStreamer video plugin" "The gstreamer video plugin (part of gstreamer-plugins-base 0.10) is required for the multimedia gstreamer backend" "http://gstreamer.freedesktop.org/modules/" FALSE "0.10")
+macro_log_feature(GSTREAMER_PLUGIN_AUDIO_LIBRARIES "GStreamer audio plugin" "The gstreamer audio plugin (part of gstreamer-plugins-base 0.10) is required for the multimedia gstreamer backend" "http://gstreamer.freedesktop.org/modules/" FALSE "0.10")
+
+macro_optional_find_package(GLIB2)
+macro_log_feature(GLIB2_FOUND "GLib2" "GLib 2 is required to compile the gstreamer backend for Phonon" "http://www.gtk.org/download/" FALSE)
+
+macro_optional_find_package(GObject)
+# No log, since GObject is bundled with GLib
+
+macro_optional_find_package(LibXml2)
+macro_log_feature(LIBXML2_FOUND "LibXml2" "LibXml2 is required to compile the gstreamer backend for Phonon" "http://xmlsoft.org/downloads.html" FALSE)
+
+macro_optional_find_package(OpenGL)
+macro_log_feature(OPENGL_FOUND "OpenGL" "OpenGL support is required to compile the gstreamer backend for Phonon" "" FALSE)
+
+if (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
+ set(BUILD_PHONON_GSTREAMER TRUE)
+else (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
+ set(BUILD_PHONON_GSTREAMER FALSE)
+endif (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
diff --git a/src/3rdparty/phonon/gstreamer/Messages.sh b/src/3rdparty/phonon/gstreamer/Messages.sh
new file mode 100644
index 0000000..4fdf1ef
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/Messages.sh
@@ -0,0 +1,5 @@
+#! /usr/bin/env bash
+find ./ -maxdepth 1 -name "*.cpp" -print > files
+find ./ -maxdepth 1 -name "*.h" -print >> files
+$XGETTEXT_QT --copyright-holder=This_file_is_part_of_KDE --msgid-bugs-address=http://bugs.kde.org --files-from=files -o $podir/phonon_gstreamer.pot
+rm files
diff --git a/src/3rdparty/phonon/gstreamer/abstractrenderer.cpp b/src/3rdparty/phonon/gstreamer/abstractrenderer.cpp
new file mode 100644
index 0000000..5d88d10
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/abstractrenderer.cpp
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "abstractrenderer.h"
+
+#ifndef QT_NO_PHONON_VIDEO
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+
+AbstractRenderer::~AbstractRenderer()
+{
+ if (m_videoSink) {
+ gst_object_unref (GST_OBJECT (m_videoSink)); //Take ownership
+ m_videoSink = 0;
+ }
+}
+
+void AbstractRenderer::aspectRatioChanged(Phonon::VideoWidget::AspectRatio aspectRatio)
+{
+ Q_UNUSED(aspectRatio);
+}
+
+void AbstractRenderer::scaleModeChanged(Phonon::VideoWidget::ScaleMode scaleMode)
+{
+ Q_UNUSED(scaleMode);
+}
+
+void AbstractRenderer::movieSizeChanged(const QSize &size)
+{
+ Q_UNUSED(size);
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_VIDEO
+
diff --git a/src/3rdparty/phonon/gstreamer/abstractrenderer.h b/src/3rdparty/phonon/gstreamer/abstractrenderer.h
new file mode 100644
index 0000000..10a2822
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/abstractrenderer.h
@@ -0,0 +1,63 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2 //Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).007 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_ABSTRACTRENDERER_H
+#define Phonon_GSTREAMER_ABSTRACTRENDERER_H
+
+#include "backend.h"
+#include "common.h"
+#include "medianode.h"
+#include <phonon/videowidget.h>
+
+#ifndef QT_NO_PHONON_VIDEO
+QT_BEGIN_NAMESPACE
+
+class QString;
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class VideoWidget;
+
+class AbstractRenderer
+{
+public:
+ AbstractRenderer(VideoWidget *video) :
+ m_videoWidget(video)
+ , m_videoSink(0) { }
+ virtual ~AbstractRenderer();
+ virtual GstElement *videoSink() {return m_videoSink;}
+ virtual void aspectRatioChanged(Phonon::VideoWidget::AspectRatio aspectRatio);
+ virtual void scaleModeChanged(Phonon::VideoWidget::ScaleMode scaleMode);
+ virtual void movieSizeChanged(const QSize &movieSize);
+ virtual void handleMediaNodeEvent(const MediaNodeEvent *event) = 0;
+ virtual bool eventFilter(QEvent *) = 0;
+ virtual void handlePaint(QPaintEvent *) {}
+ virtual bool paintsOnWidget() { return true; } // Controls overlays
+
+protected:
+ VideoWidget *m_videoWidget;
+ GstElement *m_videoSink;
+};
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_VIDEO
+#endif // Phonon_GSTREAMER_ABSTRACTRENDERER_H
diff --git a/src/3rdparty/phonon/gstreamer/alsasink2.c b/src/3rdparty/phonon/gstreamer/alsasink2.c
new file mode 100644
index 0000000..4dcb140
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/alsasink2.c
@@ -0,0 +1,1756 @@
+/* GStreamer
+ * Copyright (C) 2001 CodeFactory AB
+ * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
+ * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
+ * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2005, 2006 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+ *
+ * gstalsasink2.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:element-alsasink2
+ * @short_description: play audio to an ALSA device
+ * @see_also: alsasrc, alsamixer
+ *
+ * <refsect2>
+ * <para>
+ * This element renders raw audio samples using the ALSA api.
+ * </para>
+ * <title>Example pipelines</title>
+ * <para>
+ * Play an Ogg/Vorbis file.
+ * </para>
+ * <programlisting>
+ * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! alsasink2
+ * </programlisting>
+ * </refsect2>
+ *
+ * Last reviewed on 2006-03-01 (0.10.4)
+ */
+
+#define _XOPEN_SOURCE 600
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <alsa/asoundlib.h>
+
+#include "alsasink2.h"
+
+#include <gst/interfaces/propertyprobe.h>
+#include <gst/audio/multichannel.h>
+
+#define _(text) (text)
+
+#define GST_CHECK_ALSA_VERSION(major,minor,micro) \
+ (SND_LIB_MAJOR > (major) || \
+ (SND_LIB_MAJOR == (major) && SND_LIB_MINOR > (minor)) || \
+ (SND_LIB_MAJOR == (major) && SND_LIB_MINOR == (minor) && \
+ SND_LIB_SUBMINOR >= (micro)))
+
+static const GList *
+gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe)
+{
+ GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
+ static GList *list = NULL;
+
+ /* well, not perfect, but better than no locking at all.
+ * In the worst case we leak a list node, so who cares? */
+ GST_CLASS_LOCK (GST_OBJECT_CLASS (klass));
+
+ if (!list) {
+ GParamSpec *pspec;
+
+ pspec = g_object_class_find_property (klass, "device");
+ list = g_list_append (NULL, pspec);
+ }
+
+ GST_CLASS_UNLOCK (GST_OBJECT_CLASS (klass));
+
+ return list;
+}
+
+static GList *
+gst_alsa_get_device_list (snd_pcm_stream_t stream)
+{
+ snd_ctl_t *handle;
+ int card, err, dev;
+ snd_ctl_card_info_t *info;
+ snd_pcm_info_t *pcminfo;
+ gboolean mixer = (stream == ~0u);
+ GList *list = NULL;
+
+ if (stream == ~0u)
+ stream = 0;
+
+ snd_ctl_card_info_malloc (&info);
+ snd_pcm_info_malloc (&pcminfo);
+ card = -1;
+
+ if (snd_card_next (&card) < 0 || card < 0) {
+ /* no soundcard found */
+ return NULL;
+ }
+
+ while (card >= 0) {
+ gchar name[32];
+
+ g_snprintf (name, sizeof (name), "hw:%d", card);
+ if ((err = snd_ctl_open (&handle, name, 0)) < 0) {
+ goto next_card;
+ }
+ if ((err = snd_ctl_card_info (handle, info)) < 0) {
+ snd_ctl_close (handle);
+ goto next_card;
+ }
+
+ if (mixer) {
+ list = g_list_append (list, g_strdup (name));
+ } else {
+ g_snprintf (name, sizeof (name), "default:CARD=%d", card);
+ list = g_list_append (list, g_strdup (name));
+ dev = -1;
+ while (1) {
+ gchar *gst_device;
+
+ snd_ctl_pcm_next_device (handle, &dev);
+
+ if (dev < 0)
+ break;
+ snd_pcm_info_set_device (pcminfo, dev);
+ snd_pcm_info_set_subdevice (pcminfo, 0);
+ snd_pcm_info_set_stream (pcminfo, stream);
+ if ((err = snd_ctl_pcm_info (handle, pcminfo)) < 0) {
+ continue;
+ }
+
+ gst_device = g_strdup_printf ("hw:%d,%d", card, dev);
+ list = g_list_append (list, gst_device);
+ }
+ }
+ snd_ctl_close (handle);
+ next_card:
+ if (snd_card_next (&card) < 0) {
+ break;
+ }
+ }
+
+ snd_ctl_card_info_free (info);
+ snd_pcm_info_free (pcminfo);
+
+ return list;
+}
+
+static void
+gst_alsa_device_property_probe_probe_property (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec)
+{
+ if (!g_str_equal (pspec->name, "device")) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+ }
+}
+
+static gboolean
+gst_alsa_device_property_probe_needs_probe (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec)
+{
+ /* don't cache probed data */
+ return TRUE;
+}
+
+static GValueArray *
+gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe,
+ guint prop_id, const GParamSpec * pspec)
+{
+ GstElementClass *klass;
+ const GList *templates;
+ snd_pcm_stream_t mode = -1;
+ GValueArray *array;
+ GValue value = { 0, };
+ GList *l, *list;
+
+ if (!g_str_equal (pspec->name, "device")) {
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
+ return NULL;
+ }
+
+ klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe));
+
+ /* I'm pretty sure ALSA has a good way to do this. However, their cool
+ * auto-generated documentation is pretty much useless if you try to
+ * do function-wise look-ups. */
+ /* we assume one pad template at max [zero=mixer] */
+ templates = gst_element_class_get_pad_template_list (klass);
+ if (templates) {
+ if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC)
+ mode = SND_PCM_STREAM_CAPTURE;
+ else
+ mode = SND_PCM_STREAM_PLAYBACK;
+ }
+
+ list = gst_alsa_get_device_list (mode);
+
+ if (list == NULL) {
+ GST_LOG_OBJECT (probe, "No devices found");
+ return NULL;
+ }
+
+ array = g_value_array_new (g_list_length (list));
+ g_value_init (&value, G_TYPE_STRING);
+ for (l = list; l != NULL; l = l->next) {
+ GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data);
+ g_value_take_string (&value, (gchar *) l->data);
+ l->data = NULL;
+ g_value_array_append (array, &value);
+ }
+ g_value_unset (&value);
+ g_list_free (list);
+
+ return array;
+}
+
+static void
+gst_alsa_property_probe_interface_init (GstPropertyProbeInterface * iface)
+{
+ iface->get_properties = gst_alsa_device_property_probe_get_properties;
+ iface->probe_property = gst_alsa_device_property_probe_probe_property;
+ iface->needs_probe = gst_alsa_device_property_probe_needs_probe;
+ iface->get_values = gst_alsa_device_property_probe_get_values;
+}
+
+static void
+gst_alsa_type_add_device_property_probe_interface (GType type)
+{
+ static const GInterfaceInfo probe_iface_info = {
+ (GInterfaceInitFunc) gst_alsa_property_probe_interface_init,
+ NULL,
+ NULL,
+ };
+
+ g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
+ &probe_iface_info);
+}
+
+static GstCaps *
+gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params,
+ GstCaps * in_caps)
+{
+ GstCaps *caps;
+ guint min, max;
+ gint err, dir, min_rate, max_rate;
+ guint i;
+
+ GST_LOG_OBJECT (obj, "probing sample rates ...");
+
+ if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0)
+ goto min_rate_err;
+
+ if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0)
+ goto max_rate_err;
+
+ min_rate = min;
+ max_rate = max;
+
+ if (min_rate < 4000)
+ min_rate = 4000; /* random 'sensible minimum' */
+
+ if (max_rate <= 0)
+ max_rate = G_MAXINT; /* or maybe just use 192400 or so? */
+ else if (max_rate > 0 && max_rate < 4000)
+ max_rate = MAX (4000, min_rate);
+
+ GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min);
+ GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max);
+
+ caps = gst_caps_make_writable (in_caps);
+
+ for (i = 0; i < gst_caps_get_size (caps); ++i) {
+ GstStructure *s;
+
+ s = gst_caps_get_structure (caps, i);
+ if (min_rate == max_rate) {
+ gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL);
+ } else {
+ gst_structure_set (s, "rate", GST_TYPE_INT_RANGE,
+ min_rate, max_rate, NULL);
+ }
+ }
+
+ return caps;
+
+ /* ERRORS */
+min_rate_err:
+ {
+ GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s",
+ snd_strerror (err));
+ gst_caps_unref (in_caps);
+ return NULL;
+ }
+max_rate_err:
+ {
+ GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s",
+ snd_strerror (err));
+ gst_caps_unref (in_caps);
+ return NULL;
+ }
+}
+
+static const struct
+{
+ const int width;
+ const int depth;
+ const int sformat;
+ const int uformat;
+} pcmformats[] = {
+ {
+ 8, 8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8}, {
+ 16, 16, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16}, {
+ 32, 24, SND_PCM_FORMAT_S24, SND_PCM_FORMAT_U24}, {
+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) /* no endian-unspecific enum available */
+ 24, 24, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_U24_3LE}, {
+#else
+ 24, 24, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_U24_3BE}, {
+#endif
+ 32, 32, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_U32}
+};
+
+static GstCaps *
+gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
+ GstCaps * in_caps)
+{
+ snd_pcm_format_mask_t *mask;
+ GstStructure *s;
+ GstCaps *caps;
+ guint i;
+
+ snd_pcm_format_mask_malloc (&mask);
+ snd_pcm_hw_params_get_format_mask (hw_params, mask);
+
+ caps = gst_caps_new_empty ();
+
+ for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
+ GstStructure *scopy;
+ guint w;
+ gint width = 0, depth = 0;
+
+ s = gst_caps_get_structure (in_caps, i);
+ if (!gst_structure_has_name (s, "audio/x-raw-int")) {
+ GST_WARNING_OBJECT (obj, "skipping non-int format");
+ continue;
+ }
+ if (!gst_structure_get_int (s, "width", &width) ||
+ !gst_structure_get_int (s, "depth", &depth))
+ continue;
+ if (width == 0 || (width % 8) != 0)
+ continue; /* Only full byte widths are valid */
+ for (w = 0; w < G_N_ELEMENTS (pcmformats); w++)
+ if (pcmformats[w].width == width && pcmformats[w].depth == depth)
+ break;
+ if (w == G_N_ELEMENTS (pcmformats))
+ continue; /* Unknown format */
+
+ if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) &&
+ snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
+ /* template contains { true, false } or just one, leave it as it is */
+ scopy = gst_structure_copy (s);
+ } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) {
+ scopy = gst_structure_copy (s);
+ gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+ } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
+ scopy = gst_structure_copy (s);
+ gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
+ } else {
+ scopy = NULL;
+ }
+ if (scopy) {
+ if (width > 8) {
+ /* TODO: proper endianness detection, for now it's CPU endianness only */
+ gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
+ }
+ gst_caps_append_structure (caps, scopy);
+ }
+ }
+
+ snd_pcm_format_mask_free (mask);
+ gst_caps_unref (in_caps);
+ return caps;
+}
+
+/* we don't have channel mappings for more than this many channels */
+#define GST_ALSA_MAX_CHANNELS 8
+
+static GstStructure *
+get_channel_free_structure (const GstStructure * in_structure)
+{
+ GstStructure *s = gst_structure_copy (in_structure);
+
+ gst_structure_remove_field (s, "channels");
+ return s;
+}
+
+static void
+caps_add_channel_configuration (GstCaps * caps,
+ const GstStructure * in_structure, gint min_chans, gint max_chans)
+{
+ GstAudioChannelPosition pos[8] = {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+ GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
+ GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_LFE,
+ GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
+ };
+ GstStructure *s = NULL;
+ gint c;
+
+ if (min_chans == max_chans && max_chans <= 2) {
+ s = get_channel_free_structure (in_structure);
+ gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
+ gst_caps_append_structure (caps, s);
+ return;
+ }
+
+ g_assert (min_chans >= 1);
+
+ /* mono and stereo don't need channel configurations */
+ if (min_chans == 2) {
+ s = get_channel_free_structure (in_structure);
+ gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
+ gst_caps_append_structure (caps, s);
+ } else if (min_chans == 1 && max_chans >= 2) {
+ s = get_channel_free_structure (in_structure);
+ gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
+ gst_caps_append_structure (caps, s);
+ }
+
+ /* don't know whether to use 2.1 or 3.0 here - but I suspect
+ * alsa might work around that/fix it somehow. Can we tell alsa
+ * what our channel layout is like? */
+ if (max_chans >= 3 && min_chans <= 3) {
+ GstAudioChannelPosition pos_21[3] = {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+ GST_AUDIO_CHANNEL_POSITION_LFE
+ };
+
+ s = get_channel_free_structure (in_structure);
+ gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
+ gst_audio_set_channel_positions (s, pos_21);
+ gst_caps_append_structure (caps, s);
+ }
+
+ /* everything else (4, 6, 8 channels) needs a channel layout */
+ for (c = MAX (4, min_chans); c <= 8; c += 2) {
+ if (max_chans >= c) {
+ s = get_channel_free_structure (in_structure);
+ gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
+ gst_audio_set_channel_positions (s, pos);
+ gst_caps_append_structure (caps, s);
+ }
+ }
+
+ for (c = MAX (9, min_chans); c <= max_chans; ++c) {
+ GstAudioChannelPosition *ch_layout;
+ gint i;
+
+ ch_layout = g_new (GstAudioChannelPosition, c);
+ for (i = 0; i < c; ++i) {
+ ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+ }
+ s = get_channel_free_structure (in_structure);
+ gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
+ gst_audio_set_channel_positions (s, ch_layout);
+ gst_caps_append_structure (caps, s);
+ g_free (ch_layout);
+ }
+}
+
+static GstCaps *
+gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
+ GstCaps * in_caps)
+{
+ GstCaps *caps;
+ guint min, max;
+ gint min_chans, max_chans;
+ gint err;
+ guint i;
+
+ GST_LOG_OBJECT (obj, "probing channels ...");
+
+ if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
+ goto min_chan_error;
+
+ if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
+ goto max_chan_error;
+
+ /* note: the above functions may return (guint) -1 */
+ min_chans = min;
+ max_chans = max;
+
+ if (min_chans < 0) {
+ min_chans = 1;
+ max_chans = GST_ALSA_MAX_CHANNELS;
+ } else if (max_chans < 0) {
+ max_chans = GST_ALSA_MAX_CHANNELS;
+ }
+
+ if (min_chans > max_chans) {
+ gint temp;
+
+ GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
+ "please fix your soundcard drivers", min, max);
+ temp = min_chans;
+ min_chans = max_chans;
+ max_chans = temp;
+ }
+
+ /* pro cards seem to return large numbers for min_channels */
+ if (min_chans > GST_ALSA_MAX_CHANNELS) {
+ GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
+ if (max_chans < min_chans) {
+ max_chans = min_chans;
+ } else {
+ /* only support [max_chans; max_chans] for these cards for now
+ * to avoid inflating the source caps with loads of structures ... */
+ min_chans = max_chans;
+ }
+ } else {
+ min_chans = MAX (min_chans, 1);
+ max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
+ }
+
+ GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
+ GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
+
+ caps = gst_caps_new_empty ();
+
+ for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
+ GstStructure *s;
+ GType field_type;
+ gint c_min = min_chans;
+ gint c_max = max_chans;
+
+ s = gst_caps_get_structure (in_caps, i);
+ /* the template caps might limit the number of channels (like alsasrc),
+ * in which case we don't want to return a superset, so hack around this
+ * for the two common cases where the channels are either a fixed number
+ * or a min/max range). Example: alsasrc template has channels = [1,2] and
+ * the detection will claim to support 8 channels for device 'plughw:0' */
+ field_type = gst_structure_get_field_type (s, "channels");
+ if (field_type == G_TYPE_INT) {
+ gst_structure_get_int (s, "channels", &c_min);
+ gst_structure_get_int (s, "channels", &c_max);
+ } else if (field_type == GST_TYPE_INT_RANGE) {
+ const GValue *val;
+
+ val = gst_structure_get_value (s, "channels");
+ c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
+ c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
+ } else {
+ c_min = min_chans;
+ c_max = max_chans;
+ }
+
+ caps_add_channel_configuration (caps, s, c_min, c_max);
+ }
+
+ gst_caps_unref (in_caps);
+
+ return caps;
+
+ /* ERRORS */
+min_chan_error:
+ {
+ GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
+ snd_strerror (err));
+ return NULL;
+ }
+max_chan_error:
+ {
+ GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
+ snd_strerror (err));
+ return NULL;
+ }
+}
+
+#ifndef GST_CHECK_VERSION
+#define GST_CHECK_VERSION(major,minor,micro) \
+ (GST_VERSION_MAJOR > (major) || \
+ (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR > (minor)) || \
+ (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR == (minor) && GST_VERSION_MICRO >= (micro)))
+#endif
+
+#if GST_CHECK_VERSION(0, 10, 18)
+snd_pcm_t *
+gst_alsa_open_iec958_pcm (GstObject * obj)
+{
+ char *iec958_pcm_name = NULL;
+ snd_pcm_t *pcm = NULL;
+ int res;
+ char devstr[256]; /* Storage for local 'default' device string */
+
+ /*
+ * Try and open our default iec958 device. Fall back to searching on card x
+ * if this fails, which should only happen on older alsa setups
+ */
+
+ /* The string will be one of these:
+ * SPDIF_CON: Non-audio flag not set:
+ * spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2}
+ * SPDIF_CON: Non-audio flag set:
+ * spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2}
+ */
+ sprintf (devstr,
+ "iec958:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}",
+ IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
+ IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
+ 0, IEC958_AES3_CON_FS_48000);
+
+ GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr);
+ iec958_pcm_name = devstr;
+
+ res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
+ if (G_UNLIKELY (res < 0)) {
+ GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s",
+ snd_strerror (res));
+ pcm = NULL;
+ }
+
+ return pcm;
+}
+#endif
+
+
+/*
+ * gst_alsa_probe_supported_formats:
+ *
+ * Takes the template caps and returns the subset which is actually
+ * supported by this device.
+ *
+ */
+
+GstCaps *
+gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle,
+ const GstCaps * template_caps)
+{
+ snd_pcm_hw_params_t *hw_params;
+ snd_pcm_stream_t stream_type;
+ GstCaps *caps;
+ gint err;
+
+ snd_pcm_hw_params_malloc (&hw_params);
+ if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0)
+ goto error;
+
+ stream_type = snd_pcm_stream (handle);
+
+ caps = gst_caps_copy (template_caps);
+
+ if (!(caps = gst_alsa_detect_formats (obj, hw_params, caps)))
+ goto subroutine_error;
+
+ if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps)))
+ goto subroutine_error;
+
+ if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps)))
+ goto subroutine_error;
+
+#if GST_CHECK_VERSION(0, 10, 18)
+ /* Try opening IEC958 device to see if we can support that format (playback
+ * only for now but we could add SPDIF capture later) */
+ if (stream_type == SND_PCM_STREAM_PLAYBACK) {
+ snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj);
+
+ if (G_LIKELY (pcm)) {
+ gst_caps_append (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
+ snd_pcm_close (pcm);
+ }
+ }
+#endif
+
+ snd_pcm_hw_params_free (hw_params);
+ return caps;
+
+ /* ERRORS */
+error:
+ {
+ GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err));
+ snd_pcm_hw_params_free (hw_params);
+ return NULL;
+ }
+subroutine_error:
+ {
+ GST_ERROR_OBJECT (obj, "failed to query formats");
+ snd_pcm_hw_params_free (hw_params);
+ return NULL;
+ }
+}
+
+static gchar *
+gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
+ gint device_num, snd_pcm_stream_t stream)
+{
+ snd_ctl_card_info_t *info = NULL;
+ snd_ctl_t *ctl = NULL;
+ gchar *ret = NULL;
+ gint dev = -1;
+
+ GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);
+
+ if (snd_ctl_open (&ctl, devcard, 0) < 0)
+ return NULL;
+
+ snd_ctl_card_info_malloc (&info);
+ if (snd_ctl_card_info (ctl, info) < 0)
+ goto done;
+
+ while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
+ if (dev == device_num) {
+ snd_pcm_info_t *pcminfo;
+
+ snd_pcm_info_malloc (&pcminfo);
+ snd_pcm_info_set_device (pcminfo, dev);
+ snd_pcm_info_set_subdevice (pcminfo, 0);
+ snd_pcm_info_set_stream (pcminfo, stream);
+ if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
+ snd_pcm_info_free (pcminfo);
+ break;
+ }
+
+ ret = g_strdup (snd_pcm_info_get_name (pcminfo));
+ snd_pcm_info_free (pcminfo);
+ GST_LOG_OBJECT (obj, "name from pcminfo: %s", GST_STR_NULL (ret));
+ }
+ }
+
+ if (ret == NULL) {
+ char *name = NULL;
+ gint card;
+
+ GST_LOG_OBJECT (obj, "no luck so far, trying backup");
+ card = snd_ctl_card_info_get_card (info);
+ snd_card_get_name (card, &name);
+ ret = g_strdup (name);
+ free (name);
+ }
+
+done:
+ snd_ctl_card_info_free (info);
+ snd_ctl_close (ctl);
+
+ return ret;
+}
+
+gchar *
+gst_alsa_find_device_name (GstObject * obj, const gchar * device,
+ snd_pcm_t * handle, snd_pcm_stream_t stream)
+{
+ gchar *ret = NULL;
+
+ if (device != NULL) {
+ gchar *dev, *comma;
+ gint devnum;
+
+ GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);
+
+ /* only want name:card bit, but not devices and subdevices */
+ dev = g_strdup (device);
+ if ((comma = strchr (dev, ','))) {
+ *comma = '\0';
+ devnum = atoi (comma + 1);
+ ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
+ }
+ g_free (dev);
+ }
+
+ if (ret == NULL && handle != NULL) {
+ snd_pcm_info_t *info;
+
+ GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
+ snd_pcm_info_malloc (&info);
+ snd_pcm_info (handle, info);
+ ret = g_strdup (snd_pcm_info_get_name (info));
+ snd_pcm_info_free (info);
+ }
+
+ GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
+ GST_STR_NULL (device), GST_STR_NULL (ret));
+
+ return ret;
+}
+
+/* elementfactory information */
+static const GstElementDetails gst_alsasink2_details =
+GST_ELEMENT_DETAILS ("Audio sink (ALSA)",
+ "Sink/Audio",
+ "Output to a sound card via ALSA",
+ "Wim Taymans <wim@fluendo.com>");
+
+#define DEFAULT_DEVICE "default"
+#define DEFAULT_DEVICE_NAME ""
+#define SPDIF_PERIOD_SIZE 1536
+#define SPDIF_BUFFER_SIZE 15360
+
+enum
+{
+ PROP_0,
+ PROP_DEVICE,
+ PROP_DEVICE_NAME
+};
+
+static void gst_alsasink2_init_interfaces (GType type);
+
+GST_BOILERPLATE_FULL (_k_GstAlsaSink, gst_alsasink2, GstAudioSink,
+ GST_TYPE_AUDIO_SINK, gst_alsasink2_init_interfaces);
+
+static void gst_alsasink2_finalise (GObject * object);
+static void gst_alsasink2_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_alsasink2_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_alsasink2_getcaps (GstBaseSink * bsink);
+
+static gboolean gst_alsasink2_open (GstAudioSink * asink);
+static gboolean gst_alsasink2_prepare (GstAudioSink * asink,
+ GstRingBufferSpec * spec);
+static gboolean gst_alsasink2_unprepare (GstAudioSink * asink);
+static gboolean gst_alsasink2_close (GstAudioSink * asink);
+static guint gst_alsasink2_write (GstAudioSink * asink, gpointer data,
+ guint length);
+static guint gst_alsasink2_delay (GstAudioSink * asink);
+static void gst_alsasink2_reset (GstAudioSink * asink);
+
+static gint output_ref; /* 0 */
+static snd_output_t *output; /* NULL */
+static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
+
+
+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+# define ALSA_SINK2_FACTORY_ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
+#else
+# define ALSA_SINK2_FACTORY_ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
+#endif
+
+static GstStaticPadTemplate alsasink2_sink_factory =
+ GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 32, "
+ "depth = (int) 32, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
+ "audio/x-raw-int, "
+ "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 24, "
+ "depth = (int) 24, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
+ "audio/x-raw-int, "
+ "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 32, "
+ "depth = (int) 24, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
+ "audio/x-raw-int, "
+ "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
+ "audio/x-raw-int, "
+ "signed = (boolean) { TRUE, FALSE }, "
+ "width = (int) 8, "
+ "depth = (int) 8, "
+ "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
+ "audio/x-iec958")
+ );
+
+static void
+gst_alsasink2_finalise (GObject * object)
+{
+ _k_GstAlsaSink *sink = GST_ALSA_SINK2 (object);
+
+ g_free (sink->device);
+ g_mutex_free (sink->alsa_lock);
+
+ g_static_mutex_lock (&output_mutex);
+ --output_ref;
+ if (output_ref == 0) {
+ snd_output_close (output);
+ output = NULL;
+ }
+ g_static_mutex_unlock (&output_mutex);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_alsasink2_init_interfaces (GType type)
+{
+ gst_alsa_type_add_device_property_probe_interface (type);
+}
+
+static void
+gst_alsasink2_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_set_details (element_class, &gst_alsasink2_details);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&alsasink2_sink_factory));
+}
+static void
+gst_alsasink2_class_init (_k_GstAlsaSinkClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+ GstBaseAudioSinkClass *gstbaseaudiosink_class;
+ GstAudioSinkClass *gstaudiosink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
+ gstaudiosink_class = (GstAudioSinkClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasink2_finalise);
+ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasink2_get_property);
+ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasink2_set_property);
+
+ gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink2_getcaps);
+
+ gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink2_open);
+ gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink2_prepare);
+ gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink2_unprepare);
+ gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink2_close);
+ gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink2_write);
+ gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink2_delay);
+ gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink2_reset);
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE,
+ g_param_spec_string ("device", "Device",
+ "ALSA device, as defined in an asound configuration file",
+ DEFAULT_DEVICE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+ g_param_spec_string ("device-name", "Device name",
+ "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
+ G_PARAM_READABLE));
+}
+
+static void
+gst_alsasink2_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ _k_GstAlsaSink *sink;
+
+ sink = GST_ALSA_SINK2 (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_free (sink->device);
+ sink->device = g_value_dup_string (value);
+ /* setting NULL restores the default device */
+ if (sink->device == NULL) {
+ sink->device = g_strdup (DEFAULT_DEVICE);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_alsasink2_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ _k_GstAlsaSink *sink;
+
+ sink = GST_ALSA_SINK2 (object);
+
+ switch (prop_id) {
+ case PROP_DEVICE:
+ g_value_set_string (value, sink->device);
+ break;
+ case PROP_DEVICE_NAME:
+ g_value_take_string (value,
+ gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
+ sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_alsasink2_init (_k_GstAlsaSink * alsasink2, _k_GstAlsaSinkClass * g_class)
+{
+ GST_DEBUG_OBJECT (alsasink2, "initializing alsasink2");
+
+ alsasink2->device = g_strdup (DEFAULT_DEVICE);
+ alsasink2->handle = NULL;
+ alsasink2->cached_caps = NULL;
+ alsasink2->alsa_lock = g_mutex_new ();
+
+ g_static_mutex_lock (&output_mutex);
+ if (output_ref == 0) {
+ snd_output_stdio_attach (&output, stdout, 0);
+ ++output_ref;
+ }
+ g_static_mutex_unlock (&output_mutex);
+}
+
+#define CHECK(call, error) \
+G_STMT_START { \
+if ((err = call) < 0) \
+ goto error; \
+} G_STMT_END;
+
+static GstCaps *
+gst_alsasink2_getcaps (GstBaseSink * bsink)
+{
+ GstElementClass *element_class;
+ GstPadTemplate *pad_template;
+ _k_GstAlsaSink *sink = GST_ALSA_SINK2 (bsink);
+ GstCaps *caps;
+
+ if (sink->handle == NULL) {
+ GST_DEBUG_OBJECT (sink, "device not open, using template caps");
+ return NULL; /* base class will get template caps for us */
+ }
+
+ if (sink->cached_caps) {
+ GST_LOG_OBJECT (sink, "Returning cached caps");
+ return gst_caps_ref (sink->cached_caps);
+ }
+
+ element_class = GST_ELEMENT_GET_CLASS (sink);
+ pad_template = gst_element_class_get_pad_template (element_class, "sink");
+ g_return_val_if_fail (pad_template != NULL, NULL);
+
+ caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
+ gst_pad_template_get_caps (pad_template));
+
+ if (caps) {
+ sink->cached_caps = gst_caps_ref (caps);
+ }
+
+ GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
+
+ return caps;
+}
+
+static int
+set_hwparams (_k_GstAlsaSink * alsa)
+{
+ guint rrate;
+ gint err, dir;
+ snd_pcm_hw_params_t *params;
+ guint period_time, buffer_time;
+
+ snd_pcm_hw_params_malloc (&params);
+
+ GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
+ "SPDIF (%d)", alsa->channels, alsa->rate,
+ snd_pcm_format_name (alsa->format), alsa->iec958);
+
+ /* start with requested values, if we cannot configure alsa for those values,
+ * we set these values to -1, which will leave the default alsa values */
+ buffer_time = alsa->buffer_time;
+ period_time = alsa->period_time;
+
+retry:
+ /* choose all parameters */
+ CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
+ /* set the interleaved read/write format */
+ CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
+ wrong_access);
+ /* set the sample format */
+#if GST_CHECK_VERSION(0, 10, 18)
+ if (alsa->iec958) {
+ /* Try to use big endian first else fallback to le and swap bytes */
+ if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
+ alsa->format = SND_PCM_FORMAT_S16_LE;
+ alsa->need_swap = TRUE;
+ GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
+ } else {
+ alsa->need_swap = FALSE;
+ }
+ }
+#endif
+ CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
+ no_sample_format);
+ /* set the count of channels */
+ CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
+ no_channels);
+ /* set the stream rate */
+ rrate = alsa->rate;
+ CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
+ no_rate);
+ if (rrate != alsa->rate)
+ goto rate_match;
+
+ /* get and dump some limits */
+ {
+ guint min, max;
+
+ snd_pcm_hw_params_get_buffer_time_min (params, &min, &dir);
+ snd_pcm_hw_params_get_buffer_time_max (params, &max, &dir);
+
+ GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
+ alsa->buffer_time, min, max);
+
+ snd_pcm_hw_params_get_period_time_min (params, &min, &dir);
+ snd_pcm_hw_params_get_period_time_max (params, &max, &dir);
+
+ GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
+ alsa->period_time, min, max);
+
+ snd_pcm_hw_params_get_periods_min (params, &min, &dir);
+ snd_pcm_hw_params_get_periods_max (params, &max, &dir);
+
+ GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
+ }
+
+ /* now try to configure the buffer time and period time, if one
+ * of those fail, we fall back to the defaults and emit a warning. */
+ if (buffer_time != ~0u && !alsa->iec958) {
+ /* set the buffer time */
+ if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
+ &buffer_time, &dir)) < 0) {
+ GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set buffer time %i for playback: %s",
+ buffer_time, snd_strerror (err)));
+ /* disable buffer_time the next round */
+ buffer_time = -1;
+ goto retry;
+ }
+ GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
+ }
+ if (period_time != ~0u && !alsa->iec958) {
+ /* set the period time */
+ if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
+ &period_time, &dir)) < 0) {
+ GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set period time %i for playback: %s",
+ period_time, snd_strerror (err)));
+ /* disable period_time the next round */
+ period_time = -1;
+ goto retry;
+ }
+ GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
+ }
+
+ /* Set buffer size and period size manually for SPDIF */
+ if (G_UNLIKELY (alsa->iec958)) {
+ snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
+ snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
+
+ CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
+ &buffer_size), buffer_size);
+ CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
+ &period_size, NULL), period_size);
+ }
+
+ /* write the parameters to device */
+ CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
+
+ /* now get the configured values */
+ CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
+ buffer_size);
+ CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
+ period_size);
+
+ GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
+ alsa->period_size);
+
+ snd_pcm_hw_params_free (params);
+ return 0;
+
+ /* ERRORS */
+no_config:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Broken configuration for playback: no configurations available: %s",
+ snd_strerror (err)));
+ snd_pcm_hw_params_free (params);
+ return err;
+ }
+wrong_access:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Access type not available for playback: %s", snd_strerror (err)));
+ snd_pcm_hw_params_free (params);
+ return err;
+ }
+no_sample_format:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Sample format not available for playback: %s", snd_strerror (err)));
+ snd_pcm_hw_params_free (params);
+ return err;
+ }
+no_channels:
+ {
+ gchar *msg = NULL;
+
+ if ((alsa->channels) == 1)
+ msg = g_strdup (_("Could not open device for playback in mono mode."));
+ if ((alsa->channels) == 2)
+ msg = g_strdup (_("Could not open device for playback in stereo mode."));
+ if ((alsa->channels) > 2)
+ msg =
+ g_strdup_printf (_
+ ("Could not open device for playback in %d-channel mode."),
+ alsa->channels);
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
+ g_free (msg);
+ snd_pcm_hw_params_free (params);
+ return err;
+ }
+no_rate:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Rate %iHz not available for playback: %s",
+ alsa->rate, snd_strerror (err)));
+ return err;
+ }
+rate_match:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
+ snd_pcm_hw_params_free (params);
+ return -EINVAL;
+ }
+buffer_size:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to get buffer size for playback: %s", snd_strerror (err)));
+ snd_pcm_hw_params_free (params);
+ return err;
+ }
+period_size:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to get period size for playback: %s", snd_strerror (err)));
+ snd_pcm_hw_params_free (params);
+ return err;
+ }
+set_hw_params:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set hw params for playback: %s", snd_strerror (err)));
+ snd_pcm_hw_params_free (params);
+ return err;
+ }
+}
+
+static int
+set_swparams (_k_GstAlsaSink * alsa)
+{
+ int err;
+ snd_pcm_sw_params_t *params;
+
+ snd_pcm_sw_params_malloc (&params);
+
+ /* get the current swparams */
+ CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
+ /* start the transfer when the buffer is almost full: */
+ /* (buffer_size / avail_min) * avail_min */
+ CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
+ (alsa->buffer_size / alsa->period_size) * alsa->period_size),
+ start_threshold);
+
+ /* allow the transfer when at least period_size samples can be processed */
+ CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
+ alsa->period_size), set_avail);
+
+#if GST_CHECK_ALSA_VERSION(1,0,16)
+ /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
+#else
+ /* align all transfers to 1 sample */
+ CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
+#endif
+
+ /* write the parameters to the playback device */
+ CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
+
+ snd_pcm_sw_params_free (params);
+ return 0;
+
+ /* ERRORS */
+no_config:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to determine current swparams for playback: %s",
+ snd_strerror (err)));
+ snd_pcm_sw_params_free (params);
+ return err;
+ }
+start_threshold:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set start threshold mode for playback: %s",
+ snd_strerror (err)));
+ snd_pcm_sw_params_free (params);
+ return err;
+ }
+set_avail:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set avail min for playback: %s", snd_strerror (err)));
+ snd_pcm_sw_params_free (params);
+ return err;
+ }
+#if !GST_CHECK_ALSA_VERSION(1,0,16)
+set_align:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set transfer align for playback: %s", snd_strerror (err)));
+ snd_pcm_sw_params_free (params);
+ return err;
+ }
+#endif
+set_sw_params:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Unable to set sw params for playback: %s", snd_strerror (err)));
+ snd_pcm_sw_params_free (params);
+ return err;
+ }
+}
+
+static gboolean
+alsasink2_parse_spec (_k_GstAlsaSink * alsa, GstRingBufferSpec * spec)
+{
+ /* Initialize our boolean */
+ alsa->iec958 = FALSE;
+
+ switch (spec->type) {
+ case GST_BUFTYPE_LINEAR:
+ GST_DEBUG_OBJECT (alsa,
+ "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
+ spec->width, spec->sign, spec->bigend);
+
+ alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
+ spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
+ break;
+ case GST_BUFTYPE_FLOAT:
+ switch (spec->format) {
+ case GST_FLOAT32_LE:
+ alsa->format = SND_PCM_FORMAT_FLOAT_LE;
+ break;
+ case GST_FLOAT32_BE:
+ alsa->format = SND_PCM_FORMAT_FLOAT_BE;
+ break;
+ case GST_FLOAT64_LE:
+ alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
+ break;
+ case GST_FLOAT64_BE:
+ alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case GST_BUFTYPE_A_LAW:
+ alsa->format = SND_PCM_FORMAT_A_LAW;
+ break;
+ case GST_BUFTYPE_MU_LAW:
+ alsa->format = SND_PCM_FORMAT_MU_LAW;
+ break;
+#if GST_CHECK_VERSION(0, 10, 18)
+ case GST_BUFTYPE_IEC958:
+ alsa->format = SND_PCM_FORMAT_S16_BE;
+ alsa->iec958 = TRUE;
+ break;
+#endif
+ default:
+ goto error;
+
+ }
+ alsa->rate = spec->rate;
+ alsa->channels = spec->channels;
+ alsa->buffer_time = spec->buffer_time;
+ alsa->period_time = spec->latency_time;
+ alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
+
+ return TRUE;
+
+ /* ERRORS */
+error:
+ {
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_alsasink2_open (GstAudioSink * asink)
+{
+ _k_GstAlsaSink *alsa;
+ gint err;
+
+ alsa = GST_ALSA_SINK2 (asink);
+
+ CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
+ SND_PCM_NONBLOCK), open_error);
+ GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
+
+ return TRUE;
+
+ /* ERRORS */
+open_error:
+ {
+ if (err == -EBUSY) {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
+ (_("Could not open audio device for playback. "
+ "Device is being used by another application.")),
+ ("Device '%s' is busy", alsa->device));
+ } else {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
+ (_("Could not open audio device for playback.")),
+ ("Playback open error on device '%s': %s", alsa->device,
+ snd_strerror (err)));
+ }
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_alsasink2_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
+{
+ _k_GstAlsaSink *alsa;
+ gint err;
+
+ alsa = GST_ALSA_SINK2 (asink);
+
+#if GST_CHECK_VERSION(0, 10, 18)
+ if (spec->format == GST_IEC958) {
+ snd_pcm_close (alsa->handle);
+ alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
+ if (G_UNLIKELY (!alsa->handle)) {
+ goto no_iec958;
+ }
+ }
+#endif
+
+ if (!alsasink2_parse_spec (alsa, spec))
+ goto spec_parse;
+
+ CHECK (set_hwparams (alsa), hw_params_failed);
+ CHECK (set_swparams (alsa), sw_params_failed);
+
+ alsa->bytes_per_sample = spec->bytes_per_sample;
+ spec->segsize = alsa->period_size * spec->bytes_per_sample;
+ spec->segtotal = alsa->buffer_size / alsa->period_size;
+
+ {
+ snd_output_t *out_buf = NULL;
+ char *msg = NULL;
+
+ snd_output_buffer_open (&out_buf);
+ snd_pcm_dump_hw_setup (alsa->handle, out_buf);
+ snd_output_buffer_string (out_buf, &msg);
+ GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
+ snd_output_close (out_buf);
+ snd_output_buffer_open (&out_buf);
+ snd_pcm_dump_sw_setup (alsa->handle, out_buf);
+ snd_output_buffer_string (out_buf, &msg);
+ GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
+ snd_output_close (out_buf);
+ }
+
+ return TRUE;
+
+ /* ERRORS */
+#if GST_CHECK_VERSION(0, 10, 18)
+no_iec958:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
+ ("Could not open IEC958 (SPDIF) device for playback"));
+ return FALSE;
+ }
+#endif
+spec_parse:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Error parsing spec"));
+ return FALSE;
+ }
+hw_params_failed:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Setting of hwparams failed: %s", snd_strerror (err)));
+ return FALSE;
+ }
+sw_params_failed:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Setting of swparams failed: %s", snd_strerror (err)));
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_alsasink2_unprepare (GstAudioSink * asink)
+{
+ _k_GstAlsaSink *alsa;
+ gint err;
+
+ alsa = GST_ALSA_SINK2 (asink);
+
+ CHECK (snd_pcm_drop (alsa->handle), drop);
+
+ CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
+
+ return TRUE;
+
+ /* ERRORS */
+drop:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Could not drop samples: %s", snd_strerror (err)));
+ return FALSE;
+ }
+hw_free:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
+ ("Could not free hw params: %s", snd_strerror (err)));
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_alsasink2_close (GstAudioSink * asink)
+{
+ _k_GstAlsaSink *alsa = GST_ALSA_SINK2 (asink);
+ gint err;
+
+ if (alsa->handle) {
+ CHECK (snd_pcm_close (alsa->handle), close_error);
+ alsa->handle = NULL;
+ }
+ gst_caps_replace (&alsa->cached_caps, NULL);
+
+ return TRUE;
+
+ /* ERRORS */
+close_error:
+ {
+ GST_ELEMENT_ERROR (alsa, RESOURCE, CLOSE, (NULL),
+ ("Playback close error: %s", snd_strerror (err)));
+ return FALSE;
+ }
+}
+
+
+/*
+ * Underrun and suspend recovery
+ */
+static gint
+xrun_recovery (_k_GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
+{
+ GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
+
+ if (err == -EPIPE) { /* under-run */
+ err = snd_pcm_prepare (handle);
+ if (err < 0) {
+ GST_WARNING_OBJECT (alsa,
+ "Can't recovery from underrun, prepare failed: %s",
+ snd_strerror (err));
+ }
+ return 0;
+ } else if (err == -ESTRPIPE) {
+ while ((err = snd_pcm_resume (handle)) == -EAGAIN)
+ g_usleep (100); /* wait until the suspend flag is released */
+
+ if (err < 0) {
+ err = snd_pcm_prepare (handle);
+ if (err < 0) {
+ GST_WARNING_OBJECT (alsa,
+ "Can't recovery from suspend, prepare failed: %s",
+ snd_strerror (err));
+ }
+ }
+ return 0;
+ }
+ return err;
+}
+
+static guint
+gst_alsasink2_write (GstAudioSink * asink, gpointer data, guint length)
+{
+ _k_GstAlsaSink *alsa;
+ gint err;
+ gint cptr;
+ gint16 *ptr = data;
+
+ alsa = GST_ALSA_SINK2 (asink);
+
+ if (alsa->iec958 && alsa->need_swap) {
+ guint i;
+
+ GST_DEBUG_OBJECT (asink, "swapping bytes");
+ for (i = 0; i < length / 2; i++) {
+ ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
+ }
+ }
+
+ GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
+
+ cptr = length / alsa->bytes_per_sample;
+
+ GST_ALSA_SINK2_LOCK (asink);
+ while (cptr > 0) {
+ /* start by doing a blocking wait for free space. Set the timeout
+ * to 4 times the period time */
+ err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
+ if (err < 0) {
+ GST_DEBUG_OBJECT (asink, "wait timeout, %d", err);
+ } else {
+ err = snd_pcm_writei (alsa->handle, ptr, cptr);
+ }
+
+ GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
+ if (err < 0) {
+ GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
+ if (err == -EAGAIN) {
+ continue;
+ } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
+ goto write_error;
+ }
+ continue;
+ }
+
+ ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
+ cptr -= err;
+ }
+ GST_ALSA_SINK2_UNLOCK (asink);
+
+ return length - (cptr * alsa->bytes_per_sample);
+
+write_error:
+ {
+ GST_ALSA_SINK2_UNLOCK (asink);
+ return length; /* skip one period */
+ }
+}
+
+static guint
+gst_alsasink2_delay (GstAudioSink * asink)
+{
+ _k_GstAlsaSink *alsa;
+ snd_pcm_sframes_t delay;
+ int res;
+
+ alsa = GST_ALSA_SINK2 (asink);
+
+ res = snd_pcm_delay (alsa->handle, &delay);
+ if (G_UNLIKELY (res < 0)) {
+ /* on errors, report 0 delay */
+ GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
+ delay = 0;
+ }
+ if (G_UNLIKELY (delay < 0)) {
+ /* make sure we never return a negative delay */
+ GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
+ delay = 0;
+ }
+
+ return delay;
+}
+
+static void
+gst_alsasink2_reset (GstAudioSink * asink)
+{
+ _k_GstAlsaSink *alsa;
+ gint err;
+
+ alsa = GST_ALSA_SINK2 (asink);
+
+ GST_ALSA_SINK2_LOCK (asink);
+ GST_DEBUG_OBJECT (alsa, "drop");
+ CHECK (snd_pcm_drop (alsa->handle), drop_error);
+ GST_DEBUG_OBJECT (alsa, "prepare");
+ CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
+ GST_DEBUG_OBJECT (alsa, "reset done");
+ GST_ALSA_SINK2_UNLOCK (asink);
+
+ return;
+
+ /* ERRORS */
+drop_error:
+ {
+ GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
+ snd_strerror (err));
+ GST_ALSA_SINK2_UNLOCK (asink);
+ return;
+ }
+prepare_error:
+ {
+ GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
+ snd_strerror (err));
+ GST_ALSA_SINK2_UNLOCK (asink);
+ return;
+ }
+}
+
+static void
+gst_alsa_error_wrapper (const char *file, int line, const char *function,
+ int err, const char *fmt, ...)
+{
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ int err;
+
+ if (!gst_element_register (plugin, "_k_alsasink", GST_RANK_PRIMARY,
+ GST_TYPE_ALSA_SINK2))
+ return FALSE;
+
+ err = snd_lib_error_set_handler (gst_alsa_error_wrapper);
+ if (err != 0)
+ GST_WARNING ("failed to set alsa error handler");
+
+ return TRUE;
+}
+
+#define PACKAGE ""
+GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "_k_alsa",
+ "ALSA plugin library (hotfixed)",
+ plugin_init, "0.1", "LGPL", "Phonon-GStreamer", "")
+#undef PACKAGE
diff --git a/src/3rdparty/phonon/gstreamer/alsasink2.h b/src/3rdparty/phonon/gstreamer/alsasink2.h
new file mode 100644
index 0000000..bec9933
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/alsasink2.h
@@ -0,0 +1,87 @@
+/* GStreamer
+ * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+ *
+ * gstalsasink2.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef ALSASINK2_H
+#define ALSASINK2_H
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+#include <alsa/asoundlib.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_ALSA_SINK2 (gst_alsasink2_get_type())
+#define GST_ALSA_SINK2(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_SINK2,_k_GstAlsaSink))
+#define GST_ALSA_SINK2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SINK2,_k_GstAlsaSinkClass))
+#define GST_IS_ALSA_SINK2(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SINK2))
+#define GST_IS_ALSA_SINK2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SINK2))
+#define GST_ALSA_SINK2_CAST(obj) ((_k_GstAlsaSink *) (obj))
+
+typedef struct _k_GstAlsaSink _k_GstAlsaSink;
+typedef struct _k_GstAlsaSinkClass _k_GstAlsaSinkClass;
+
+#define GST_ALSA_SINK2_GET_LOCK(obj) (GST_ALSA_SINK2_CAST (obj)->alsa_lock)
+#define GST_ALSA_SINK2_LOCK(obj) (g_mutex_lock (GST_ALSA_SINK2_GET_LOCK (obj)))
+#define GST_ALSA_SINK2_UNLOCK(obj) (g_mutex_unlock (GST_ALSA_SINK2_GET_LOCK (obj)))
+
+/**
+ * _k_GstAlsaSink:
+ *
+ * Opaque data structure
+ */
+struct _k_GstAlsaSink {
+ GstAudioSink sink;
+
+ gchar *device;
+
+ snd_pcm_t *handle;
+ snd_pcm_hw_params_t *hwparams;
+ snd_pcm_sw_params_t *swparams;
+
+ snd_pcm_access_t access;
+ snd_pcm_format_t format;
+ guint rate;
+ guint channels;
+ gint bytes_per_sample;
+ gboolean iec958;
+ gboolean need_swap;
+
+ guint buffer_time;
+ guint period_time;
+ snd_pcm_uframes_t buffer_size;
+ snd_pcm_uframes_t period_size;
+
+ GstCaps *cached_caps;
+
+ GMutex *alsa_lock;
+};
+
+struct _k_GstAlsaSinkClass {
+ GstAudioSinkClass parent_class;
+};
+
+GType gst_alsasink2_get_type(void);
+
+G_END_DECLS
+
+#endif /* ALSASINK2_H */
diff --git a/src/3rdparty/phonon/gstreamer/artssink.cpp b/src/3rdparty/phonon/gstreamer/artssink.cpp
new file mode 100644
index 0000000..441607d
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/artssink.cpp
@@ -0,0 +1,278 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*****************************************
+ *
+ * This is an aRts plugin for GStreamer
+ *
+ ****************************************/
+
+#include <gst/gst.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/gstaudiosink.h>
+#include "artssink.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+static GstStaticPadTemplate sinktemplate =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (
+ "audio/x-raw-int, "
+ "width = (int) { 8, 16 }, "
+ "depth = (int) { 8, 16 }, "
+ "endianness = (int) BYTE_ORDER, "
+ "channels = (int) { 1, 2 }, "
+ "rate = (int) [ 8000, 96000 ]"
+ )
+);
+
+typedef int (*Ptr_arts_init)();
+typedef arts_stream_t (*Ptr_arts_play_stream)(int, int, int, const char*);
+typedef int (*Ptr_arts_close_stream)(arts_stream_t);
+typedef int (*Ptr_arts_stream_get)(arts_stream_t, arts_parameter_t_enum);
+typedef int (*Ptr_arts_stream_set)(arts_stream_t, arts_parameter_t_enum, int value);
+typedef int (*Ptr_arts_write)(arts_stream_t, const void *, int);
+typedef int (*Ptr_arts_suspended)();
+typedef void (*Ptr_arts_free)();
+
+static Ptr_arts_init p_arts_init = 0;
+static Ptr_arts_play_stream p_arts_play_stream = 0;
+static Ptr_arts_close_stream p_arts_close_stream = 0;
+static Ptr_arts_stream_get p_arts_stream_get= 0;
+static Ptr_arts_stream_set p_arts_stream_set= 0;
+static Ptr_arts_write p_arts_write = 0;
+static Ptr_arts_suspended p_arts_suspended = 0;
+static Ptr_arts_free p_arts_free = 0;
+
+static void arts_sink_dispose (GObject * object);
+static void arts_sink_reset (GstAudioSink * asink);
+static void arts_sink_finalize (GObject * object);
+static GstCaps *arts_sink_get_caps (GstBaseSink * bsink);
+static gboolean arts_sink_open (GstAudioSink * asink);
+static gboolean arts_sink_close (GstAudioSink * asink);
+static gboolean arts_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec);
+static gboolean arts_sink_unprepare (GstAudioSink * asink);
+static guint arts_sink_write (GstAudioSink * asink, gpointer data, guint length);
+static guint arts_sink_delay (GstAudioSink * asink);
+
+static gboolean connected = false;
+static gboolean init = false;
+static int sinkCount;
+
+GST_BOILERPLATE (ArtsSink, arts_sink, GstAudioSink, GST_TYPE_AUDIO_SINK)
+
+// ArtsSink args
+enum
+{
+ ARG_0,
+ ARG_ARTSSINK
+};
+
+/* open the device with given specs */
+gboolean arts_sink_open(GstAudioSink *sink)
+{
+ Q_UNUSED(sink);
+
+ // We already have an open connection to this device
+ if (!init) {
+ GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), ("Could not connect to aRts", NULL));
+ return false;
+ } else if (connected) {
+ GST_ELEMENT_ERROR (sink, RESOURCE, BUSY, (NULL), ("Device is busy", NULL));
+ return false;
+ }
+
+ // Check if all symbols were resolved
+ if (!(p_arts_init && p_arts_play_stream && p_arts_close_stream
+ && p_arts_stream_get && p_arts_stream_set && p_arts_write && p_arts_free))
+ return FALSE;
+
+ // Check if arts_init succeeded
+ if (!init)
+ return false;
+
+ return true;
+}
+
+/* prepare resources and state to operate with the given specs */
+static gboolean arts_sink_prepare(GstAudioSink *sink, GstRingBufferSpec *spec)
+{
+ ArtsSink *asink = (ArtsSink*)sink;
+
+ if (!init)
+ return false;
+
+ asink->samplerate = spec->rate;
+ asink->samplebits = spec->depth;
+ asink->channels = spec->channels;
+ asink->bytes_per_sample = spec->bytes_per_sample;
+
+ static int id = 0;
+ asink->stream = p_arts_play_stream(spec->rate, spec->depth, spec->channels,
+ QString("gstreamer-%0").arg(id++).toLatin1().constData());
+ if (asink->stream)
+ connected = true;
+
+ return connected;
+}
+
+/* undo anything that was done in prepare() */
+static gboolean arts_sink_unprepare(GstAudioSink *sink)
+{
+ Q_UNUSED(sink);
+ ArtsSink *asink = (ArtsSink*)sink;
+ if (init && connected) {
+ p_arts_close_stream(asink->stream);
+ connected = false;
+ }
+ return true;
+}
+
+/* close the device */
+static gboolean arts_sink_close(GstAudioSink *sink)
+{
+ Q_UNUSED(sink);
+ return true;
+}
+
+/* write samples to the device */
+static guint arts_sink_write(GstAudioSink *sink, gpointer data, guint length)
+{
+ ArtsSink *asink = (ArtsSink*)sink;
+
+ if (!init)
+ return 0;
+
+ int errorcode = p_arts_write(asink->stream, (char*)data, length);
+
+ if (errorcode < 0)
+ GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), ("Could not write to device.", NULL));
+
+ return errorcode > 0 ? errorcode : 0;
+}
+
+/* get number of samples queued in the device */
+static guint arts_sink_delay(GstAudioSink *sink)
+{
+ ArtsSink *asink = (ArtsSink*)sink;
+ if (!init)
+ return 0;
+
+ // We get results in millisecons so we have to caculate the approximate size in samples
+ guint delay = p_arts_stream_get(asink->stream, ARTS_P_SERVER_LATENCY) * (asink->samplerate / 1000);
+ return delay;
+}
+
+/* reset the audio device, unblock from a write */
+static void arts_sink_reset(GstAudioSink *sink)
+{
+ // ### We are currently unable to gracefully recover
+ // after artsd has been restarted or killed.
+ Q_UNUSED(sink);
+}
+
+// Register element details
+static void arts_sink_base_init (gpointer g_class) {
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ static gchar longname[] = "Experimental aRts sink",
+ klass[] = "Sink/Audio",
+ description[] = "aRts Audio Output Device",
+ author[] = "Nokia Corporation and/or its subsidiary(-ies) <qt-info@nokia.com>";
+ GstElementDetails details = GST_ELEMENT_DETAILS (longname,
+ klass,
+ description,
+ author);
+ gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sinktemplate));
+ gst_element_class_set_details (gstelement_class, &details);
+}
+
+static void arts_sink_class_init (ArtsSinkClass * klass)
+{
+ parent_class = (GstAudioSinkClass*)g_type_class_peek_parent(klass);
+
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (arts_sink_finalize);
+ gobject_class->dispose = GST_DEBUG_FUNCPTR (arts_sink_dispose);
+
+ GstBaseSinkClass *gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (arts_sink_get_caps);
+
+ GstAudioSinkClass *gstaudiosink_class = (GstAudioSinkClass*)klass;
+ gstaudiosink_class->open = GST_DEBUG_FUNCPTR(arts_sink_open);
+ gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR(arts_sink_prepare);
+ gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR(arts_sink_unprepare);
+ gstaudiosink_class->close = GST_DEBUG_FUNCPTR(arts_sink_close);
+ gstaudiosink_class->write = GST_DEBUG_FUNCPTR(arts_sink_write);
+ gstaudiosink_class->delay = GST_DEBUG_FUNCPTR(arts_sink_delay);
+ gstaudiosink_class->reset = GST_DEBUG_FUNCPTR(arts_sink_reset);
+}
+
+static void arts_sink_init (ArtsSink * src, ArtsSinkClass * g_class)
+{
+ Q_UNUSED(g_class);
+ GST_DEBUG_OBJECT (src, "initializing artssink");
+ src->stream = 0;
+#ifndef QT_NO_LIBRARY
+ p_arts_init = (Ptr_arts_init)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_init");
+ p_arts_play_stream = (Ptr_arts_play_stream)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_play_stream");
+ p_arts_close_stream = (Ptr_arts_close_stream)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_close_stream");
+ p_arts_stream_get = (Ptr_arts_stream_get)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_stream_get");
+ p_arts_stream_set = (Ptr_arts_stream_set)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_stream_set");
+ p_arts_write = (Ptr_arts_write)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_write");
+ p_arts_suspended = (Ptr_arts_suspended)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_suspended");
+ p_arts_free = (Ptr_arts_free)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_free");
+
+ if (!sinkCount) {
+ int errorcode = p_arts_init();
+ if (!errorcode) {
+ init = TRUE;
+ }
+ }
+ sinkCount ++;
+#endif //QT_NO_LIBRARY
+}
+
+static void arts_sink_dispose (GObject * object)
+{
+ Q_UNUSED(object);
+ if (--sinkCount == 0) {
+ p_arts_free();
+ }
+}
+
+static void arts_sink_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static GstCaps *arts_sink_get_caps (GstBaseSink * bsink)
+{
+ Q_UNUSED(bsink);
+ return NULL;
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/artssink.h b/src/3rdparty/phonon/gstreamer/artssink.h
new file mode 100644
index 0000000..169e73e
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/artssink.h
@@ -0,0 +1,91 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __ARTS_SINK_H__
+#define __ARTS_SINK_H__
+
+#include <QtCore>
+#include <sys/types.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+G_BEGIN_DECLS
+
+extern "C" {
+
+#define GST_TYPE_ARTS_SINK (arts_sink_get_type())
+#define GST_ARTS_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ARTS_SINK,ArtsSink))
+#define GST_ARTS_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ARTS_SINK,ArtsSinkClass))
+#define GST_IS_ARTS_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ARTS_SINK))
+#define GST_IS_ARTS_SINK_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ARTS_SINK))
+
+typedef struct _ArtsSink ArtsSink;
+typedef struct _ArtsSinkClass ArtsSinkClass;
+
+enum arts_parameter_t_enum {
+ ARTS_P_BUFFER_SIZE = 1,
+ ARTS_P_BUFFER_TIME = 2,
+ ARTS_P_BUFFER_SPACE = 3,
+ ARTS_P_SERVER_LATENCY = 4,
+ ARTS_P_TOTAL_LATENCY = 5,
+ ARTS_P_BLOCKING = 6,
+ ARTS_P_PACKET_SIZE = 7,
+ ARTS_P_PACKET_COUNT = 8,
+ ARTS_P_PACKET_SETTINGS = 9
+};
+
+typedef void *arts_stream_t;
+
+struct _ArtsSink {
+ GstAudioSink sink;
+ arts_stream_t stream;
+ int samplerate;
+ int samplebits;
+ int channels;
+ int bytes_per_sample;
+};
+
+struct GConfClient;
+struct GError;
+typedef void (*Ptr_g_type_init)();
+typedef GConfClient* (*Ptr_gconf_client_get_default)();
+typedef char* (*Ptr_gconf_client_get_string)(GConfClient*, const char*, GError **);
+typedef void (*Ptr_g_object_unref)(void *);
+typedef void (*Ptr_g_error_free)(GError *);
+typedef void (*Ptr_g_free)(void*);
+
+struct _ArtsSinkClass {
+ GstAudioSinkClass parent_class;
+};
+
+GType arts_sink_get_type (void);
+}
+G_END_DECLS
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // __ARTS_SINK_H__
diff --git a/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp b/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp
new file mode 100644
index 0000000..802cb18
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp
@@ -0,0 +1,149 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2009 Martin Sandsmark <sandsmark@samfundet.no>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "audiodataoutput.h"
+#include "gsthelper.h"
+#include "medianode.h"
+#include "mediaobject.h"
+#include <QtCore/QVector>
+#include <QtCore/QMap>
+#include <phonon/audiooutput.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+AudioDataOutput::AudioDataOutput(Backend *backend, QObject *parent)
+ : QObject(parent),
+ MediaNode(backend, AudioSink | AudioSource)
+{
+ static int count = 0;
+ m_name = "AudioDataOutput" + QString::number(count++);
+
+ m_queue = gst_element_factory_make ("identity", NULL);
+ gst_object_ref(m_queue);
+ m_isValid = true;
+}
+
+AudioDataOutput::~AudioDataOutput()
+{
+ gst_element_set_state(m_queue, GST_STATE_NULL);
+ gst_object_unref(m_queue);
+}
+
+int AudioDataOutput::dataSize() const
+{
+ return m_dataSize;
+}
+
+int AudioDataOutput::sampleRate() const
+{
+ return 44100;
+}
+
+void AudioDataOutput::setDataSize(int size)
+{
+ m_dataSize = size;
+}
+
+typedef QMap<Phonon::AudioDataOutput::Channel, QVector<float> > FloatMap;
+typedef QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > IntMap;
+
+inline void AudioDataOutput::convertAndEmit(const QVector<qint16> &leftBuffer, const QVector<qint16> &rightBuffer)
+{
+ //TODO: Floats
+ IntMap map;
+ map.insert(Phonon::AudioDataOutput::LeftChannel, leftBuffer);
+ map.insert(Phonon::AudioDataOutput::RightChannel, rightBuffer);
+ emit dataReady(map);
+}
+
+void AudioDataOutput::processBuffer(GstPad*, GstBuffer* buffer, gpointer gThat)
+{
+ // TODO emit endOfMedia
+ AudioDataOutput *that = reinterpret_cast<AudioDataOutput*>(gThat);
+
+ // determine the number of channels
+ GstStructure* structure = gst_caps_get_structure (GST_BUFFER_CAPS(buffer), 0);
+ gst_structure_get_int (structure, "channels", &that->m_channels);
+
+ if (that->m_channels > 2 || that->m_channels < 0) {
+ qWarning() << Q_FUNC_INFO << ": Number of channels not supported: " << that->m_channels;
+ return;
+ }
+
+ gint16 *data = reinterpret_cast<gint16*>(GST_BUFFER_DATA(buffer));
+ guint size = GST_BUFFER_SIZE(buffer) / sizeof(gint16);
+
+ that->m_pendingData.reserve(that->m_pendingData.size() + size);
+
+ for (uint i=0; i<size; i++) {
+ // 8 bit? interleaved? yay for lacking documentation!
+ that->m_pendingData.append(data[i]);
+ }
+
+ while (that->m_pendingData.size() > that->m_dataSize * that->m_channels) {
+ if (that->m_channels == 1) {
+ QVector<qint16> intBuffer(that->m_dataSize);
+ memcpy(intBuffer.data(), that->m_pendingData.constData(), that->m_dataSize * sizeof(qint16));
+
+ that->convertAndEmit(intBuffer, intBuffer);
+ int newSize = that->m_pendingData.size() - that->m_dataSize;
+ memmove(that->m_pendingData.data(), that->m_pendingData.constData() + that->m_dataSize, newSize * sizeof(qint16));
+ that->m_pendingData.resize(newSize);
+ } else {
+ QVector<qint16> left(that->m_dataSize), right(that->m_dataSize);
+ for (int i=0; i<that->m_dataSize; i++) {
+ left[i] = that->m_pendingData[i*2];
+ right[i] = that->m_pendingData[i*2+1];
+ }
+ that->m_pendingData.resize(that->m_pendingData.size() - that->m_dataSize*2);
+ that->convertAndEmit(left, right);
+ }
+ }
+}
+
+void AudioDataOutput::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ if (event->type() == MediaNodeEvent::MediaObjectConnected && root()) {
+ g_object_set(G_OBJECT(audioElement()), "sync", true, (const char*)NULL);
+ GstPad *audiopad = gst_element_get_pad (audioElement(), "src");
+ gst_pad_add_buffer_probe (audiopad, G_CALLBACK(processBuffer), this);
+ gst_object_unref (audiopad);
+ return;
+ }
+
+ MediaNode::mediaNodeEvent(event);
+}
+
+}} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#include "moc_audiodataoutput.cpp"
+// vim: sw=4 ts=4
+
diff --git a/src/3rdparty/phonon/gstreamer/audiodataoutput.h b/src/3rdparty/phonon/gstreamer/audiodataoutput.h
new file mode 100644
index 0000000..cd5ef49
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audiodataoutput.h
@@ -0,0 +1,90 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2009 Martin Sandsmark <sandsmark@samfundet.no>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_AUDIODATAOUTPUT_H
+#define Phonon_GSTREAMER_AUDIODATAOUTPUT_H
+
+#include "abstractaudiooutput.h"
+#include "backend.h"
+#include "medianode.h"
+#include <phonon/audiodataoutput.h>
+#include <phonon/audiodataoutputinterface.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+ /**
+ * \author Martin Sandsmark <sandsmark@samfundet.no>
+ */
+ class AudioDataOutput : public QObject,
+ public AudioDataOutputInterface,
+ public MediaNode
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioDataOutputInterface Phonon::Gstreamer::MediaNode)
+
+ public:
+ AudioDataOutput(Backend *, QObject *);
+ ~AudioDataOutput();
+
+ public Q_SLOTS:
+ int dataSize() const;
+ int sampleRate() const;
+ void setDataSize(int size);
+
+ public:
+ /// callback function for handling new audio data
+ static void processBuffer(GstPad*, GstBuffer*, gpointer);
+
+ Phonon::AudioDataOutput* frontendObject() const { return m_frontend; }
+ void setFrontendObject(Phonon::AudioDataOutput *frontend) { m_frontend = frontend; }
+
+ GstElement *audioElement() { return m_queue; }
+
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+
+ signals:
+ void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &data);
+ void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<float> > &data);
+ void endOfMedia(int remainingSamples);
+
+ private:
+ void convertAndEmit(const QVector<qint16>&, const QVector<qint16>&);
+
+ GstElement *m_queue;
+ int m_dataSize;
+ QVector<qint16> m_pendingData;
+ Phonon::AudioDataOutput *m_frontend;
+ int m_channels;
+ };
+}} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_FAKE_AUDIODATAOUTPUT_H
diff --git a/src/3rdparty/phonon/gstreamer/audioeffect.cpp b/src/3rdparty/phonon/gstreamer/audioeffect.cpp
new file mode 100644
index 0000000..d3d7a35
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audioeffect.cpp
@@ -0,0 +1,79 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "backend.h"
+#include "medianode.h"
+#include "effectmanager.h"
+#include "audioeffect.h"
+#include "gsthelper.h"
+
+#include <gst/gst.h>
+#ifndef QT_NO_PHONON_EFFECT
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+AudioEffect::AudioEffect(Backend *backend, int effectId, QObject *parent)
+ : Effect(backend, parent, AudioSource | AudioSink)
+{
+ static int count = 0;
+ m_name = "AudioEffect" + QString::number(count++);
+ QList<EffectInfo*> audioEffects = backend->effectManager()->audioEffects();
+ if (effectId >= 0 && effectId < audioEffects.size()) {
+ m_effectName = audioEffects[effectId]->name();
+ init();
+ } else {
+ Q_ASSERT(0); // Effect ID out of range
+ }
+}
+
+GstElement* AudioEffect::createEffectBin()
+{
+ GstElement *audioBin = gst_bin_new(NULL);
+
+ // We need a queue to handle tee-connections from parent node
+ GstElement *queue= gst_element_factory_make ("queue", NULL);
+ gst_bin_add(GST_BIN(audioBin), queue);
+
+ GstElement *mconv= gst_element_factory_make ("audioconvert", NULL);
+ gst_bin_add(GST_BIN(audioBin), mconv);
+
+ m_effectElement = gst_element_factory_make (qPrintable(m_effectName), NULL);
+ gst_bin_add(GST_BIN(audioBin), m_effectElement);
+
+ //Link src pad
+ GstPad *srcPad= gst_element_get_pad (m_effectElement, "src");
+ gst_element_add_pad (audioBin, gst_ghost_pad_new ("src", srcPad));
+ gst_object_unref (srcPad);
+
+ //Link sink pad
+ gst_element_link_many(queue, mconv, m_effectElement, (const char*)NULL);
+ GstPad *sinkpad = gst_element_get_pad (queue, "sink");
+ gst_element_add_pad (audioBin, gst_ghost_pad_new ("sink", sinkpad));
+ gst_object_unref (sinkpad);
+ return audioBin;
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_EFFECT
+#include "moc_audioeffect.cpp"
diff --git a/src/3rdparty/phonon/gstreamer/audioeffect.h b/src/3rdparty/phonon/gstreamer/audioeffect.h
new file mode 100644
index 0000000..f49f8d2
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audioeffect.h
@@ -0,0 +1,55 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_AUDIOEFFECT_H
+#define Phonon_GSTREAMER_AUDIOEFFECT_H
+
+#include "common.h"
+#include "effect.h"
+#include "medianode.h"
+
+#include <phonon/effectparameter.h>
+#include <phonon/effectinterface.h>
+
+#include <QtCore/QObject>
+
+#include <gst/gst.h>
+
+#ifndef QT_NO_PHONON_EFFECT
+QT_BEGIN_NAMESPACE
+namespace Phonon
+{
+namespace Gstreamer
+{
+ class AudioOutput;
+ class EffectInfo;
+
+ class AudioEffect : public Effect
+ {
+ Q_OBJECT
+ public:
+ AudioEffect (Backend *backend, int effectId, QObject *parent);
+ protected:
+ GstElement* createEffectBin();
+ GstElement* audioElement() { return m_effectBin; }
+ QString m_effectName;
+ };
+}} //namespace Phonon::Gstreamer
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_EFFECT
+
+#endif // Phonon_GSTREAMER_AUDIOEFFECT_H
diff --git a/src/3rdparty/phonon/gstreamer/audiooutput.cpp b/src/3rdparty/phonon/gstreamer/audiooutput.cpp
new file mode 100644
index 0000000..f3137b2
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audiooutput.cpp
@@ -0,0 +1,256 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "audiooutput.h"
+#include "backend.h"
+#include "mediaobject.h"
+#include "gsthelper.h"
+#include <phonon/audiooutput.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+AudioOutput::AudioOutput(Backend *backend, QObject *parent)
+ : QObject(parent)
+ , MediaNode(backend, AudioSink)
+ , m_volumeLevel(1.0)
+ , m_device(0) // ### get from backend
+ , m_volumeElement(0)
+ , m_audioBin(0)
+ , m_audioSink(0)
+ , m_conv(0)
+{
+ static int count = 0;
+ m_name = "AudioOutput" + QString::number(count++);
+ if (m_backend->isValid()) {
+ m_audioBin = gst_bin_new (NULL);
+ gst_object_ref (GST_OBJECT (m_audioBin));
+ gst_object_sink (GST_OBJECT (m_audioBin));
+
+ m_conv = gst_element_factory_make ("audioconvert", NULL);
+
+ // Get category from parent
+ Phonon::Category category = Phonon::NoCategory;
+ if (Phonon::AudioOutput *audioOutput = qobject_cast<Phonon::AudioOutput *>(parent))
+ category = audioOutput->category();
+
+ m_audioSink = m_backend->deviceManager()->createAudioSink(category);
+ m_volumeElement = gst_element_factory_make ("volume", NULL);
+ GstElement *queue = gst_element_factory_make ("queue", NULL);
+ GstElement *audioresample = gst_element_factory_make ("audioresample", NULL);
+
+ if (queue && m_audioBin && m_conv && audioresample && m_audioSink && m_volumeElement) {
+ gst_bin_add_many (GST_BIN (m_audioBin), queue, m_conv, audioresample, m_volumeElement, m_audioSink, (const char*)NULL);
+
+ if (gst_element_link_many (queue, m_conv, audioresample, m_volumeElement, m_audioSink, (const char*)NULL)) {
+ // Add ghost sink for audiobin
+ GstPad *audiopad = gst_element_get_pad (queue, "sink");
+ gst_element_add_pad (m_audioBin, gst_ghost_pad_new ("sink", audiopad));
+ gst_object_unref (audiopad);
+ m_isValid = true; // Initialization ok, accept input
+ }
+ }
+ }
+}
+
+void AudioOutput::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ if (!m_audioBin)
+ return;
+
+ switch (event->type()) {
+
+ default:
+ break;
+ }
+}
+
+
+AudioOutput::~AudioOutput()
+{
+ if (m_audioBin) {
+ gst_element_set_state (m_audioBin, GST_STATE_NULL);
+ gst_object_unref (m_audioBin);
+ }
+}
+
+qreal AudioOutput::volume() const
+{
+ return m_volumeLevel;
+}
+
+int AudioOutput::outputDevice() const
+{
+ return m_device;
+}
+
+void AudioOutput::setVolume(qreal newVolume)
+{
+ if (newVolume > 2.0 )
+ newVolume = 2.0;
+ else if (newVolume < 0.0)
+ newVolume = 0.0;
+
+ if (newVolume == m_volumeLevel)
+ return;
+
+ m_volumeLevel = newVolume;
+
+ if (m_volumeElement) {
+ g_object_set(G_OBJECT(m_volumeElement), "volume", newVolume, (const char*)NULL);
+ }
+
+ emit volumeChanged(newVolume);
+}
+
+bool AudioOutput::setOutputDevice(int newDevice)
+{
+ m_backend->logMessage(Q_FUNC_INFO + QString::number(newDevice), Backend::Info, this);
+
+ if (newDevice == m_device)
+ return true;
+
+ if (root()) {
+ root()->saveState();
+ if (gst_element_set_state(root()->pipeline(), GST_STATE_READY) == GST_STATE_CHANGE_FAILURE)
+ return false;
+ }
+
+ bool success = false;
+ if (m_audioSink && newDevice >= 0) {
+ // Save previous state
+ GstState oldState = GST_STATE(m_audioSink);
+ const QByteArray oldDeviceValue = GstHelper::property(m_audioSink, "device");
+ const QByteArray deviceId = m_backend->deviceManager()->gstId(newDevice);
+ m_device = newDevice;
+
+ // We test if the device can be opened by checking if it can go from NULL to READY state
+ gst_element_set_state(m_audioSink, GST_STATE_NULL);
+ success = GstHelper::setProperty(m_audioSink, "device", deviceId);
+ if (success) {
+ success = (gst_element_set_state(m_audioSink, oldState) == GST_STATE_CHANGE_SUCCESS);
+ }
+ if (!success) { // Revert state
+ m_backend->logMessage(Q_FUNC_INFO +
+ QLatin1String(" Failed to change device ") +
+ deviceId, Backend::Info, this);
+
+ GstHelper::setProperty(m_audioSink, "device", oldDeviceValue);
+ gst_element_set_state(m_audioSink, oldState);
+ } else {
+ m_backend->logMessage(Q_FUNC_INFO +
+ QLatin1String(" Successfully changed device ") +
+ deviceId, Backend::Info, this);
+ }
+
+ // Note the stopped state should not really be necessary, but seems to be required to
+ // properly reset after changing the audio state
+ if (root()) {
+ QMetaObject::invokeMethod(root(), "setState", Qt::QueuedConnection, Q_ARG(State, StoppedState));
+ root()->resumeState();
+ }
+ }
+ return success;
+}
+
+#if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 2, 0))
+bool AudioOutput::setOutputDevice(const AudioOutputDevice &newDevice)
+{
+ m_backend->logMessage(Q_FUNC_INFO, Backend::Info, this);
+ if (!m_audioSink || !newDevice.isValid()) {
+ return false;
+ }
+ const QVariant driver = newDevice.property("driver");
+ if (!driver.isValid()) {
+ return setOutputDevice(newDevice.index());
+ }
+ if (newDevice.index() == m_device) {
+ return true;
+ }
+
+ if (root()) {
+ root()->saveState();
+ if (gst_element_set_state(root()->pipeline(), GST_STATE_READY) == GST_STATE_CHANGE_FAILURE)
+ return false;
+ }
+
+ // Save previous state
+ const GstState oldState = GST_STATE(m_audioSink);
+ const QByteArray oldDeviceValue = GstHelper::property(m_audioSink, "device");
+
+ const QByteArray sinkName = GstHelper::property(m_audioSink, "name");
+ if (sinkName == "alsasink" || sinkName == "alsasink2") {
+ if (driver.toByteArray() != "alsa") {
+ return false;
+ }
+ }
+
+ const QVariant deviceIdsProperty = newDevice.property("deviceIds");
+ QStringList deviceIds;
+ if (deviceIdsProperty.type() == QVariant::StringList) {
+ deviceIds = deviceIdsProperty.toStringList();
+ } else if (deviceIdsProperty.type() == QVariant::String) {
+ deviceIds += deviceIdsProperty.toString();
+ }
+
+ // We test if the device can be opened by checking if it can go from NULL to READY state
+ foreach (const QString &deviceId, deviceIds) {
+ gst_element_set_state(m_audioSink, GST_STATE_NULL);
+ if (GstHelper::setProperty(m_audioSink, "device", deviceId.toUtf8())) {
+ m_backend->logMessage(Q_FUNC_INFO + QLatin1String("setProperty(device,") +
+ deviceId + QLatin1String(") succeeded"), Backend::Info, this);
+ if (gst_element_set_state(m_audioSink, oldState) == GST_STATE_CHANGE_SUCCESS) {
+ m_backend->logMessage(Q_FUNC_INFO + QLatin1String("go to old state on device") +
+ deviceId + QLatin1String(" succeeded"), Backend::Info, this);
+ m_device = newDevice.index();
+ if (root()) {
+ QMetaObject::invokeMethod(root(), "setState", Qt::QueuedConnection, Q_ARG(State, StoppedState));
+ root()->resumeState();
+ }
+ return true;
+ } else {
+ m_backend->logMessage(Q_FUNC_INFO + QLatin1String("go to old state on device") +
+ deviceId + QLatin1String(" failed"), Backend::Info, this);
+ }
+ } else {
+ m_backend->logMessage(Q_FUNC_INFO + QLatin1String("setProperty(device,") +
+ deviceId + QLatin1String(") failed"), Backend::Info, this);
+ }
+ }
+ // Revert state
+ GstHelper::setProperty(m_audioSink, "device", oldDeviceValue);
+ gst_element_set_state(m_audioSink, oldState);
+
+ if (root()) {
+ QMetaObject::invokeMethod(root(), "setState", Qt::QueuedConnection, Q_ARG(State, StoppedState));
+ root()->resumeState();
+ }
+
+ return false;
+}
+#endif
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#include "moc_audiooutput.cpp"
diff --git a/src/3rdparty/phonon/gstreamer/audiooutput.h b/src/3rdparty/phonon/gstreamer/audiooutput.h
new file mode 100644
index 0000000..846fa7b
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audiooutput.h
@@ -0,0 +1,82 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_AUDIOOUTPUT_H
+#define Phonon_GSTREAMER_AUDIOOUTPUT_H
+
+#include "common.h"
+#include "medianode.h"
+
+#include <phonon/audiooutputinterface.h>
+#include <phonon/phononnamespace.h>
+
+#include <QtCore/QFile>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+class AudioOutput : public QObject, public AudioOutputInterface, public MediaNode
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioOutputInterface Phonon::Gstreamer::MediaNode)
+public:
+ AudioOutput(Backend *backend, QObject *parent);
+ ~AudioOutput();
+
+ qreal volume() const;
+ int outputDevice() const;
+ void setVolume(qreal newVolume);
+ bool setOutputDevice(int newDevice);
+#if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 2, 0))
+ bool setOutputDevice(const AudioOutputDevice &newDevice);
+#endif
+
+public:
+ GstElement *audioElement()
+ {
+ Q_ASSERT(m_audioBin);
+ return m_audioBin;
+ }
+
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+Q_SIGNALS:
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+
+private:
+
+ qreal m_volumeLevel;
+ int m_device;
+
+ GstElement *m_volumeElement;
+ GstElement *m_audioBin;
+ GstElement *m_audioSink;
+ GstElement *m_conv;
+};
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_AUDIOOUTPUT_H
diff --git a/src/3rdparty/phonon/gstreamer/backend.cpp b/src/3rdparty/phonon/gstreamer/backend.cpp
new file mode 100644
index 0000000..729a1d3
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/backend.cpp
@@ -0,0 +1,491 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "backend.h"
+#include "audiooutput.h"
+#include "audiodataoutput.h"
+#include "audioeffect.h"
+#include "mediaobject.h"
+#include "videowidget.h"
+#include "devicemanager.h"
+#include "effectmanager.h"
+#include "message.h"
+#include "volumefadereffect.h"
+#include <gst/interfaces/propertyprobe.h>
+#include <phonon/pulsesupport.h>
+
+#include <QtCore/QSet>
+#include <QtCore/QVariant>
+#include <QtCore/QtPlugin>
+
+QT_BEGIN_NAMESPACE
+
+Q_EXPORT_PLUGIN2(phonon_gstreamer, Phonon::Gstreamer::Backend)
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class MediaNode;
+
+Backend::Backend(QObject *parent, const QVariantList &)
+ : QObject(parent)
+ , m_deviceManager(0)
+ , m_effectManager(0)
+ , m_debugLevel(Warning)
+ , m_isValid(false)
+{
+ // Initialise PulseAudio support
+ PulseSupport *pulse = PulseSupport::getInstance();
+ pulse->enable();
+ connect(pulse, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), SIGNAL(objectDescriptionChanged(ObjectDescriptionType)));
+
+ // In order to support reloading, we only set the app name once...
+ static bool first = true;
+ if (first) {
+ first = false;
+ g_set_application_name(qApp->applicationName().toUtf8());
+ }
+ GError *err = 0;
+ bool wasInit = gst_init_check(0, 0, &err); //init gstreamer: must be called before any gst-related functions
+ if (err)
+ g_error_free(err);
+
+ qRegisterMetaType<Message>("Message");
+#ifndef QT_NO_PROPERTIES
+ setProperty("identifier", QLatin1String("phonon_gstreamer"));
+ setProperty("backendName", QLatin1String("Gstreamer"));
+ setProperty("backendComment", QLatin1String("Gstreamer plugin for Phonon"));
+ setProperty("backendVersion", QLatin1String("0.2"));
+ setProperty("backendWebsite", QLatin1String("http://qt.nokia.com/"));
+#endif //QT_NO_PROPERTIES
+
+ //check if we should enable debug output
+ QString debugLevelString = qgetenv("PHONON_GST_DEBUG");
+ int debugLevel = debugLevelString.toInt();
+ if (debugLevel > 3) //3 is maximum
+ debugLevel = 3;
+ m_debugLevel = (DebugLevel)debugLevel;
+
+ if (wasInit) {
+ m_isValid = checkDependencies();
+ gchar *versionString = gst_version_string();
+ logMessage(QString("Using %0").arg(versionString));
+ g_free(versionString);
+ }
+ if (!m_isValid)
+ qWarning("Phonon::GStreamer::Backend: Failed to initialize GStreamer");
+
+ m_deviceManager = new DeviceManager(this);
+ m_effectManager = new EffectManager(this);
+}
+
+Backend::~Backend()
+{
+ delete m_effectManager;
+ delete m_deviceManager;
+ PulseSupport::shutdown();
+}
+
+gboolean Backend::busCall(GstBus *bus, GstMessage *msg, gpointer data)
+{
+ Q_UNUSED(bus);
+ Q_ASSERT(msg);
+
+ MediaObject *mediaObject = static_cast<MediaObject*>(data);
+ Q_ASSERT(mediaObject);
+
+ Message message(msg, mediaObject);
+ QMetaObject::invokeMethod(mediaObject->backend(), "handleBusMessage", Qt::QueuedConnection, Q_ARG(Message, message));
+
+ return true;
+}
+
+/***
+ * !reimp
+ */
+QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+{
+ // Return nothing if dependencies are not met
+
+ switch (c) {
+ case MediaObjectClass:
+ return new MediaObject(this, parent);
+
+ case AudioOutputClass:
+ return new AudioOutput(this, parent);
+
+#ifndef QT_NO_PHONON_EFFECT
+ case EffectClass:
+ return new AudioEffect(this, args[0].toInt(), parent);
+#endif //QT_NO_PHONON_EFFECT
+ case AudioDataOutputClass:
+ return new AudioDataOutput(this, parent);
+
+#ifndef QT_NO_PHONON_VIDEO
+ case VideoDataOutputClass:
+ logMessage("createObject() : VideoDataOutput not implemented");
+ break;
+
+ case VideoWidgetClass: {
+ QWidget *widget = qobject_cast<QWidget*>(parent);
+ return new VideoWidget(this, widget);
+ }
+#endif //QT_NO_PHONON_VIDEO
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+ case VolumeFaderEffectClass:
+ return new VolumeFaderEffect(this, parent);
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+
+ case VisualizationClass: //Fall through
+ default:
+ logMessage("createObject() : Backend object not available");
+ }
+ return 0;
+}
+
+// Returns true if all dependencies are met
+// and gstreamer is usable, otherwise false
+bool Backend::isValid() const
+{
+ return m_isValid;
+}
+
+bool Backend::supportsVideo() const
+{
+ return isValid();
+}
+
+bool Backend::checkDependencies() const
+{
+ bool success = false;
+ // Verify that gst-plugins-base is installed
+ GstElementFactory *acFactory = gst_element_factory_find ("audioconvert");
+ if (acFactory) {
+ gst_object_unref(acFactory);
+ success = true;
+ // Check if gst-plugins-good is installed
+ GstElementFactory *csFactory = gst_element_factory_find ("videobalance");
+ if (csFactory) {
+ gst_object_unref(csFactory);
+ } else {
+ QString message = tr("Warning: You do not seem to have the package gstreamer0.10-plugins-good installed.\n"
+ " Some video features have been disabled.");
+ qDebug() << message;
+ }
+ } else {
+ qWarning() << tr("Warning: You do not seem to have the base GStreamer plugins installed.\n"
+ " All audio and video support has been disabled");
+ }
+ return success;
+}
+
+/***
+ * !reimp
+ */
+QStringList Backend::availableMimeTypes() const
+{
+ QStringList availableMimeTypes;
+
+ if (!isValid())
+ return availableMimeTypes;
+
+ GstElementFactory *mpegFactory;
+ // Add mp3 as a separate mime type as people are likely to look for it.
+ if ((mpegFactory = gst_element_factory_find ("ffmpeg")) ||
+ (mpegFactory = gst_element_factory_find ("mad"))) {
+ availableMimeTypes << QLatin1String("audio/x-mp3");
+ gst_object_unref(GST_OBJECT(mpegFactory));
+ }
+
+ // Iterate over all audio and video decoders and extract mime types from sink caps
+ GList* factoryList = gst_registry_get_feature_list(gst_registry_get_default (), GST_TYPE_ELEMENT_FACTORY);
+ for (GList* iter = g_list_first(factoryList) ; iter != NULL ; iter = g_list_next(iter)) {
+ GstPluginFeature *feature = GST_PLUGIN_FEATURE(iter->data);
+ QString klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
+
+ if (klass == QLatin1String("Codec/Decoder") ||
+ klass == QLatin1String("Codec/Decoder/Audio") ||
+ klass == QLatin1String("Codec/Decoder/Video") ||
+ klass == QLatin1String("Codec/Demuxer") ||
+ klass == QLatin1String("Codec/Demuxer/Audio") ||
+ klass == QLatin1String("Codec/Demuxer/Video") ||
+ klass == QLatin1String("Codec/Parser") ||
+ klass == QLatin1String("Codec/Parser/Audio") ||
+ klass == QLatin1String("Codec/Parser/Video")) {
+
+ const GList *static_templates;
+ GstElementFactory *factory = GST_ELEMENT_FACTORY(feature);
+ static_templates = gst_element_factory_get_static_pad_templates(factory);
+
+ for (; static_templates != NULL ; static_templates = static_templates->next) {
+ GstStaticPadTemplate *padTemplate = (GstStaticPadTemplate *) static_templates->data;
+ if (padTemplate && padTemplate->direction == GST_PAD_SINK) {
+ GstCaps *caps = gst_static_pad_template_get_caps (padTemplate);
+
+ if (caps) {
+ for (unsigned int struct_idx = 0; struct_idx < gst_caps_get_size (caps); struct_idx++) {
+
+ const GstStructure* capsStruct = gst_caps_get_structure (caps, struct_idx);
+ QString mime = QString::fromUtf8(gst_structure_get_name (capsStruct));
+ if (!availableMimeTypes.contains(mime))
+ availableMimeTypes.append(mime);
+ }
+ }
+ }
+ }
+ }
+ }
+ g_list_free(factoryList);
+ if (availableMimeTypes.contains("audio/x-vorbis")
+ && availableMimeTypes.contains("application/x-ogm-audio")) {
+ if (!availableMimeTypes.contains("audio/x-vorbis+ogg"))
+ availableMimeTypes.append("audio/x-vorbis+ogg");
+ if (!availableMimeTypes.contains("application/ogg")) /* *.ogg */
+ availableMimeTypes.append("application/ogg");
+ if (!availableMimeTypes.contains("audio/ogg")) /* *.oga */
+ availableMimeTypes.append("audio/ogg");
+ }
+ availableMimeTypes.sort();
+ return availableMimeTypes;
+}
+
+/***
+ * !reimp
+ */
+QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+ QList<int> list;
+
+ if (!isValid())
+ return list;
+
+ switch (type) {
+ case Phonon::AudioOutputDeviceType: {
+ QList<AudioDevice> deviceList = deviceManager()->audioOutputDevices();
+ for (int dev = 0 ; dev < deviceList.size() ; ++dev)
+ list.append(deviceList[dev].id);
+ break;
+ }
+ break;
+
+ case Phonon::EffectType: {
+ QList<EffectInfo*> effectList = effectManager()->audioEffects();
+ for (int eff = 0 ; eff < effectList.size() ; ++eff)
+ list.append(eff);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return list;
+}
+
+/***
+ * !reimp
+ */
+QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+
+ QHash<QByteArray, QVariant> ret;
+
+ if (!isValid())
+ return ret;
+
+ switch (type) {
+ case Phonon::AudioOutputDeviceType: {
+ AudioDevice* ad;
+ if ((ad = deviceManager()->audioDevice(index))) {
+ ret.insert("name", ad->gstId);
+ ret.insert("description", ad->description);
+ ret.insert("icon", ad->icon);
+ }
+ }
+ break;
+
+ case Phonon::EffectType: {
+ QList<EffectInfo*> effectList = effectManager()->audioEffects();
+ if (index >= 0 && index <= effectList.size()) {
+ const EffectInfo *effect = effectList[index];
+ ret.insert("name", effect->name());
+ ret.insert("description", effect->description());
+ ret.insert("author", effect->author());
+ } else
+ Q_ASSERT(1); // Since we use list position as ID, this should not happen
+ }
+ default:
+ break;
+ }
+ return ret;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::startConnectionChange(QSet<QObject *> objects)
+{
+ foreach (QObject *object, objects) {
+ MediaNode *sourceNode = qobject_cast<MediaNode *>(object);
+ MediaObject *media = sourceNode->root();
+ if (media) {
+ media->saveState();
+ return true;
+ }
+ }
+ return true;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::connectNodes(QObject *source, QObject *sink)
+{
+ if (isValid()) {
+ MediaNode *sourceNode = qobject_cast<MediaNode *>(source);
+ MediaNode *sinkNode = qobject_cast<MediaNode *>(sink);
+ if (sourceNode && sinkNode) {
+ if (sourceNode->connectNode(sink)) {
+ sourceNode->root()->invalidateGraph();
+ logMessage(QString("Backend connected %0 to %1").arg(source->metaObject()->className()).arg(sink->metaObject()->className()));
+ return true;
+ }
+ }
+ }
+ logMessage(QString("Linking %0 to %1 failed").arg(source->metaObject()->className()).arg(sink->metaObject()->className()), Warning);
+ return false;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::disconnectNodes(QObject *source, QObject *sink)
+{
+ MediaNode *sourceNode = qobject_cast<MediaNode *>(source);
+ MediaNode *sinkNode = qobject_cast<MediaNode *>(sink);
+
+ if (sourceNode && sinkNode)
+ return sourceNode->disconnectNode(sink);
+ else
+ return false;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::endConnectionChange(QSet<QObject *> objects)
+{
+ foreach (QObject *object, objects) {
+ MediaNode *sourceNode = qobject_cast<MediaNode *>(object);
+ MediaObject *media = sourceNode->root();
+ if (media) {
+ media->resumeState();
+ return true;
+ }
+ }
+ return true;
+}
+
+/***
+ * Request bus messages for this mediaobject
+ */
+void Backend::addBusWatcher(MediaObject* node)
+{
+ Q_ASSERT(node);
+ GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(node->pipeline()));
+ gst_bus_add_watch (bus, busCall, node);
+ gst_object_unref(bus);
+}
+
+/***
+ * Ignore bus messages for this mediaobject
+ */
+void Backend::removeBusWatcher(MediaObject* node)
+{
+ Q_ASSERT(node);
+ g_source_remove_by_user_data(node);
+}
+
+/***
+ * Polls each mediaobject's pipeline and delivers
+ * pending any pending messages
+ */
+void Backend::handleBusMessage(Message message)
+{
+ MediaObject *mediaObject = message.source();
+ mediaObject->handleBusMessage(message);
+}
+
+DeviceManager* Backend::deviceManager() const
+{
+ return m_deviceManager;
+}
+
+EffectManager* Backend::effectManager() const
+{
+ return m_effectManager;
+}
+
+/**
+ * Returns a debuglevel that is determined by the
+ * PHONON_GST_DEBUG environment variable.
+ *
+ * Warning - important warnings
+ * Info - general info
+ * Debug - gives extra info
+ */
+Backend::DebugLevel Backend::debugLevel() const
+{
+ return m_debugLevel;
+}
+
+/***
+ * Prints a conditional debug message based on the current debug level
+ * If obj is provided, classname and objectname will be printed as well
+ *
+ * see debugLevel()
+ */
+void Backend::logMessage(const QString &message, int priority, QObject *obj) const
+{
+ if (debugLevel() > 0) {
+ QString output;
+ if (obj) {
+ // Strip away namespace from className
+ QString className(obj->metaObject()->className());
+ int nameLength = className.length() - className.lastIndexOf(':') - 1;
+ className = className.right(nameLength);
+ output.sprintf("%s %s (%s %p)", message.toLatin1().constData(),
+ obj->objectName().toLatin1().constData(),
+ className.toLatin1().constData(), obj);
+ }
+ else {
+ output = message;
+ }
+ if (priority <= (int)debugLevel()) {
+ qDebug() << QString("PGST(%1): %2").arg(priority).arg(output);
+ }
+ }
+}
+
+}
+}
+
+QT_END_NAMESPACE
+
+#include "moc_backend.cpp"
diff --git a/src/3rdparty/phonon/gstreamer/backend.h b/src/3rdparty/phonon/gstreamer/backend.h
new file mode 100644
index 0000000..d157f11
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/backend.h
@@ -0,0 +1,100 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_BACKEND_H
+#define Phonon_GSTREAMER_BACKEND_H
+
+#include "common.h"
+#include "devicemanager.h"
+#include "medianode.h"
+
+#include <phonon/objectdescription.h>
+#include <phonon/backendinterface.h>
+
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+#include <QtCore/QStringList>
+#include <QtCore/QTimer>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+class AudioOutput;
+class MediaNode;
+class MediaObject;
+class EffectManager;
+
+class Backend : public QObject, public BackendInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::BackendInterface)
+
+public:
+
+ enum DebugLevel {NoDebug, Warning, Info, Debug};
+ Backend(QObject *parent = 0, const QVariantList & = QVariantList());
+ virtual ~Backend();
+
+ DeviceManager* deviceManager() const;
+ EffectManager* effectManager() const;
+
+ QObject *createObject(BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
+
+ bool isValid() const;
+ bool supportsVideo() const;
+ QStringList availableMimeTypes() const;
+
+ QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+
+ bool startConnectionChange(QSet<QObject *>);
+ bool connectNodes(QObject *, QObject *);
+ bool disconnectNodes(QObject *, QObject *);
+ bool endConnectionChange(QSet<QObject *>);
+
+ DebugLevel debugLevel() const;
+
+ void addBusWatcher(MediaObject* node);
+ void removeBusWatcher(MediaObject* node);
+ void logMessage(const QString &message, int priority = 2, QObject *obj=0) const;
+ bool checkDependencies() const;
+
+Q_SIGNALS:
+ void objectDescriptionChanged(ObjectDescriptionType);
+
+private Q_SLOTS:
+ void handleBusMessage(Message);
+
+private:
+ static gboolean busCall(GstBus *bus, GstMessage *msg, gpointer data);
+
+ DeviceManager *m_deviceManager;
+ EffectManager *m_effectManager;
+ DebugLevel m_debugLevel;
+ bool m_isValid;
+};
+}
+} // namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_BACKEND_H
diff --git a/src/3rdparty/phonon/gstreamer/common.h b/src/3rdparty/phonon/gstreamer/common.h
new file mode 100644
index 0000000..355df50
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/common.h
@@ -0,0 +1,51 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_COMMON_H
+#define Phonon_GSTREAMER_COMMON_H
+
+#include <phonon/phonon_export.h>
+
+#include <QtCore/QDebug>
+
+#ifdef DEBUG_IMPLEMENTED
+#define IMPLEMENTED qDebug() << "PGst:" << __FUNCTION__ << "(" << __FILE__ << "):"
+#else
+#define IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef DEBUG_HALF_IMPLEMENTED
+#define HALF_IMPLEMENTED qDebug() << "PGst: --- HALF IMPLEMENTED:" << __FUNCTION__ << "(" << __FILE__ << "):"
+#else
+#define HALF_IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef DEBUG_NOT_IMPLEMENTED
+#define NOT_IMPLEMENTED qDebug() << "PGst: *** NOT IMPLEMENTED:" << __FUNCTION__ << "(" << __FILE__ << "):"
+#else
+#define NOT_IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef DEBUG_IMPLEMENTED_SILENT
+#define IMPLEMENTED_SILENT qDebug() << "PGst: (silent)" << __FUNCTION__ << "(" << __FILE__ << "):"
+#else
+#define IMPLEMENTED_SILENT if (1); else qDebug()
+#endif
+
+#define BACKEND_WARNING qDebug() << "PGst: ____ WARNING ____" << Q_FUNC_INFO << ":"
+
+#endif // Phonon_GSTREAMER_COMMON_H
diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.cpp b/src/3rdparty/phonon/gstreamer/devicemanager.cpp
new file mode 100644
index 0000000..518aa85
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/devicemanager.cpp
@@ -0,0 +1,396 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gst/interfaces/propertyprobe.h>
+#include "devicemanager.h"
+#include "backend.h"
+#include "gsthelper.h"
+#include "videowidget.h"
+#include "glrenderer.h"
+#include "widgetrenderer.h"
+#ifdef Q_WS_X11
+#include "x11renderer.h"
+#endif
+#include "artssink.h"
+#include "pulsesupport.h"
+
+#ifdef USE_ALSASINK2
+#include "alsasink2.h"
+#endif
+
+/*
+ * This class manages the list of currently
+ * active output devices
+ */
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+AudioDevice::AudioDevice(DeviceManager *manager, const QByteArray &gstId)
+ : gstId(gstId)
+{
+ // This should never be called when PulseAudio is active.
+ Q_ASSERT(!PulseSupport::getInstance()->isActive());
+
+ id = manager->allocateDeviceId();
+ icon = "audio-card";
+
+ //get name from device
+ if (gstId == "default") {
+ description = "Default audio device";
+ } else {
+ GstElement *aSink= manager->createAudioSink();
+
+ if (aSink) {
+ gchar *deviceDescription = NULL;
+
+ if (GST_IS_PROPERTY_PROBE(aSink) && gst_property_probe_get_property( GST_PROPERTY_PROBE(aSink), "device" ) ) {
+ g_object_set (G_OBJECT(aSink), "device", gstId.constData(), (const char*)NULL);
+ g_object_get (G_OBJECT(aSink), "device-name", &deviceDescription, (const char*)NULL);
+ description = QByteArray(deviceDescription);
+ g_free (deviceDescription);
+ gst_element_set_state(aSink, GST_STATE_NULL);
+ gst_object_unref (aSink);
+ }
+ }
+ }
+}
+
+DeviceManager::DeviceManager(Backend *backend)
+ : QObject(backend)
+ , m_backend(backend)
+ , m_audioDeviceCounter(0)
+{
+ QSettings settings(QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+
+ PulseSupport *pulse = PulseSupport::getInstance();
+ m_audioSink = qgetenv("PHONON_GST_AUDIOSINK");
+ if (m_audioSink.isEmpty()) {
+ m_audioSink = settings.value(QLatin1String("audiosink"), "Auto").toByteArray().toLower();
+ if (m_audioSink == "auto" && pulse->isActive())
+ m_audioSink = "pulsesink";
+ }
+ if ("pulsesink" != m_audioSink)
+ pulse->enable(false);
+
+ m_videoSinkWidget = qgetenv("PHONON_GST_VIDEOMODE");
+ if (m_videoSinkWidget.isEmpty()) {
+ m_videoSinkWidget = settings.value(QLatin1String("videomode"), "Auto").toByteArray().toLower();
+ }
+
+ if (m_backend->isValid())
+ updateDeviceList();
+}
+
+DeviceManager::~DeviceManager()
+{
+ m_audioDeviceList.clear();
+}
+
+/***
+* Returns a Gst Audiosink based on GNOME configuration settings,
+* or 0 if the element is not available.
+*/
+GstElement *DeviceManager::createGNOMEAudioSink(Category category)
+{
+ GstElement *sink = gst_element_factory_make ("gconfaudiosink", NULL);
+
+ if (sink) {
+
+ // set profile property on the gconfaudiosink to "music and movies"
+ if (g_object_class_find_property (G_OBJECT_GET_CLASS (sink), "profile")) {
+ switch (category) {
+ case NotificationCategory:
+ g_object_set (G_OBJECT (sink), "profile", 0, (const char*)NULL); // 0 = 'sounds'
+ break;
+ case CommunicationCategory:
+ g_object_set (G_OBJECT (sink), "profile", 2, (const char*)NULL); // 2 = 'chat'
+ break;
+ default:
+ g_object_set (G_OBJECT (sink), "profile", 1, (const char*)NULL); // 1 = 'music and movies'
+ break;
+ }
+ }
+ }
+ return sink;
+}
+
+
+bool DeviceManager::canOpenDevice(GstElement *element) const
+{
+ if (!element)
+ return false;
+
+ if (gst_element_set_state(element, GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS)
+ return true;
+
+ const QList<QByteArray> &list = GstHelper::extractProperties(element, "device");
+ foreach (const QByteArray &gstId, list) {
+ GstHelper::setProperty(element, "device", gstId);
+ if (gst_element_set_state(element, GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS) {
+ return true;
+ }
+ }
+ // FIXME: the above can still fail for a valid alsasink because list only contains entries of
+ // the form "hw:X,Y". Would be better to use "default:X" or "dmix:X,Y"
+
+ gst_element_set_state(element, GST_STATE_NULL);
+ return false;
+}
+
+/*
+*
+* Returns a GstElement with a valid audio sink
+* based on the current value of PHONON_GSTREAMER_DRIVER
+*
+* Allowed values are auto (default), alsa, oss, arts and ess
+* does not exist
+*
+* If no real sound sink is available a fakesink will be returned
+*/
+GstElement *DeviceManager::createAudioSink(Category category)
+{
+ GstElement *sink = 0;
+
+ if (m_backend && m_backend->isValid())
+ {
+ if (m_audioSink == "auto") //this is the default value
+ {
+ //### TODO : get equivalent KDE settings here
+
+ if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
+ sink = createGNOMEAudioSink(category);
+ if (canOpenDevice(sink))
+ m_backend->logMessage("AudioOutput using gconf audio sink");
+ else if (sink) {
+ gst_object_unref(sink);
+ sink = 0;
+ }
+ }
+
+#ifdef USE_ALSASINK2
+ if (!sink) {
+ sink = gst_element_factory_make ("_k_alsasink", NULL);
+ if (canOpenDevice(sink))
+ m_backend->logMessage("AudioOutput using alsa2 audio sink");
+ else if (sink) {
+ gst_object_unref(sink);
+ sink = 0;
+ }
+ }
+#endif
+
+ if (!sink) {
+ sink = gst_element_factory_make ("alsasink", NULL);
+ if (canOpenDevice(sink))
+ m_backend->logMessage("AudioOutput using alsa audio sink");
+ else if (sink) {
+ gst_object_unref(sink);
+ sink = 0;
+ }
+ }
+
+ if (!sink) {
+ sink = gst_element_factory_make ("autoaudiosink", NULL);
+ if (canOpenDevice(sink))
+ m_backend->logMessage("AudioOutput using auto audio sink");
+ else if (sink) {
+ gst_object_unref(sink);
+ sink = 0;
+ }
+ }
+
+ if (!sink) {
+ sink = gst_element_factory_make ("osssink", NULL);
+ if (canOpenDevice(sink))
+ m_backend->logMessage("AudioOutput using oss audio sink");
+ else if (sink) {
+ gst_object_unref(sink);
+ sink = 0;
+ }
+ }
+ } else if (m_audioSink == "fake") {
+ //do nothing as a fakesink will be created by default
+ } else if (m_audioSink == "artssink") {
+ sink = GST_ELEMENT(g_object_new(arts_sink_get_type(), NULL));
+ } else if (!m_audioSink.isEmpty()) { //Use a custom sink
+ sink = gst_element_factory_make (m_audioSink, NULL);
+ if (canOpenDevice(sink))
+ m_backend->logMessage(QString("AudioOutput using %0").arg(QString::fromUtf8(m_audioSink)));
+ else if (sink) {
+ gst_object_unref(sink);
+ sink = 0;
+ }
+ }
+ }
+
+ if (!sink) { //no suitable sink found so we'll make a fake one
+ sink = gst_element_factory_make("fakesink", NULL);
+ if (sink) {
+ m_backend->logMessage("AudioOutput Using fake audio sink");
+ //without sync the sink will pull the pipeline as fast as the CPU allows
+ g_object_set (G_OBJECT (sink), "sync", TRUE, (const char*)NULL);
+ }
+ }
+ Q_ASSERT(sink);
+ return sink;
+}
+
+#ifndef QT_NO_PHONON_VIDEO
+AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget *parent)
+{
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES)
+ if (m_videoSinkWidget == "opengl") {
+ return new GLRenderer(parent);
+ } else
+#endif
+ if (m_videoSinkWidget == "software") {
+ return new WidgetRenderer(parent);
+ }
+#ifdef Q_WS_X11
+ else if (m_videoSinkWidget == "xwindow") {
+ return new X11Renderer(parent);
+ } else {
+ GstElementFactory *srcfactory = gst_element_factory_find("ximagesink");
+ if (srcfactory) {
+ return new X11Renderer(parent);
+ }
+ }
+#endif
+ return new WidgetRenderer(parent);
+}
+#endif //QT_NO_PHONON_VIDEO
+
+/**
+ * Allocate a device id for a new audio device
+ */
+int DeviceManager::allocateDeviceId()
+{
+ return m_audioDeviceCounter++;
+}
+
+
+/**
+ * Returns a positive device id or -1 if device does not exist
+ *
+ * The gstId is typically in the format hw:1,0
+ */
+int DeviceManager::deviceId(const QByteArray &gstId) const
+{
+ for (int i = 0 ; i < m_audioDeviceList.size() ; ++i) {
+ if (m_audioDeviceList[i].gstId == gstId) {
+ return m_audioDeviceList[i].id;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Returns a gstId or "default" if device does not exist
+ *
+ * The gstId is typically in the format hw:1,0
+ */
+const QByteArray DeviceManager::gstId(int deviceId)
+{
+ if (!PulseSupport::getInstance()->isActive()) {
+ AudioDevice *ad = audioDevice(deviceId);
+ if (ad)
+ return QByteArray(ad->gstId);
+ }
+ return QByteArray("default");
+}
+
+/**
+* Get the AudioDevice for a given device id
+*/
+AudioDevice* DeviceManager::audioDevice(int id)
+{
+ for (int i = 0 ; i < m_audioDeviceList.size() ; ++i) {
+ if (m_audioDeviceList[i].id == id)
+ return &m_audioDeviceList[i];
+ }
+ return NULL;
+}
+
+/**
+ * Updates the current list of active devices
+ */
+void DeviceManager::updateDeviceList()
+{
+ //fetch list of current devices
+ GstElement *audioSink= createAudioSink();
+
+ QList<QByteArray> list;
+
+ if (audioSink) {
+ if (!PulseSupport::getInstance()->isActive()) {
+ // If we're using pulse, the PulseSupport class takes care of things for us.
+ list = GstHelper::extractProperties(audioSink, "device");
+ list.prepend("default");
+ }
+
+ for (int i = 0 ; i < list.size() ; ++i) {
+ QByteArray gstId = list.at(i);
+ if (deviceId(gstId) == -1) {
+ // This is a new device, add it
+ m_audioDeviceList.append(AudioDevice(this, gstId));
+ emit deviceAdded(deviceId(gstId));
+ m_backend->logMessage(QString("Found new audio device %0").arg(QString::fromUtf8(gstId)), Backend::Debug, this);
+ }
+ }
+
+ if (list.size() < m_audioDeviceList.size()) {
+ //a device was removed
+ for (int i = m_audioDeviceList.size() -1 ; i >= 0 ; --i) {
+ QByteArray currId = m_audioDeviceList[i].gstId;
+ bool found = false;
+ for (int k = list.size() -1 ; k >= 0 ; --k) {
+ if (currId == list[k]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ m_backend->logMessage(QString("Audio device lost %0").arg(QString::fromUtf8(currId)), Backend::Debug, this);
+ emit deviceRemoved(deviceId(currId));
+ m_audioDeviceList.removeAt(i);
+ }
+ }
+ }
+ }
+
+ gst_element_set_state (audioSink, GST_STATE_NULL);
+ gst_object_unref (audioSink);
+}
+
+/**
+ * Returns a list of hardware id usable by gstreamer [i.e hw:1,0]
+ */
+const QList<AudioDevice> DeviceManager::audioOutputDevices() const
+{
+ return m_audioDeviceList;
+}
+
+}
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.h b/src/3rdparty/phonon/gstreamer/devicemanager.h
new file mode 100644
index 0000000..9c6aa8d
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/devicemanager.h
@@ -0,0 +1,84 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_DEVICEMANAGER_H
+#define Phonon_GSTREAMER_DEVICEMANAGER_H
+
+#include "common.h"
+
+#include <phonon/audiooutputinterface.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QTimer>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon {
+namespace Gstreamer {
+class Backend;
+class DeviceManager;
+class AbstractRenderer;
+class VideoWidget;
+
+class AudioDevice {
+public :
+ AudioDevice(DeviceManager *s, const QByteArray &deviceId);
+ int id;
+ QByteArray gstId;
+ QByteArray description;
+ QString icon;
+};
+
+class DeviceManager : public QObject {
+ Q_OBJECT
+public:
+ DeviceManager(Backend *parent);
+ virtual ~DeviceManager();
+ const QList<AudioDevice> audioOutputDevices() const;
+ GstPad *requestPad(int device) const;
+ int allocateDeviceId();
+ int deviceId(const QByteArray &gstId) const;
+ const QByteArray gstId(int id);
+ AudioDevice* audioDevice(int id);
+ GstElement *createGNOMEAudioSink(Category category);
+ GstElement *createAudioSink(Category category = NoCategory);
+ AbstractRenderer *createVideoRenderer(VideoWidget *parent);
+
+signals:
+ void deviceAdded(int);
+ void deviceRemoved(int);
+
+public slots:
+ void updateDeviceList();
+
+private:
+ bool canOpenDevice(GstElement *element) const;
+ Backend *m_backend;
+ QList <AudioDevice> m_audioDeviceList;
+ int m_audioDeviceCounter;
+ QTimer m_devicePollTimer;
+ QByteArray m_audioSink;
+ QByteArray m_videoSinkWidget;
+};
+}
+} // namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_DEVICEMANAGER_H
diff --git a/src/3rdparty/phonon/gstreamer/effect.cpp b/src/3rdparty/phonon/gstreamer/effect.cpp
new file mode 100644
index 0000000..4937246
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/effect.cpp
@@ -0,0 +1,246 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "effect.h"
+#include "common.h"
+#include "audiooutput.h"
+#include "backend.h"
+#include "medianode.h"
+#include "effectmanager.h"
+#include "gsthelper.h"
+
+#include <gst/gst.h>
+
+#ifndef QT_NO_PHONON_EFFECT
+QT_BEGIN_NAMESPACE
+namespace Phonon
+{
+namespace Gstreamer
+{
+Effect::Effect(Backend *backend, QObject *parent, NodeDescription description)
+ : QObject(parent),
+ MediaNode(backend, description)
+ , m_effectBin(0)
+ , m_effectElement(0)
+{
+}
+
+void Effect::init()
+{
+ m_effectBin = createEffectBin();
+ if (m_effectBin) {
+ setupEffectParams();
+ gst_object_ref (GST_OBJECT (m_effectBin)); // Take ownership
+ gst_object_sink (GST_OBJECT (m_effectBin));
+ m_isValid = true;
+ }
+}
+
+Effect::~Effect()
+{
+ if (m_effectBin) {
+ gst_element_set_state (m_effectBin, GST_STATE_NULL);
+ gst_object_unref (m_effectBin);
+ }
+}
+
+void Effect::setupEffectParams()
+{
+
+ Q_ASSERT(m_effectElement);
+
+ //query and store parameters
+ if (m_effectElement) {
+ GParamSpec **property_specs;
+ guint propertyCount, i;
+ property_specs = g_object_class_list_properties(G_OBJECT_GET_CLASS (m_effectElement), &propertyCount);
+ for (i = 0; i < propertyCount; i++) {
+ GParamSpec *param = property_specs[i];
+ if (param->flags & G_PARAM_WRITABLE) {
+ QString propertyName = g_param_spec_get_name (param);
+
+ // These properties should not be exposed to the front-end
+ if (propertyName == "qos" || propertyName == "name" || propertyName == "async-handling")
+ continue;
+
+ switch(param->value_type) {
+ case G_TYPE_UINT:
+ m_parameterList.append(Phonon::EffectParameter(i, propertyName,
+ 0, //hints
+ G_PARAM_SPEC_UINT(param)->default_value,
+ G_PARAM_SPEC_UINT(param)->minimum,
+ G_PARAM_SPEC_UINT(param)->maximum));
+ break;
+
+ case G_TYPE_STRING:
+ m_parameterList.append(Phonon::EffectParameter(i, propertyName,
+ 0, //hints
+ G_PARAM_SPEC_STRING(param)->default_value,
+ 0,
+ 0));
+ break;
+
+ case G_TYPE_INT:
+ m_parameterList.append(Phonon::EffectParameter(i, propertyName,
+ EffectParameter::IntegerHint, //hints
+ QVariant(G_PARAM_SPEC_INT(param)->default_value),
+ QVariant(G_PARAM_SPEC_INT(param)->minimum),
+ QVariant(G_PARAM_SPEC_INT(param)->maximum)));
+ break;
+
+ case G_TYPE_FLOAT:
+ m_parameterList.append(Phonon::EffectParameter(i, propertyName,
+ 0, //hints
+ QVariant((double)G_PARAM_SPEC_FLOAT(param)->default_value),
+ QVariant((double)G_PARAM_SPEC_FLOAT(param)->minimum),
+ QVariant((double)G_PARAM_SPEC_FLOAT(param)->maximum)));
+ break;
+
+ case G_TYPE_DOUBLE:
+ m_parameterList.append(Phonon::EffectParameter(i, propertyName,
+ 0, //hints
+ QVariant(G_PARAM_SPEC_DOUBLE(param)->default_value),
+ QVariant(G_PARAM_SPEC_DOUBLE(param)->minimum),
+ QVariant(G_PARAM_SPEC_DOUBLE(param)->maximum)));
+ break;
+
+ case G_TYPE_BOOLEAN:
+ m_parameterList.append(Phonon::EffectParameter(i, propertyName,
+ Phonon::EffectParameter::ToggledHint, //hints
+ QVariant((bool)G_PARAM_SPEC_BOOLEAN(param)->default_value),
+ QVariant((bool)false), QVariant((bool)true)));
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
+QList<Phonon::EffectParameter> Effect::parameters() const
+{
+ return m_parameterList;
+}
+
+QVariant Effect::parameterValue(const EffectParameter &p) const
+{
+
+ Q_ASSERT(m_effectElement);
+
+ QVariant returnVal;
+ switch (p.type()) {
+ case QVariant::Int:
+ {
+ gint val = 0;
+ g_object_get(G_OBJECT(m_effectElement), qPrintable(p.name()), &val, (const char*)NULL);
+ returnVal = val;
+ }
+ break;
+
+ case QVariant::Bool:
+ {
+ gboolean val = 0;
+ g_object_get(G_OBJECT(m_effectElement), qPrintable(p.name()), &val, (const char*)NULL);
+ returnVal = val;
+ }
+ break;
+
+ case QVariant::String:
+ {
+ gchar *val = 0;
+ g_object_get(G_OBJECT(m_effectElement), qPrintable(p.name()), &val, (const char*)NULL);
+ returnVal = QString::fromUtf8(val);
+ g_free(val);
+ }
+ break;
+
+ case QVariant::Double:
+ {
+ GParamSpec* spec = g_object_class_find_property(G_OBJECT_GET_CLASS(m_effectElement), p.name().toLatin1().constData());
+ Q_ASSERT(spec);
+ if (spec && spec->value_type == G_TYPE_FLOAT) {
+ gfloat val = 0;
+ g_object_get(G_OBJECT(m_effectElement), qPrintable(p.name()), &val, (const char*)NULL);
+ returnVal = QVariant((float)val);
+ } else {
+ gdouble val = 0;
+ g_object_get(G_OBJECT(m_effectElement), qPrintable(p.name()), &val, (const char*)NULL);
+ returnVal = QVariant((float)val);
+ }
+ }
+ break;
+
+ default:
+ Q_ASSERT(0); //not a supported variant type
+ }
+ return returnVal;
+}
+
+
+void Effect::setParameterValue(const EffectParameter &p, const QVariant &v)
+{
+ Q_ASSERT(m_effectElement);
+
+ // Note that the frontend currently calls this after creation with a null-value
+ // for all parameters.
+
+ if (v.isValid()) {
+
+ switch (p.type()) {
+ // ### range values should really be checked by the front end, why isnt it working?
+ case QVariant::Int:
+ if (v.toInt() >= p.minimumValue().toInt() && v.toInt() <= p.maximumValue().toInt())
+ g_object_set(G_OBJECT(m_effectElement), qPrintable(p.name()), (gint)v.toInt(), (const char*)NULL);
+ break;
+
+ case QVariant::Double:
+ if (v.toDouble() >= p.minimumValue().toDouble() && v.toDouble() <= p.maximumValue().toDouble()) {
+ GParamSpec* spec = g_object_class_find_property(G_OBJECT_GET_CLASS(m_effectElement), p.name().toLatin1().constData());
+ Q_ASSERT(spec);
+ if (spec && spec->value_type == G_TYPE_FLOAT)
+ g_object_set(G_OBJECT(m_effectElement), qPrintable(p.name()), (gfloat)v.toDouble(), (const char*)NULL);
+ else
+ g_object_set(G_OBJECT(m_effectElement), qPrintable(p.name()), (gdouble)v.toDouble(), (const char*)NULL);
+ }
+ break;
+
+ case QVariant::UInt:
+ if (v.toUInt() >= p.minimumValue().toUInt() && v.toUInt() <= p.maximumValue().toUInt())
+ g_object_set(G_OBJECT(m_effectElement), qPrintable(p.name()), v.toUInt(), (const char*)NULL);
+ break;
+
+ case QVariant::String:
+ g_object_set(G_OBJECT(m_effectElement), qPrintable(p.name()), v.toString().toUtf8().constData(), (const char*)NULL);
+ break;
+
+ case QVariant::Bool:
+ g_object_set(G_OBJECT(m_effectElement), qPrintable(p.name()), (gboolean)v.toBool(), (const char*)NULL);
+ break;
+
+ default:
+ Q_ASSERT(0); //not a supported variant type
+ }
+ }
+}
+
+}
+} //namespace Phonon::Gstreamer
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_EFFECT
+#include "moc_effect.cpp"
diff --git a/src/3rdparty/phonon/gstreamer/effect.h b/src/3rdparty/phonon/gstreamer/effect.h
new file mode 100644
index 0000000..51cbe9c
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/effect.h
@@ -0,0 +1,64 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_EFFECT_H
+#define Phonon_GSTREAMER_EFFECT_H
+
+#include "common.h"
+#include "medianode.h"
+
+#include <phonon/effectparameter.h>
+#include <phonon/effectinterface.h>
+
+#include <QtCore/QObject>
+
+#include <gst/gst.h>
+
+#ifndef QT_NO_PHONON_EFFECT
+QT_BEGIN_NAMESPACE
+namespace Phonon
+{
+namespace Gstreamer
+{
+ class EffectInfo;
+
+ class Effect : public QObject, public Phonon::EffectInterface, public MediaNode
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface Phonon::Gstreamer::MediaNode)
+ public:
+ Effect (Backend *backend, QObject *parent, NodeDescription description);
+ virtual ~Effect ();
+
+ virtual QList<EffectParameter> parameters() const;
+ virtual QVariant parameterValue(const EffectParameter &) const;
+ virtual void setParameterValue(const EffectParameter &, const QVariant &);
+
+ virtual GstElement* createEffectBin() = 0;
+ virtual void init();
+ virtual void setupEffectParams();
+
+ protected:
+ GstElement *m_effectBin;
+ GstElement *m_effectElement;
+ QList<Phonon::EffectParameter> m_parameterList;
+ };
+}} //namespace Phonon::Gstreamer
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_EFFECT
+
+#endif // Phonon_GSTREAMER_EFFECT_H
diff --git a/src/3rdparty/phonon/gstreamer/effectmanager.cpp b/src/3rdparty/phonon/gstreamer/effectmanager.cpp
new file mode 100644
index 0000000..6c88148
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/effectmanager.cpp
@@ -0,0 +1,105 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gst/interfaces/propertyprobe.h>
+#include "effectmanager.h"
+#include "backend.h"
+#include "gsthelper.h"
+
+/*
+ * This class manages the list of currently
+ * available audio effects.
+ */
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+EffectInfo::EffectInfo(const QString &name, const QString&description, const QString&author)
+ : m_name(name)
+ , m_description(description)
+ , m_author(author) {}
+
+EffectManager::EffectManager(Backend *backend)
+ : QObject(backend)
+ , m_backend(backend)
+{
+ GList* factoryList = gst_registry_get_feature_list(gst_registry_get_default (), GST_TYPE_ELEMENT_FACTORY);
+ QString name, klass, description, author;
+ for (GList* iter = g_list_first(factoryList) ; iter != NULL ; iter = g_list_next(iter)) {
+ GstPluginFeature *feature = GST_PLUGIN_FEATURE(iter->data);
+ klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
+ if ( klass == "Filter/Effect/Audio" ) {
+ name = GST_PLUGIN_FEATURE_NAME(feature);
+
+ // These plugins simply make no sense to the frontend:
+ // "audiorate" Should be internal
+ // "volume" not needed
+ // "equalizer-nbands" not really useful at the moment
+
+ // These plugins simply don't work or have major stability issues:
+ // "iir" Does not seem to do much at the moment
+ // "audioinvert" Only works for some streams, should be invesigated
+ // "lpwsinc" Crashes for large values of filter kernel
+ // "name" Crashes for large values of filter kernel
+
+ // Seems to be working, but not well tested:
+ // name == "rglimiter" Seems functional
+ // name == "rgvolume" Seems to be working
+
+ QString pluginString = qgetenv("PHONON_GST_ALL_EFFECTS");
+ bool acceptAll = pluginString.toInt();
+
+ if (acceptAll
+ // Plugins that have been accepted so far
+ || name == "audiopanorama"
+ || name == "audioamplify"
+ || name == "audiodynamic"
+ || name == "equalizer-10bands"
+ || name == "speed")
+ {
+ description = gst_element_factory_get_description (GST_ELEMENT_FACTORY(feature));
+ author = gst_element_factory_get_author (GST_ELEMENT_FACTORY(feature));
+ EffectInfo *effect = new EffectInfo(name, description, author);
+ m_audioEffectList.append(effect);
+ }
+ }
+ }
+ g_list_free(factoryList);
+}
+
+EffectManager::~EffectManager()
+{
+ qDeleteAll(m_audioEffectList);
+ m_audioEffectList.clear();
+}
+
+/**
+ * Returns a list of available audio effects
+ */
+const QList<EffectInfo*> EffectManager::audioEffects() const
+{
+ return m_audioEffectList;
+}
+
+}
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/effectmanager.h b/src/3rdparty/phonon/gstreamer/effectmanager.h
new file mode 100644
index 0000000..f7d9c96
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/effectmanager.h
@@ -0,0 +1,91 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_EFFECTMANAGER_H
+#define Phonon_GSTREAMER_EFFECTMANAGER_H
+
+#include "common.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QTimer>
+#include <QtCore/QStringList>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+class Backend;
+class EffectManager;
+
+class EffectInfo
+{
+public :
+ EffectInfo(const QString &name,
+ const QString &description,
+ const QString &author);
+
+ QString name() const
+ {
+ return m_name;
+ }
+ QString description() const
+ {
+ return m_description;
+ }
+ QString author() const
+ {
+ return m_author;
+ }
+ QStringList properties() const
+ {
+ return m_properties;
+ }
+ void addProperty(QString propertyName)
+ {
+ m_properties.append(propertyName);
+ }
+
+private:
+ QString m_name;
+ QString m_description;
+ QString m_author;
+ QStringList m_properties;
+};
+
+class EffectManager : public QObject
+{
+ Q_OBJECT
+public:
+ EffectManager(Backend *parent);
+ virtual ~EffectManager();
+ const QList<EffectInfo*> audioEffects() const;
+
+private:
+ Backend *m_backend;
+ QList <EffectInfo*> m_audioEffectList;
+ QList <EffectInfo*> m_visualizationList;
+};
+}
+} // namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_EFFECTMANAGER_H
diff --git a/src/3rdparty/phonon/gstreamer/glrenderer.cpp b/src/3rdparty/phonon/gstreamer/glrenderer.cpp
new file mode 100644
index 0000000..106884f
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/glrenderer.cpp
@@ -0,0 +1,339 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QtGui/QPainter>
+#include <QtGui/QResizeEvent>
+
+#ifndef QT_NO_OPENGL
+
+#include "common.h"
+#include "message.h"
+#include "mediaobject.h"
+#include "qwidgetvideosink.h"
+#include "glrenderer.h"
+#include "qrgb.h"
+
+#if !defined(QT_OPENGL_ES)
+
+#include <gst/gst.h>
+
+// support old OpenGL installations (1.2)
+// assume that if TEXTURE0 isn't defined, none are
+#ifndef GL_TEXTURE0
+# define GL_TEXTURE0 0x84C0
+# define GL_TEXTURE1 0x84C1
+# define GL_TEXTURE2 0x84C2
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static void frameRendered()
+{
+ static QString displayFps = qgetenv("PHONON_GST_FPS");
+ if (displayFps.isEmpty())
+ return;
+
+ static int frames = 0;
+ static QTime lastTime = QTime::currentTime();
+ QTime time = QTime::currentTime();
+
+ int delta = lastTime.msecsTo(time);
+ if (delta > 2000) {
+ printf("FPS: %f\n", 1000.0 * frames / qreal(delta));
+ lastTime = time;
+ frames = 0;
+ }
+
+ ++frames;
+}
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+GLRenderer::GLRenderer(VideoWidget* videoWidget) :
+ AbstractRenderer(videoWidget)
+ , m_glWindow(0)
+{
+ videoWidget->backend()->logMessage("Creating OpenGL renderer");
+ QGLFormat format = QGLFormat::defaultFormat();
+ format.setSwapInterval(1); // Enable vertical sync on draw to avoid tearing
+ m_glWindow = new GLRenderWidgetImplementation(videoWidget, format);
+
+ if ((m_videoSink = m_glWindow->createVideoSink())) { //if ((m_videoSink = m_glWindow->createVideoSink())) {
+ gst_object_ref (GST_OBJECT (m_videoSink)); //Take ownership
+ gst_object_sink (GST_OBJECT (m_videoSink));
+
+ QWidgetVideoSinkBase* sink = reinterpret_cast<QWidgetVideoSinkBase*>(m_videoSink);
+ // Let the videosink know which widget to direct frame updates to
+ sink->renderWidget = videoWidget;
+ }
+}
+
+GLRenderer::~GLRenderer()
+{
+ if (m_videoSink) {
+ gst_object_unref (GST_OBJECT (m_videoSink));
+ m_videoSink = 0;
+ }
+}
+
+
+bool GLRenderer::eventFilter(QEvent * event)
+{
+ if (event->type() == QEvent::User) {
+ NewFrameEvent *frameEvent= static_cast <NewFrameEvent *>(event);
+ m_glWindow->setNextFrame(frameEvent->frame, frameEvent->width, frameEvent->height);
+ return true;
+ }
+ else if (event->type() == QEvent::Resize) {
+ m_glWindow->setGeometry(m_videoWidget->geometry());
+ return true;
+ }
+ return false;
+}
+
+void GLRenderer::handleMediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()) {
+ case MediaNodeEvent::SourceChanged:
+ {
+ Q_ASSERT(m_glWindow);
+ m_glWindow->clearFrame();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+GstElement* GLRenderWidgetImplementation::createVideoSink()
+{
+ if (hasYUVSupport())
+ return GST_ELEMENT(g_object_new(get_type_YUV(), NULL));
+ return 0;
+}
+
+void GLRenderWidgetImplementation::setNextFrame(const QByteArray &array, int w, int h)
+{
+ if (m_videoWidget->root()->state() == Phonon::LoadingState)
+ return;
+
+ m_frame = QImage();
+
+ if (hasYUVSupport())
+ updateTexture(array, w, h);
+ else
+ m_frame = QImage((uchar *)array.constData(), w, h, QImage::Format_RGB32);
+
+ m_array = array;
+ m_width = w;
+ m_height = h;
+
+ update();
+}
+
+void GLRenderWidgetImplementation::clearFrame()
+{
+ m_frame = QImage();
+ m_array = QByteArray();
+ update();
+}
+
+bool GLRenderWidgetImplementation::hasYUVSupport() const
+{
+ return m_yuvSupport;
+}
+
+static QImage convertFromYUV(const QByteArray &array, int w, int h)
+{
+ QImage result(w, h, QImage::Format_RGB32);
+
+ // TODO: bilinearly interpolate the U and V channels for better result
+
+ for (int y = 0; y < h; ++y) {
+ uint *sp = (uint *)result.scanLine(y);
+
+ const uchar *yp = (const uchar *)(array.constData() + y * w);
+ const uchar *up = (const uchar *)(array.constData() + w * h + (y/2)*(w/2));
+ const uchar *vp = (const uchar *)(array.constData() + w * h * 5/4 + (y/2)*(w/2));
+
+ for (int x = 0; x < w; ++x) {
+ const int sy = *yp;
+ const int su = *up;
+ const int sv = *vp;
+
+ const int R = int(1.164 * (sy - 16) + 1.596 * (sv - 128));
+ const int G = int(1.164 * (sy - 16) - 0.813 * (sv - 128) - 0.391 * (su - 128));
+ const int B = int(1.164 * (sy - 16) + 2.018 * (su - 128));
+
+ *sp = qRgb(qBound(0, R, 255),
+ qBound(0, G, 255),
+ qBound(0, B, 255));
+
+ ++yp;
+ ++sp;
+ if (x & 1) {
+ ++up;
+ ++vp;
+ }
+ }
+ }
+ return result;
+}
+
+const QImage &GLRenderWidgetImplementation::currentFrame() const
+{
+ if (m_frame.isNull() && !m_array.isNull())
+ m_frame = convertFromYUV(m_array, m_width, m_height);
+
+ return m_frame;
+}
+
+#ifndef GL_FRAGMENT_PROGRAM_ARB
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#endif
+
+// arbfp1 fragment program for converting yuv to rgb
+const char *const yuvToRgb =
+ "!!ARBfp1.0"
+ "PARAM c[3] = { { 0.5, 0.0625 },"
+ "{ 1.164, 0, 1.596, 2.0179999 },"
+ "{ 1.164, -0.391, -0.81300002 } };"
+ "TEMP R0;"
+ "TEMP R1;"
+ "TEX R0.x, fragment.texcoord[0], texture[2], 2D;"
+ "ADD R1.z, R0.x, -c[0].x;"
+ "TEX R1.x, fragment.texcoord[0], texture[0], 2D;"
+ "TEX R0.x, fragment.texcoord[0], texture[1], 2D;"
+ "ADD R1.x, R1, -c[0].y;"
+ "ADD R1.y, R0.x, -c[0].x;"
+ "DP3 result.color.x, R1, c[1];"
+ "DP3 result.color.y, R1, c[2];"
+ "DP3 result.color.z, R1, c[1].xwyw;"
+ "END";
+
+GLRenderWidgetImplementation::GLRenderWidgetImplementation(VideoWidget*videoWidget, const QGLFormat &format) :
+ QGLWidget(format, videoWidget)
+ , m_program(0)
+ , m_yuvSupport(false)
+ , m_videoWidget(videoWidget)
+{
+ makeCurrent();
+ glGenTextures(3, m_texture);
+
+ glProgramStringARB = (_glProgramStringARB) context()->getProcAddress(QLatin1String("glProgramStringARB"));
+ glBindProgramARB = (_glBindProgramARB) context()->getProcAddress(QLatin1String("glBindProgramARB"));
+ glDeleteProgramsARB = (_glDeleteProgramsARB) context()->getProcAddress(QLatin1String("glDeleteProgramsARB"));
+ glGenProgramsARB = (_glGenProgramsARB) context()->getProcAddress(QLatin1String("glGenProgramsARB"));
+ glActiveTexture = (_glActiveTexture) context()->getProcAddress(QLatin1String("glActiveTexture"));
+
+ m_hasPrograms = glProgramStringARB && glBindProgramARB && glDeleteProgramsARB && glGenProgramsARB && glActiveTexture;
+
+ if (m_hasPrograms) {
+ glGenProgramsARB(1, &m_program);
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_program);
+
+ const GLbyte *gl_src = reinterpret_cast<const GLbyte *>(yuvToRgb);
+ glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ int(strlen(yuvToRgb)), gl_src);
+
+ if (glGetError() != GL_NO_ERROR) {
+ glDeleteProgramsARB(1, &m_program);
+ m_hasPrograms = false;
+ } else {
+ m_yuvSupport = true;
+ }
+ }
+
+ QPalette palette;
+ palette.setColor(QPalette::Background, Qt::black);
+ setPalette(palette);
+ setAutoFillBackground(true);
+ // Videowidget always have this property to allow hiding the mouse cursor
+ setMouseTracking(true);
+}
+
+void GLRenderWidgetImplementation::updateTexture(const QByteArray &array, int width, int height)
+{
+ m_width = width;
+ m_height = height;
+
+ makeCurrent();
+
+ int w[3] = { width, width/2, width/2 };
+ int h[3] = { height, height/2, height/2 };
+ int offs[3] = { 0, width*height, width*height*5/4 };
+
+ for (int i = 0; i < 3; ++i) {
+ glBindTexture(GL_TEXTURE_2D, m_texture[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w[i], h[i], 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, array.data() + offs[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);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ }
+}
+
+void GLRenderWidgetImplementation::paintEvent(QPaintEvent *)
+{
+ QPainter painter(this);
+ m_drawFrameRect = m_videoWidget->calculateDrawFrameRect();
+ if (m_yuvSupport && frameIsSet()) {
+ glEnable(GL_FRAGMENT_PROGRAM_ARB);
+ glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_program);
+ const float tx_array[] = { 0, 0, 1, 0, 1, 1, 0, 1};
+ const QRectF r = drawFrameRect();
+
+ const float v_array[] = { float(r.left()), float(r.top()), float(r.right()), float(r.top()), float(r.right()), float(r.bottom()), float(r.left()), float(r.bottom()) };
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_texture[0]);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, m_texture[1]);
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, m_texture[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_QUADS, 0, 4);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ glDisable(GL_FRAGMENT_PROGRAM_ARB);
+ } else {
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+ painter.drawImage(drawFrameRect(), currentFrame());
+ }
+
+ frameRendered();
+}
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // QT_OPENGL_ES
+#endif // QT_NO_OPENGL
diff --git a/src/3rdparty/phonon/gstreamer/glrenderer.h b/src/3rdparty/phonon/gstreamer/glrenderer.h
new file mode 100644
index 0000000..68dd141
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/glrenderer.h
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_GLRENDERER_H
+#define Phonon_GSTREAMER_GLRENDERER_H
+
+#include "videowidget.h"
+#include "common.h"
+
+#ifndef QT_NO_OPENGL
+
+#include <QtOpenGL/QGLFormat>
+#include <QtOpenGL/QGLWidget>
+
+#ifndef QT_OPENGL_ES
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+class GLRenderWidgetImplementation;
+
+class GLRenderer : public AbstractRenderer
+{
+public:
+ GLRenderer(VideoWidget *control);
+ ~GLRenderer();
+ void handleMediaNodeEvent(const MediaNodeEvent *event);
+ bool eventFilter(QEvent * event);
+ bool paintsOnWidget() { return false; }
+private:
+ GLRenderWidgetImplementation *m_glWindow;
+};
+
+class GLRenderWidgetImplementation : public QGLWidget
+{
+ Q_OBJECT
+
+ // ARB_fragment_program
+ typedef void (*_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *);
+ typedef void (*_glBindProgramARB) (GLenum, GLuint);
+ typedef void (*_glDeleteProgramsARB) (GLsizei, const GLuint *);
+ typedef void (*_glGenProgramsARB) (GLsizei, GLuint *);
+ typedef void (*_glActiveTexture) (GLenum);
+public:
+ GLRenderWidgetImplementation(VideoWidget *control, const QGLFormat &format);
+ void paintEvent(QPaintEvent *event);
+ GstElement *createVideoSink();
+ void updateTexture(const QByteArray &array, int width, int height);
+ bool hasYUVSupport() const;
+ const QImage& currentFrame() const;
+ QRect drawFrameRect() const { return m_drawFrameRect; }
+ bool frameIsSet() const { return !m_array.isNull(); }
+ void setNextFrame(const QByteArray &array, int width, int height);
+ void clearFrame();
+private:
+ _glProgramStringARB glProgramStringARB;
+ _glBindProgramARB glBindProgramARB;
+ _glDeleteProgramsARB glDeleteProgramsARB;
+ _glGenProgramsARB glGenProgramsARB;
+ _glActiveTexture glActiveTexture;
+
+ mutable QImage m_frame;
+ QByteArray m_array;
+ int m_width;
+ int m_height;
+ QRect m_drawFrameRect;
+ GLuint m_texture[3];
+
+ bool m_hasPrograms;
+ GLuint m_program;
+ bool m_yuvSupport;
+ VideoWidget *m_videoWidget;
+};
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif //QT_OPENGL_ES
+#endif // QT_NO_OPENGL
+
+#endif // Phonon_GSTREAMER_GLRENDERER_H
diff --git a/src/3rdparty/phonon/gstreamer/gsthelper.cpp b/src/3rdparty/phonon/gstreamer/gsthelper.cpp
new file mode 100644
index 0000000..69bb75c
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/gsthelper.cpp
@@ -0,0 +1,170 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gst/interfaces/propertyprobe.h>
+#include <gst/gst.h>
+#include "common.h"
+#include "gsthelper.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+/**
+ * Probes a gstElement for a list of settable string-property values
+ *
+ * @return a QStringList containing a list of allwed string values for the given
+ * element
+ */
+QList<QByteArray> GstHelper::extractProperties(GstElement *elem, const QByteArray &value)
+{
+ Q_ASSERT(elem);
+ QList<QByteArray> list;
+
+ if (GST_IS_PROPERTY_PROBE(elem)) {
+ GstPropertyProbe *probe = GST_PROPERTY_PROBE(elem);
+ const GParamSpec *devspec = 0;
+ GValueArray *array = NULL;
+
+ if ((devspec = gst_property_probe_get_property (probe, value))) {
+ if ((array = gst_property_probe_probe_and_get_values (probe, devspec))) {
+ for (unsigned int device = 0; device < array->n_values; device++) {
+ GValue *deviceId = g_value_array_get_nth (array, device);
+ list.append(g_value_get_string(deviceId));
+ }
+ }
+ if (array)
+ g_value_array_free (array);
+ }
+ }
+ return list;
+}
+
+/**
+ * Sets the string value of a GstElement's property
+ *
+ * @return false if the value could not be set.
+ */
+bool GstHelper::setProperty(GstElement *elem, const char *propertyName, const QByteArray &propertyValue)
+{
+ Q_ASSERT(elem);
+ Q_ASSERT(propertyName && strlen(propertyName));
+
+ if (GST_IS_PROPERTY_PROBE(elem) && gst_property_probe_get_property( GST_PROPERTY_PROBE( elem), propertyName ) ) {
+ g_object_set(G_OBJECT(elem), propertyName, propertyValue.constData(), (const char*)NULL);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Queries an element for the value of an object property
+ */
+QByteArray GstHelper::property(GstElement *elem, const char *propertyName)
+{
+ Q_ASSERT(elem);
+ Q_ASSERT(propertyName && strlen(propertyName));
+ QByteArray retVal;
+
+ if (GST_IS_PROPERTY_PROBE(elem) && gst_property_probe_get_property( GST_PROPERTY_PROBE(elem), propertyName)) {
+ gchar *value = NULL;
+ g_object_get (G_OBJECT(elem), propertyName, &value, (const char*)NULL);
+ retVal = QByteArray(value);
+ g_free (value);
+ }
+ return retVal;
+}
+
+/**
+ * Queries a GstObject for it's name
+ */
+QByteArray GstHelper::name(GstObject *obj)
+{
+ Q_ASSERT(obj);
+ QByteArray retVal;
+ gchar *value = NULL;
+ if ((value = gst_object_get_name (obj))) {
+ retVal = QByteArray(value);
+ g_free (value);
+ }
+ return retVal;
+}
+
+
+/***
+ * Creates an instance of a playbin with "audio-src" and
+ * "video-src" ghost pads to allow redirected output streams.
+ *
+ * ### This function is probably not required now that MediaObject is based
+ * on decodebin directly.
+ */
+GstElement* GstHelper::createPluggablePlaybin()
+{
+ GstElement *playbin = 0;
+ //init playbin and add to our pipeline
+ playbin = gst_element_factory_make("playbin2", NULL);
+
+ //Create an identity element to redirect sound
+ GstElement *audioSinkBin = gst_bin_new (NULL);
+ GstElement *audioPipe = gst_element_factory_make("identity", NULL);
+ gst_bin_add(GST_BIN(audioSinkBin), audioPipe);
+
+ //Create a sinkpad on the identity
+ GstPad *audiopad = gst_element_get_pad (audioPipe, "sink");
+ gst_element_add_pad (audioSinkBin, gst_ghost_pad_new ("sink", audiopad));
+ gst_object_unref (audiopad);
+
+ //Create an "audio_src" source pad on the playbin
+ GstPad *audioPlaypad = gst_element_get_pad (audioPipe, "src");
+ gst_element_add_pad (playbin, gst_ghost_pad_new ("audio_src", audioPlaypad));
+ gst_object_unref (audioPlaypad);
+
+ //Done with our audio redirection
+ g_object_set (G_OBJECT(playbin), "audio-sink", audioSinkBin, (const char*)NULL);
+
+ // * * Redirect video to "video_src" pad : * *
+
+ //Create an identity element to redirect sound
+ GstElement *videoSinkBin = gst_bin_new (NULL);
+ GstElement *videoPipe = gst_element_factory_make("identity", NULL);
+ gst_bin_add(GST_BIN(videoSinkBin), videoPipe);
+
+ //Create a sinkpad on the identity
+ GstPad *videopad = gst_element_get_pad (videoPipe, "sink");
+ gst_element_add_pad (videoSinkBin, gst_ghost_pad_new ("sink", videopad));
+ gst_object_unref (videopad);
+
+ //Create an "audio_src" source pad on the playbin
+ GstPad *videoPlaypad = gst_element_get_pad (videoPipe, "src");
+ gst_element_add_pad (playbin, gst_ghost_pad_new ("video_src", videoPlaypad));
+ gst_object_unref (videoPlaypad);
+
+ //Done with our video redirection
+ g_object_set (G_OBJECT(playbin), "video-sink", videoSinkBin, (const char*)NULL);
+ return playbin;
+}
+
+
+} //namespace Gstreamer
+} //namespace Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/gsthelper.h b/src/3rdparty/phonon/gstreamer/gsthelper.h
new file mode 100644
index 0000000..ff342a4
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/gsthelper.h
@@ -0,0 +1,49 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_GSTHELPER_H
+#define Phonon_GSTREAMER_GSTHELPER_H
+
+#include "common.h"
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+template<class T> class QList;
+class QByteArray;
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+class GstHelper
+{
+public:
+ static QList<QByteArray> extractProperties(GstElement *elem, const QByteArray &value);
+ static bool setProperty(GstElement *elem, const char *propertyName, const QByteArray &propertyValue);
+ static QByteArray property(GstElement *elem, const char *propertyName);
+ static QByteArray name(GstObject *elem);
+ static GstElement* createPluggablePlaybin();
+};
+
+} // ns Gstreamer
+} // ns Phonon
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_GSTHELPER_H
diff --git a/src/3rdparty/phonon/gstreamer/gstreamer.desktop b/src/3rdparty/phonon/gstreamer/gstreamer.desktop
new file mode 100644
index 0000000..0861762
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/gstreamer.desktop
@@ -0,0 +1,108 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=PhononBackend
+MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;application/x-quicktimeplayer;video/mkv;video/msvideo;video/x-msvideo;video/x-flic;audio/x-aiff;audio/aiff;audio/x-pn-aiff;audio/x-realaudio;audio/basic;audio/x-basic;audio/x-pn-au;audio/x-8svx;audio/8svx;audio/x-16sv;audio/168sv;image/x-ilbm;image/ilbm;video/x-anim;video/anim;image/png;image/x-png;video/mng;video/x-mng;audio/x-ogg;audio/x-speex+ogg;application/ogg;application/ogg;audio/vnd.rn-realaudio;audio/x-pn-realaudio-plugin;audio/x-real-audio;application/vnd.rn-realmedia;video/mpeg;video/x-mpeg;audio/x-wav;audio/wav;audio/x-pn-wav;audio/x-pn-windows-acm;audio/mpeg2;audio/x-mpeg2;audio/mpeg3;audio/x-mpeg3;audio/mpeg;audio/x-mpeg;x-mpegurl;audio/x-mpegurl;audio/mp3;audio/mpeg;
+X-KDE-Library=phonon_gstreamer
+X-KDE-PhononBackendInfo-InterfaceVersion=1
+X-KDE-PhononBackendInfo-Version=0.1
+X-KDE-PhononBackendInfo-Website=http://gstreamer.freedesktop.org/
+Icon=phonon-gstreamer
+InitialPreference=10
+
+Name=GStreamer
+Name[bg]=GStreamer
+Name[ca]=GStreamer
+Name[ca@valencia]=GStreamer
+Name[cs]=GStreamer
+Name[da]=GStreamer
+Name[de]=GStreamer
+Name[el]=GStreamer
+Name[en_GB]=GStreamer
+Name[es]=GStreamer
+Name[et]=GStreamer
+Name[eu]=GStreamer
+Name[fi]=GStreamer
+Name[fr]=GStreamer
+Name[ga]=GStreamer
+Name[gl]=GStreamer
+Name[hsb]=GStreamer
+Name[hu]=GStreamer
+Name[id]=GStreamer
+Name[is]=GStreamer
+Name[it]=GStreamer
+Name[ja]=GStreamer
+Name[ko]=GStreamer
+Name[ku]=GStreamer
+Name[lt]=GStreamer
+Name[lv]=GStreamer
+Name[nb]=GStreamer
+Name[nds]=GStreamer
+Name[nl]=GStreamer
+Name[nn]=GStreamer
+Name[pa]=ਜੀਸਟੀਰਮਰ
+Name[pl]=GStreamer
+Name[pt]=GStreamer
+Name[pt_BR]=GStreamer
+Name[ru]=GStreamer
+Name[se]=GStreamer
+Name[sk]=GStreamer
+Name[sl]=GStreamer
+Name[sr]=Гстример
+Name[sr@ijekavian]=Гстример
+Name[sr@ijekavianlatin]=GStreamer
+Name[sr@latin]=GStreamer
+Name[sv]=Gstreamer
+Name[tr]=GStreamer
+Name[uk]=GStreamer
+Name[x-test]=xxGStreamerxx
+Name[zh_CN]=GStreamer
+Name[zh_TW]=GStreamer
+
+Comment=Phonon GStreamer backend
+Comment[bg]=Phonon GStreamer
+Comment[ca]=Dorsal GStreamer del Phonon
+Comment[ca@valencia]=Dorsal GStreamer del Phonon
+Comment[cs]=Phonon GStreamer backend
+Comment[da]=GStreamer-backend til Phonon
+Comment[de]=Phonon-Treiber für GStreamer
+Comment[el]=Σύστημα υποστήριξης GStreamer του Phonon
+Comment[en_GB]=Phonon GStreamer backend
+Comment[es]=Motor GStreamer para Phonon
+Comment[et]=Phononi GStreameri taustaprogramm
+Comment[eu]=Phonon GStreamer backend
+Comment[fi]=Phonon GStreamer-taustaohjelma
+Comment[fr]=Système de gestion GStreamer pour Phonon
+Comment[ga]=Inneall GStreamer le haghaidh Phonon
+Comment[gl]=Infraestrutura de GStreamer para Phonon
+Comment[hsb]=Phonon GStreamer backend
+Comment[hu]=Phonon GStreamer modul
+Comment[id]=Phonon GStreamer backend
+Comment[is]=Phonon GStreamer bakendi
+Comment[it]=Motore Gstreamer di Phonon
+Comment[ja]=Phonon GStreamer バックエンド
+Comment[ko]=Phonon GStreamer 백엔드
+Comment[ku]=Binesaza Phonon GStreamer
+Comment[lt]=Phonon GStreamer galinė sąsaja
+Comment[lv]=Phonon GStreamer aizmugure
+Comment[nb]=Phonon-motor for GStreamer
+Comment[nds]=Phonon-Hülpprogramm GStreamer
+Comment[nl]=GStreamer-backend (Phonon)
+Comment[nn]=Phonon-motor for GStreamer
+Comment[pa]=ਫੋਨੋਨ ਜਸਟੀਰਮਰ ਬੈਕਐਂਡ
+Comment[pl]=Obsługa GStreamera przez Phonon
+Comment[pt]=Infra-estrutura do GStreamer para o Phonon
+Comment[pt_BR]=Infraestrutura Phonon GStreamer
+Comment[ru]=Механизм GStreamer для Phonon
+Comment[se]=Phonon GStreamer duogášmohtor
+Comment[sk]=GStreamer podsystém
+Comment[sl]=Phononova hrbtenica GStreamer
+Comment[sr]=Гстример као позадина Фонона
+Comment[sr@ijekavian]=Гстример као позадина Фонона
+Comment[sr@ijekavianlatin]=GStreamer kao pozadina Phonona
+Comment[sr@latin]=GStreamer kao pozadina Phonona
+Comment[sv]=Phonon Gstreamer-gränssnitt
+Comment[tr]=Phonon GStreamer arka ucu
+Comment[uk]=Сервер GStreamer для Phonon
+Comment[x-test]=xxPhonon GStreamer backendxx
+Comment[zh_CN]=Phonon GStreamer 后端
+Comment[zh_TW]=Phonon GStreamer 後端介面
diff --git a/src/3rdparty/phonon/gstreamer/lgpl-2.1.txt b/src/3rdparty/phonon/gstreamer/lgpl-2.1.txt
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/lgpl-2.1.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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 library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/3rdparty/phonon/gstreamer/lgpl-3.txt b/src/3rdparty/phonon/gstreamer/lgpl-3.txt
new file mode 100644
index 0000000..fc8a5de
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/lgpl-3.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/3rdparty/phonon/gstreamer/medianode.cpp b/src/3rdparty/phonon/gstreamer/medianode.cpp
new file mode 100644
index 0000000..1a84592
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/medianode.cpp
@@ -0,0 +1,456 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "medianode.h"
+#include "mediaobject.h"
+#include "message.h"
+#include "backend.h"
+#include "gsthelper.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+MediaNode::MediaNode(Backend *backend, NodeDescription description) :
+ m_isValid(false),
+ m_root(0),
+ m_audioTee(0),
+ m_videoTee(0),
+ m_fakeAudioSink(0),
+ m_fakeVideoSink(0),
+ m_backend(backend),
+ m_description(description)
+{
+ if ((description & AudioSink) && (description & VideoSink)) {
+ Q_ASSERT(0); // A node cannot accept both audio and video
+ }
+
+ if (description & AudioSource) {
+ m_audioTee = gst_element_factory_make("tee", NULL);
+ gst_object_ref (GST_OBJECT (m_audioTee));
+ gst_object_sink (GST_OBJECT (m_audioTee));
+
+ // Fake audio sink to swallow unconnected audio pads
+ m_fakeAudioSink = gst_element_factory_make("fakesink", NULL);
+ g_object_set (G_OBJECT (m_fakeAudioSink), "sync", TRUE, (const char*)NULL);
+ gst_object_ref (GST_OBJECT (m_fakeAudioSink));
+ gst_object_sink (GST_OBJECT (m_fakeAudioSink));
+ }
+
+ if (description & VideoSource) {
+ m_videoTee = gst_element_factory_make("tee", NULL);
+ gst_object_ref (GST_OBJECT (m_videoTee));
+ gst_object_sink (GST_OBJECT (m_videoTee));
+
+ // Fake video sink to swallow unconnected video pads
+ m_fakeVideoSink = gst_element_factory_make("fakesink", NULL);
+ g_object_set (G_OBJECT (m_fakeVideoSink), "sync", TRUE, (const char*)NULL);
+ gst_object_ref (GST_OBJECT (m_fakeVideoSink));
+ gst_object_sink (GST_OBJECT (m_fakeVideoSink));
+ }
+}
+
+MediaNode::~MediaNode()
+{
+ if (m_videoTee) {
+ gst_element_set_state(m_videoTee, GST_STATE_NULL);
+ gst_object_unref(m_videoTee);
+ }
+
+ if (m_audioTee) {
+ gst_element_set_state(m_audioTee, GST_STATE_NULL);
+ gst_object_unref(m_audioTee);
+ }
+
+ if (m_fakeAudioSink) {
+ gst_element_set_state(m_fakeAudioSink, GST_STATE_NULL);
+ gst_object_unref(m_fakeAudioSink);
+ }
+
+ if (m_fakeVideoSink) {
+ gst_element_set_state(m_fakeVideoSink, GST_STATE_NULL);
+ gst_object_unref(m_fakeVideoSink);
+ }
+}
+
+
+/**
+ * Connects children recursively from a mediaobject root
+ */
+bool MediaNode::buildGraph()
+{
+ Q_ASSERT(root()); //We cannot build the graph without a root element source
+
+ bool success = link();
+
+ if (success) {
+ // connect children recursively
+ for (int i=0; i< m_audioSinkList.size(); ++i) {
+ if (MediaNode *node = qobject_cast<MediaNode*>(m_audioSinkList[i])) {
+ node->setRoot(root());
+ if (!node->buildGraph())
+ success = false;
+ }
+ }
+
+ for (int i=0; i < m_videoSinkList.size(); ++i) {
+ if (MediaNode *node = qobject_cast<MediaNode*>(m_videoSinkList[i])) {
+ node->setRoot(root());
+ if (!node->buildGraph())
+ success = false;
+ }
+ }
+ }
+
+ if (!success)
+ unlink();
+
+ return success;
+}
+
+/**
+ * Disconnects children recursively
+ */
+bool MediaNode::breakGraph()
+{
+ for (int i=0; i<m_audioSinkList.size(); ++i) {
+ MediaNode *node = qobject_cast<MediaNode*>(m_audioSinkList[i]);
+ if (!node || !node->breakGraph())
+ return false;
+ node->setRoot(0);
+ }
+
+ for (int i=0; i <m_videoSinkList.size(); ++i) {
+ MediaNode *node = qobject_cast<MediaNode*>(m_videoSinkList[i]);
+ if (!node || !node->breakGraph())
+ return false;
+ node->setRoot(0);
+ }
+ unlink();
+ return true;
+}
+
+bool MediaNode::connectNode(QObject *obj)
+{
+ MediaNode *sink = qobject_cast<MediaNode*>(obj);
+
+ bool success = false;
+
+ if (sink) {
+
+ if (!sink->isValid()) {
+ m_backend->logMessage(QString("Trying to link to an invalid node (%0)").arg(sink->name()), Backend::Warning);
+ return false;
+ }
+
+ if (sink->root()) {
+ m_backend->logMessage("Trying to link a node that is already linked to a different mediasource ", Backend::Warning);
+ return false;
+ }
+
+ if ((m_description & AudioSource) && (sink->m_description & AudioSink)) {
+ m_audioSinkList << obj;
+ MediaNodeEvent event(MediaNodeEvent::AudioSinkAdded, sink);
+ root()->mediaNodeEvent(&event);
+ success = true;
+ }
+
+ if ((m_description & VideoSource) && (sink->m_description & VideoSink)) {
+ m_videoSinkList << obj;
+ MediaNodeEvent event(MediaNodeEvent::VideoSinkAdded, sink);
+ root()->mediaNodeEvent(&event);
+ success = true;
+ }
+
+ // If we have a root source, and we are connected
+ // try to link the gstreamer elements
+ if (success && root()) {
+ MediaNodeEvent mediaObjectConnected(MediaNodeEvent::MediaObjectConnected, root());
+ notify(&mediaObjectConnected);
+ root()->buildGraph();
+ }
+ }
+ return success;
+}
+
+bool MediaNode::disconnectNode(QObject *obj)
+{
+ MediaNode *sink = qobject_cast<MediaNode*>(obj);
+ if (root()) {
+ // Disconnecting elements while playing or paused seems to cause
+ // potential deadlock. Hence we force the pipeline into ready state
+ // before any nodes are disconnected.
+ gst_element_set_state(root()->pipeline(), GST_STATE_READY);
+
+ Q_ASSERT(sink->root()); //sink has to have a root since it is connected
+
+ if (sink->description() & (AudioSink)) {
+ GstPad *sinkPad = gst_element_get_pad(sink->audioElement(), "sink");
+ // Release requested src pad from tee
+ GstPad *requestedPad = gst_pad_get_peer(sinkPad);
+ if (requestedPad) {
+ gst_element_release_request_pad(m_audioTee, requestedPad);
+ gst_object_unref(requestedPad);
+ }
+ if (GST_ELEMENT_PARENT(sink->audioElement()))
+ gst_bin_remove(GST_BIN(root()->audioGraph()), sink->audioElement());
+ gst_object_unref(sinkPad);
+ }
+
+ if (sink->description() & (VideoSink)) {
+ GstPad *sinkPad = gst_element_get_pad(sink->videoElement(), "sink");
+ // Release requested src pad from tee
+ GstPad *requestedPad = gst_pad_get_peer(sinkPad);
+ if (requestedPad) {
+ gst_element_release_request_pad(m_videoTee, requestedPad);
+ gst_object_unref(requestedPad);
+ }
+ if (GST_ELEMENT_PARENT(sink->videoElement()))
+ gst_bin_remove(GST_BIN(root()->videoGraph()), sink->videoElement());
+ gst_object_unref(sinkPad);
+ }
+
+ sink->breakGraph();
+ sink->setRoot(0);
+ }
+
+ m_videoSinkList.removeAll(obj);
+ m_audioSinkList.removeAll(obj);
+
+ if (sink->m_description & AudioSink) {
+ // Remove sink from graph
+ MediaNodeEvent event(MediaNodeEvent::AudioSinkRemoved, sink);
+ mediaNodeEvent(&event);
+ return true;
+ }
+
+ if ((m_description & VideoSource) && (sink->m_description & VideoSink)) {
+ // Remove sink from graph
+ MediaNodeEvent event(MediaNodeEvent::VideoSinkRemoved, sink);
+ mediaNodeEvent(&event);
+ return true;
+ }
+
+ return false;
+}
+
+void MediaNode::mediaNodeEvent(const MediaNodeEvent *) {}
+
+/**
+ * Propagates an event down the graph
+ * sender is responsible for deleting the event
+ */
+void MediaNode::notify(const MediaNodeEvent *event)
+{
+ Q_ASSERT(event);
+ mediaNodeEvent(event);
+ for (int i=0; i<m_audioSinkList.size(); ++i) {
+ MediaNode *node = qobject_cast<MediaNode*>(m_audioSinkList[i]);
+ node->notify(event);
+ }
+
+ for (int i=0; i<m_videoSinkList.size(); ++i) {
+ MediaNode *node = qobject_cast<MediaNode*>(m_videoSinkList[i]);
+ node->notify(event);
+ }
+}
+
+/*
+ * Requests a new tee pad and connects a node to it
+ */
+bool MediaNode::addOutput(MediaNode *output, GstElement *tee)
+{
+ Q_ASSERT(root());
+
+ bool success = true;
+
+ GstElement *sinkElement = 0;
+ if (output->description() & AudioSink)
+ sinkElement = output->audioElement();
+ else if (output->description() & VideoSink)
+ sinkElement = output->videoElement();
+
+ Q_ASSERT(sinkElement);
+
+ if (!sinkElement)
+ return false;
+
+ GstState state = GST_STATE (root()->pipeline());
+ GstPad *srcPad = gst_element_get_request_pad (tee, "src%d");
+ GstPad *sinkPad = gst_element_get_pad (sinkElement, "sink");
+
+ if (!sinkPad) {
+ success = false;
+ } else if (gst_pad_is_linked(sinkPad)) {
+ gst_object_unref (GST_OBJECT (sinkPad));
+ gst_object_unref (GST_OBJECT (srcPad));
+ return true;
+ }
+
+ if (success) {
+ if (output->description() & AudioSink)
+ gst_bin_add(GST_BIN(root()->audioGraph()), sinkElement);
+ else if (output->description() & VideoSink)
+ gst_bin_add(GST_BIN(root()->videoGraph()), sinkElement);
+ }
+
+ if (success) {
+ gst_pad_link(srcPad, sinkPad);
+ gst_element_set_state(sinkElement, state);
+ } else {
+ gst_element_release_request_pad(tee, srcPad);
+ }
+
+ gst_object_unref (GST_OBJECT (srcPad));
+ gst_object_unref (GST_OBJECT (sinkPad));
+
+ return success;
+}
+
+// Used to seal up unconnected source nodes by connecting unconnected src pads to fake sinks
+bool MediaNode::connectToFakeSink(GstElement *tee, GstElement *sink, GstElement *bin)
+{
+ bool success = true;
+ GstPad *sinkPad = gst_element_get_pad (sink, "sink");
+
+ if (GST_PAD_IS_LINKED (sinkPad)) {
+ //This fakesink is already connected
+ gst_object_unref (sinkPad);
+ return true;
+ }
+
+ GstPad *srcPad = gst_element_get_request_pad (tee, "src%d");
+ gst_bin_add(GST_BIN(bin), sink);
+ if (success)
+ success = (gst_pad_link (srcPad, sinkPad) == GST_PAD_LINK_OK);
+ if (success)
+ success = (gst_element_set_state(sink, GST_STATE(bin)) != GST_STATE_CHANGE_FAILURE);
+ gst_object_unref (srcPad);
+ gst_object_unref (sinkPad);
+ return success;
+}
+
+// Used to seal up unconnected source nodes by connecting unconnected src pads to fake sinks
+bool MediaNode::releaseFakeSinkIfConnected(GstElement *tee, GstElement *fakesink, GstElement *bin)
+{
+ if (GST_ELEMENT_PARENT(fakesink) == GST_ELEMENT(bin)) {
+ GstPad *sinkPad = gst_element_get_pad(fakesink, "sink");
+
+ // Release requested src pad from tee
+ GstPad *requestedPad = gst_pad_get_peer(sinkPad);
+ if (requestedPad) {
+ gst_element_release_request_pad(tee, requestedPad);
+ gst_object_unref(requestedPad);
+ }
+ gst_object_unref(sinkPad);
+
+ gst_element_set_state(fakesink, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(bin), fakesink);
+ Q_ASSERT(!GST_ELEMENT_PARENT(fakesink));
+ }
+ return true;
+}
+
+bool MediaNode::linkMediaNodeList(QList<QObject *> &list, GstElement *bin, GstElement *tee, GstElement *fakesink, GstElement *src)
+{
+ if (!GST_ELEMENT_PARENT(tee)) {
+ gst_bin_add(GST_BIN(bin), tee);
+ if (!gst_element_link_pads(src, "src", tee, "sink"))
+ return false;
+ gst_element_set_state(tee, GST_STATE(bin));
+ }
+ if (list.isEmpty()) {
+ //connect node to a fake sink to avoid clogging the pipeline
+ if (!connectToFakeSink(tee, fakesink, bin))
+ return false;
+ } else {
+ // Remove fake sink if previously connected
+ if (!releaseFakeSinkIfConnected(tee, fakesink, bin))
+ return false;
+
+ for (int i = 0 ; i < list.size() ; ++i) {
+ QObject *sink = list[i];
+ if (MediaNode *output = qobject_cast<MediaNode*>(sink)) {
+ if (!addOutput(output, tee))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool MediaNode::link()
+{
+ // Rewire everything
+ if ((description() & AudioSource)) {
+ if (!linkMediaNodeList(m_audioSinkList, root()->audioGraph(), m_audioTee, m_fakeAudioSink, audioElement()))
+ return false;
+ }
+
+ if ((description() & VideoSource)) {
+ if (!linkMediaNodeList(m_videoSinkList, root()->videoGraph(), m_videoTee, m_fakeVideoSink, videoElement()))
+ return false;
+ }
+ return true;
+}
+
+bool MediaNode::unlink()
+{
+ Q_ASSERT(root());
+ if (description() & AudioSource) {
+ if (GST_ELEMENT_PARENT(m_audioTee) == GST_ELEMENT(root()->audioGraph())) {
+ gst_element_set_state(m_audioTee, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(root()->audioGraph()), m_audioTee);
+ }
+ for (int i=0; i<m_audioSinkList.size(); ++i) {
+ QObject *audioSink = m_audioSinkList[i];
+ if (MediaNode *output = qobject_cast<MediaNode*>(audioSink)) {
+ GstElement *element = output->audioElement();
+ if (GST_ELEMENT_PARENT(element) == GST_ELEMENT(root()->audioGraph())) {
+ gst_element_set_state(element, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(root()->audioGraph()), element);
+ }
+ }
+ }
+ } else if (description() & VideoSource) {
+ if (GST_ELEMENT_PARENT(m_videoTee) == GST_ELEMENT(root()->videoGraph())) {
+ gst_element_set_state(m_videoTee, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(root()->videoGraph()), m_videoTee);
+ }
+ for (int i=0; i <m_videoSinkList.size(); ++i) {
+ QObject *videoSink = m_videoSinkList[i];
+ if (MediaNode *vw = qobject_cast<MediaNode*>(videoSink)) {
+ GstElement *element = vw->videoElement();
+ if (GST_ELEMENT_PARENT(element) == GST_ELEMENT(root()->videoGraph())) {
+ gst_element_set_state(element, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(root()->videoGraph()), element);
+ }
+ }
+ }
+ }
+ return true;
+}
+
+
+} // ns Gstreamer
+} // ns Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/medianode.h b/src/3rdparty/phonon/gstreamer/medianode.h
new file mode 100644
index 0000000..6e3850a
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/medianode.h
@@ -0,0 +1,128 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_MEDIANODE_H
+#define Phonon_GSTREAMER_MEDIANODE_H
+
+#include "common.h"
+#include "medianodeevent.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QSize>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon {
+namespace Gstreamer {
+
+class Message;
+class MediaObject;
+class Backend;
+
+class MediaNode {
+public:
+ enum NodeDescriptionEnum {
+ AudioSource = 0x1,
+ AudioSink = 0x2,
+ VideoSource = 0x4,
+ VideoSink = 0x8
+ };
+ Q_DECLARE_FLAGS(NodeDescription, NodeDescriptionEnum)
+
+ MediaNode(Backend *backend, NodeDescription description);
+
+ virtual ~MediaNode();
+
+ bool connectNode(QObject *other);
+ bool disconnectNode(QObject *other);
+
+ bool buildGraph();
+ bool breakGraph();
+
+ virtual bool link();
+ virtual bool unlink();
+
+ NodeDescription description() const {
+ return m_description;
+ }
+
+ bool isValid() {
+ return m_isValid;
+ }
+
+ MediaObject *root() {
+ return m_root;
+ }
+
+ void setRoot(MediaObject *mediaObject) {
+ m_root = mediaObject;
+ }
+
+ void notify(const MediaNodeEvent *event);
+
+ Backend *backend() {
+ return m_backend;
+ }
+
+ const QString &name() {
+ return m_name;
+ }
+
+ virtual GstElement *audioElement() {
+ return m_audioTee;
+ }
+
+ virtual GstElement *videoElement() {
+ return m_videoTee;
+ }
+
+protected:
+ bool connectToFakeSink(GstElement *tee, GstElement *sink, GstElement *bin);
+ bool releaseFakeSinkIfConnected(GstElement *tee, GstElement *sink, GstElement *bin);
+ bool linkMediaNodeList(QList<QObject *> &list, GstElement *bin, GstElement *tee, GstElement *sink, GstElement *src);
+
+ virtual void mediaNodeEvent(const MediaNodeEvent *event);
+ QList<QObject *> m_audioSinkList;
+ QList<QObject *> m_videoSinkList;
+
+ bool m_isValid;
+ MediaObject *m_root;
+ GstElement *m_audioTee;
+ GstElement *m_videoTee;
+ GstElement *m_fakeAudioSink;
+ GstElement *m_fakeVideoSink;
+ Backend *m_backend;
+ QString m_name;
+
+private:
+ bool addOutput(MediaNode *, GstElement *tee);
+ NodeDescription m_description;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(MediaNode::NodeDescription)
+
+} // ns Gstreamer
+} // ns Phonon
+
+Q_DECLARE_INTERFACE(Phonon::Gstreamer::MediaNode, "org.phonon.gstreamer.MediaNode")
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_MEDIANODE_H
diff --git a/src/3rdparty/phonon/gstreamer/medianodeevent.cpp b/src/3rdparty/phonon/gstreamer/medianodeevent.cpp
new file mode 100644
index 0000000..20560ee
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/medianodeevent.cpp
@@ -0,0 +1,38 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "medianodeevent.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+MediaNodeEvent::MediaNodeEvent(Type type, const void *data) :
+ eventType(type),
+ eventData(data)
+{}
+
+MediaNodeEvent::~MediaNodeEvent()
+{}
+
+}
+} // namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/medianodeevent.h b/src/3rdparty/phonon/gstreamer/medianodeevent.h
new file mode 100644
index 0000000..cacf4a5
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/medianodeevent.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_MEDIANODEEVENT_H
+#define Phonon_GSTREAMER_MEDIANODEEVENT_H
+
+#include "common.h"
+
+#include <QtCore>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+class MediaNodeEvent
+{
+public:
+ enum Type {
+ VideoAvailable,
+ AudioAvailable,
+ SourceChanged,
+ MediaObjectConnected,
+ StateChanged,
+ VideoSinkAdded,
+ VideoSinkRemoved,
+ AudioSinkAdded,
+ AudioSinkRemoved,
+ VideoHandleRequest,
+ VideoSizeChanged
+ };
+
+ MediaNodeEvent(Type type, const void *data = 0);
+ virtual ~MediaNodeEvent();
+
+ inline Type type() const
+ {
+ return eventType;
+ };
+ inline const void* data() const
+ {
+ return eventData;
+ };
+
+private:
+ Type eventType;
+ const void *eventData;
+};
+
+}
+} // namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_MEDIANODEEVENT_H
diff --git a/src/3rdparty/phonon/gstreamer/mediaobject.cpp b/src/3rdparty/phonon/gstreamer/mediaobject.cpp
new file mode 100644
index 0000000..23a60c0
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/mediaobject.cpp
@@ -0,0 +1,1698 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <cmath>
+#include <gst/interfaces/propertyprobe.h>
+#include <gst/pbutils/install-plugins.h>
+#include "common.h"
+#include "mediaobject.h"
+#include "videowidget.h"
+#include "message.h"
+#include "backend.h"
+#include "streamreader.h"
+#include "phononsrc.h"
+#include <QtCore>
+#include <QtCore/QTimer>
+#include <QtCore/QVector>
+#include <QtCore/QFile>
+#include <QtCore/QByteRef>
+#include <QtCore/QStringList>
+#include <QtCore/QEvent>
+#include <QApplication>
+
+#define ABOUT_TO_FINNISH_TIME 2000
+#define MAX_QUEUE_TIME 20 * GST_SECOND
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+MediaObject::MediaObject(Backend *backend, QObject *parent)
+ : QObject(parent)
+ , MediaNode(backend, AudioSource | VideoSource)
+ , m_resumeState(false)
+ , m_oldState(Phonon::LoadingState)
+ , m_oldPos(0)
+ , m_state(Phonon::LoadingState)
+ , m_pendingState(Phonon::LoadingState)
+ , m_tickTimer(new QTimer(this))
+ , m_prefinishMark(0)
+ , m_transitionTime(0)
+ , m_isStream(false)
+ , m_posAtSeek(-1)
+ , m_prefinishMarkReachedNotEmitted(true)
+ , m_aboutToFinishEmitted(false)
+ , m_loading(false)
+ , m_capsHandler(0)
+ , m_datasource(0)
+ , m_decodebin(0)
+ , m_audioPipe(0)
+ , m_videoPipe(0)
+ , m_totalTime(-1)
+ , m_bufferPercent(0)
+ , m_hasVideo(false)
+ , m_videoStreamFound(false)
+ , m_hasAudio(false)
+ , m_seekable(false)
+ , m_atEndOfStream(false)
+ , m_atStartOfStream(false)
+ , m_error(Phonon::NoError)
+ , m_pipeline(0)
+ , m_audioGraph(0)
+ , m_videoGraph(0)
+ , m_previousTickTime(-1)
+ , m_resetNeeded(false)
+ , m_autoplayTitles(true)
+ , m_availableTitles(0)
+ , m_currentTitle(1)
+ , m_pendingTitle(1)
+{
+ qRegisterMetaType<GstCaps*>("GstCaps*");
+ qRegisterMetaType<State>("State");
+
+ static int count = 0;
+ m_name = "MediaObject" + QString::number(count++);
+
+ if (!m_backend->isValid()) {
+ setError(tr("Cannot start playback. \n\nCheck your GStreamer installation and make sure you "
+ "\nhave libgstreamer-plugins-base installed."), Phonon::FatalError);
+ } else {
+ m_root = this;
+ createPipeline();
+ m_backend->addBusWatcher(this);
+ connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
+ }
+ connect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
+ this, SLOT(notifyStateChange(Phonon::State, Phonon::State)));
+
+}
+
+MediaObject::~MediaObject()
+{
+ m_backend->removeBusWatcher(this);
+ if (m_pipeline) {
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ gst_object_unref(m_pipeline);
+ }
+ if (m_audioGraph) {
+ gst_element_set_state(m_audioGraph, GST_STATE_NULL);
+ gst_object_unref(m_audioGraph);
+ }
+ if (m_videoGraph) {
+ gst_element_set_state(m_videoGraph, GST_STATE_NULL);
+ gst_object_unref(m_videoGraph);
+ }
+}
+
+QString stateString(const Phonon::State &state)
+{
+ switch (state) {
+ case Phonon::LoadingState:
+ return QString("LoadingState");
+ case Phonon::StoppedState:
+ return QString("StoppedState");
+ case Phonon::PlayingState:
+ return QString("PlayingState");
+ case Phonon::BufferingState:
+ return QString("BufferingState");
+ case Phonon::PausedState:
+ return QString("PausedState");
+ case Phonon::ErrorState:
+ return QString("ErrorState");
+ }
+ return QString();
+}
+
+void
+pluginInstallationDone( GstInstallPluginsReturn res, gpointer userData )
+{
+ // Nothing inside yet
+ Q_UNUSED(res);
+ Q_UNUSED(userData);
+}
+
+void MediaObject::saveState()
+{
+ //Only first resumeState is respected
+ if (m_resumeState)
+ return;
+
+ if (m_pendingState == Phonon::PlayingState || m_pendingState == Phonon::PausedState) {
+ m_resumeState = true;
+ m_oldState = m_pendingState;
+ m_oldPos = getPipelinePos();
+ }
+}
+
+void MediaObject::resumeState()
+{
+ if (m_resumeState)
+ QMetaObject::invokeMethod(this, "setState", Qt::QueuedConnection, Q_ARG(State, m_oldState));
+}
+
+void MediaObject::newPadAvailable (GstPad *pad)
+{
+ GstCaps *caps;
+ GstStructure *str;
+ caps = gst_pad_get_caps (pad);
+ if (caps) {
+ str = gst_caps_get_structure (caps, 0);
+ QString mediaString(gst_structure_get_name (str));
+
+ if (mediaString.startsWith("video")) {
+ connectVideo(pad);
+ } else if (mediaString.startsWith("audio")) {
+ connectAudio(pad);
+ } else {
+ m_backend->logMessage("Could not connect pad", Backend::Warning);
+ }
+ gst_caps_unref (caps);
+ }
+}
+
+void MediaObject::cb_newpad (GstElement *decodebin,
+ GstPad *pad,
+ gboolean last,
+ gpointer data)
+{
+ Q_UNUSED(decodebin);
+ Q_UNUSED(pad);
+ Q_UNUSED(last);
+ Q_UNUSED(data);
+
+ MediaObject *media = static_cast<MediaObject*>(data);
+ Q_ASSERT(media);
+ media->newPadAvailable(pad);
+}
+
+void MediaObject::noMorePadsAvailable ()
+{
+ if (m_missingCodecs.size() > 0) {
+ bool canPlay = (m_hasAudio || m_videoStreamFound);
+ Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError;
+#ifdef PLUGIN_INSTALL_API
+ GstInstallPluginsContext *ctx = gst_install_plugins_context_new ();
+ gchar *details[2];
+ details[0] = m_missingCodecs[0].toLocal8Bit().data();
+ details[1] = NULL;
+ GstInstallPluginsReturn status;
+
+ status = gst_install_plugins_async( details, ctx, pluginInstallationDone, NULL );
+ gst_install_plugins_context_free ( ctx );
+
+ if ( status != GST_INSTALL_PLUGINS_STARTED_OK )
+ {
+ if( status == GST_INSTALL_PLUGINS_HELPER_MISSING )
+ setError(tr("Missing codec helper script assistant."), Phonon::FatalError );
+ else
+ setError(tr("Plugin codec installation failed for codec: %0")
+ .arg(m_missingCodecs[0].split("|")[3]), error);
+ }
+ m_missingCodecs.clear();
+#else
+ QString codecs = m_missingCodecs.join(", ");
+
+ if (error == Phonon::NormalError && m_hasVideo && !m_videoStreamFound) {
+ m_hasVideo = false;
+ emit hasVideoChanged(false);
+ }
+ setError(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0").arg(codecs), error);
+ m_missingCodecs.clear();
+#endif
+ }
+}
+
+void MediaObject::cb_no_more_pads (GstElement * decodebin, gpointer data)
+{
+ Q_UNUSED(decodebin);
+ MediaObject *media = static_cast<MediaObject*>(data);
+ Q_ASSERT(media);
+ QMetaObject::invokeMethod(media, "noMorePadsAvailable", Qt::QueuedConnection);
+}
+
+typedef void (*Ptr_gst_pb_utils_init)();
+typedef gchar* (*Ptr_gst_pb_utils_get_codec_description)(const GstCaps *);
+
+void MediaObject::cb_unknown_type (GstElement *decodebin, GstPad *pad, GstCaps *caps, gpointer data)
+{
+ Q_UNUSED(decodebin);
+ Q_UNUSED(pad);
+ MediaObject *media = static_cast<MediaObject*>(data);
+ Q_ASSERT(media);
+
+ QString value = "unknown codec";
+
+ // These functions require GStreamer > 0.10.12
+#ifndef QT_NO_LIBRARY
+ static Ptr_gst_pb_utils_init p_gst_pb_utils_init = 0;
+ static Ptr_gst_pb_utils_get_codec_description p_gst_pb_utils_get_codec_description = 0;
+ if (!p_gst_pb_utils_init) {
+ p_gst_pb_utils_init = (Ptr_gst_pb_utils_init)QLibrary::resolve(QLatin1String("gstpbutils-0.10"), 0, "gst_pb_utils_init");
+ p_gst_pb_utils_get_codec_description = (Ptr_gst_pb_utils_get_codec_description)QLibrary::resolve(QLatin1String("gstpbutils-0.10"), 0, "gst_pb_utils_get_codec_description");
+ if (p_gst_pb_utils_init)
+ p_gst_pb_utils_init();
+ }
+ if (p_gst_pb_utils_get_codec_description) {
+ gchar *codecName = NULL;
+ codecName = p_gst_pb_utils_get_codec_description (caps);
+ value = QString::fromUtf8(codecName);
+ g_free (codecName);
+ } else
+#endif //QT_NO_LIBRARY
+ {
+ // For GStreamer versions < 0.10.12
+ GstStructure *str = gst_caps_get_structure (caps, 0);
+ value = QString::fromUtf8(gst_structure_get_name (str));
+
+ }
+
+#ifdef PLUGIN_INSTALL_API
+ QString plugins = QString("gstreamer|0.10|%0|%1|decoder-%2")
+ .arg( qApp->applicationName() )
+ .arg( value )
+ .arg( QString::fromUtf8(gst_caps_to_string (caps) ) );
+ media->addMissingCodecName( plugins );
+#else
+ media->addMissingCodecName( value );
+#endif
+}
+
+static void notifyVideoCaps(GObject *obj, GParamSpec *, gpointer data)
+{
+ GstPad *pad = GST_PAD(obj);
+ GstCaps *caps = gst_pad_get_caps (pad);
+ Q_ASSERT(caps);
+ MediaObject *media = static_cast<MediaObject*>(data);
+
+ // We do not want any more notifications until the source changes
+ g_signal_handler_disconnect(pad, media->capsHandler());
+
+ // setVideoCaps calls loadingComplete(), meaning we cannot call it from
+ // the streaming thread
+ QMetaObject::invokeMethod(media, "setVideoCaps", Qt::QueuedConnection, Q_ARG(GstCaps *, caps));
+}
+
+void MediaObject::setVideoCaps(GstCaps *caps)
+{
+ GstStructure *str;
+ gint width, height;
+
+ if ((str = gst_caps_get_structure (caps, 0))) {
+ if (gst_structure_get_int (str, "width", &width) && gst_structure_get_int (str, "height", &height)) {
+ gint aspectNum = 0;
+ gint aspectDenum = 0;
+ if (gst_structure_get_fraction(str, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) {
+ if (aspectDenum > 0)
+ width = width*aspectNum/aspectDenum;
+ }
+ // Let child nodes know about our new video size
+ QSize size(width, height);
+ MediaNodeEvent event(MediaNodeEvent::VideoSizeChanged, &size);
+ notify(&event);
+ }
+ }
+ gst_caps_unref(caps);
+}
+
+// Adds an element to the pipeline if not previously added
+bool MediaObject::addToPipeline(GstElement *elem)
+{
+ bool success = true;
+ if (!GST_ELEMENT_PARENT(elem)) { // If not already in pipeline
+ success = gst_bin_add(GST_BIN(m_pipeline), elem);
+ }
+ return success;
+}
+
+void MediaObject::connectVideo(GstPad *pad)
+{
+ GstState currentState = GST_STATE(m_pipeline);
+ if (addToPipeline(m_videoGraph)) {
+ GstPad *videopad = gst_element_get_pad (m_videoGraph, "sink");
+ if (!GST_PAD_IS_LINKED (videopad) && (gst_pad_link (pad, videopad) == GST_PAD_LINK_OK)) {
+ gst_element_set_state(m_videoGraph, currentState == GST_STATE_PLAYING ? GST_STATE_PLAYING : GST_STATE_PAUSED);
+ m_videoStreamFound = true;
+ m_backend->logMessage("Video track connected", Backend::Info, this);
+ // Note that the notify::caps _must_ be installed after linking to work with Dapper
+ m_capsHandler = g_signal_connect(pad, "notify::caps", G_CALLBACK(notifyVideoCaps), this);
+
+ if (!m_loading && !m_hasVideo) {
+ m_hasVideo = m_videoStreamFound;
+ emit hasVideoChanged(m_hasVideo);
+ }
+ }
+ gst_object_unref (videopad);
+ } else {
+ m_backend->logMessage("The video stream could not be plugged.", Backend::Info, this);
+ }
+}
+
+void MediaObject::connectAudio(GstPad *pad)
+{
+ GstState currentState = GST_STATE(m_pipeline);
+ if (addToPipeline(m_audioGraph)) {
+ GstPad *audiopad = gst_element_get_pad (m_audioGraph, "sink");
+ if (!GST_PAD_IS_LINKED (audiopad) && (gst_pad_link (pad, audiopad)==GST_PAD_LINK_OK)) {
+ gst_element_set_state(m_audioGraph, currentState == GST_STATE_PLAYING ? GST_STATE_PLAYING : GST_STATE_PAUSED);
+ m_hasAudio = true;
+ m_backend->logMessage("Audio track connected", Backend::Info, this);
+ }
+ gst_object_unref (audiopad);
+ } else {
+ m_backend->logMessage("The audio stream could not be plugged.", Backend::Info, this);
+ }
+}
+
+void MediaObject::cb_pad_added(GstElement *decodebin,
+ GstPad *pad,
+ gpointer data)
+{
+ Q_UNUSED(decodebin);
+ GstPad *decodepad = static_cast<GstPad*>(data);
+ gst_pad_link (pad, decodepad);
+ //gst_object_unref (decodepad);
+}
+
+/**
+ * Create a media source from a given URL.
+ *
+ * returns true if successful
+ */
+bool MediaObject::createPipefromURL(const QUrl &url)
+{
+ // Remove any existing data source
+ if (m_datasource) {
+ gst_bin_remove(GST_BIN(m_pipeline), m_datasource);
+ // m_pipeline has the only ref to datasource
+ m_datasource = 0;
+ }
+
+ // Verify that the uri can be parsed
+ if (!url.isValid()) {
+ m_backend->logMessage(QString("%1 is not a valid URI").arg(url.toString()));
+ return false;
+ }
+
+ // Create a new datasource based on the input URL
+ // add the 'file' scheme if it's missing; the double '/' is needed!
+ QByteArray encoded_cstr_url = (url.scheme() == QLatin1String("") ?
+ "file://" + url.toEncoded() :
+ url.toEncoded());
+ m_datasource = gst_element_make_from_uri(GST_URI_SRC, encoded_cstr_url.constData(), (const char*)NULL);
+ if (!m_datasource)
+ return false;
+
+ // Set the device for MediaSource::Disc
+ if (m_source.type() == MediaSource::Disc) {
+
+ if (g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "device")) {
+ QByteArray mediaDevice = QFile::encodeName(m_source.deviceName());
+ if (!mediaDevice.isEmpty())
+ g_object_set (G_OBJECT (m_datasource), "device", mediaDevice.constData(), (const char*)NULL);
+ }
+
+ // Also Set optical disc speed to 2X for Audio CD
+ if (m_source.discType() == Phonon::Cd
+ && (g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "read-speed"))) {
+ g_object_set (G_OBJECT (m_datasource), "read-speed", 2, (const char*)NULL);
+ m_backend->logMessage(QString("new device speed : 2X"), Backend::Info, this);
+ }
+ }
+
+ /* make HTTP sources send extra headers so we get icecast
+ * metadata in case the stream is an icecast stream */
+ if (encoded_cstr_url.startsWith("http://")
+ && g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "iradio-mode")) {
+ g_object_set (m_datasource, "iradio-mode", TRUE, NULL);
+ m_isStream = true;
+ }
+
+ // Link data source into pipeline
+ gst_bin_add(GST_BIN(m_pipeline), m_datasource);
+ if (!gst_element_link(m_datasource, m_decodebin)) {
+ // For sources with dynamic pads (such as RtspSrc) we need to connect dynamically
+ GstPad *decodepad = gst_element_get_pad (m_decodebin, "sink");
+ g_signal_connect (m_datasource, "pad-added", G_CALLBACK (&cb_pad_added), decodepad);
+ }
+
+ return true;
+}
+
+/**
+ * Create a media source from a media stream
+ *
+ * returns true if successful
+ */
+bool MediaObject::createPipefromStream(const MediaSource &source)
+{
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ // Remove any existing data source
+ if (m_datasource) {
+ gst_bin_remove(GST_BIN(m_pipeline), m_datasource);
+ // m_pipeline has the only ref to datasource
+ m_datasource = 0;
+ }
+
+ m_datasource = GST_ELEMENT(g_object_new(phonon_src_get_type(), NULL));
+ if (!m_datasource)
+ return false;
+
+ StreamReader *streamReader = new StreamReader(source);
+ g_object_set (G_OBJECT (m_datasource), "iodevice", streamReader, (const char*)NULL);
+
+ // Link data source into pipeline
+ gst_bin_add(GST_BIN(m_pipeline), m_datasource);
+ if (!gst_element_link(m_datasource, m_decodebin)) {
+ gst_bin_remove(GST_BIN(m_pipeline), m_datasource);
+ return false;
+ }
+ return true;
+#else //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ Q_UNUSED(source);
+ return false;
+#endif
+}
+
+void MediaObject::createPipeline()
+{
+ m_pipeline = gst_pipeline_new (NULL);
+ gst_object_ref (GST_OBJECT (m_pipeline));
+ gst_object_sink (GST_OBJECT (m_pipeline));
+
+ m_decodebin = gst_element_factory_make ("decodebin2", NULL);
+ g_signal_connect (m_decodebin, "new-decoded-pad", G_CALLBACK (&cb_newpad), this);
+ g_signal_connect (m_decodebin, "unknown-type", G_CALLBACK (&cb_unknown_type), this);
+ g_signal_connect (m_decodebin, "no-more-pads", G_CALLBACK (&cb_no_more_pads), this);
+
+ gst_bin_add(GST_BIN(m_pipeline), m_decodebin);
+
+ // Create a bin to contain the gst elements for this medianode
+
+ // Set up audio graph
+ m_audioGraph = gst_bin_new(NULL);
+ gst_object_ref (GST_OBJECT (m_audioGraph));
+ gst_object_sink (GST_OBJECT (m_audioGraph));
+
+ // Note that these queues are only required for streaming content
+ // And should ideally be created on demand as they will disable
+ // pull-mode access. Also note that the max-size-time are increased to
+ // reduce buffer overruns as these are not gracefully handled at the moment.
+ m_audioPipe = gst_element_factory_make("queue", NULL);
+ g_object_set(G_OBJECT(m_audioPipe), "max-size-time", MAX_QUEUE_TIME, (const char*)NULL);
+ gst_bin_add(GST_BIN(m_audioGraph), m_audioPipe);
+ GstPad *audiopad = gst_element_get_pad (m_audioPipe, "sink");
+ gst_element_add_pad (m_audioGraph, gst_ghost_pad_new ("sink", audiopad));
+ gst_object_unref (audiopad);
+
+ // Set up video graph
+ m_videoGraph = gst_bin_new(NULL);
+ gst_object_ref (GST_OBJECT (m_videoGraph));
+ gst_object_sink (GST_OBJECT (m_videoGraph));
+
+ m_videoPipe = gst_element_factory_make("queue", NULL);
+ g_object_set(G_OBJECT(m_videoPipe), "max-size-time", MAX_QUEUE_TIME, (const char*)NULL);
+ gst_bin_add(GST_BIN(m_videoGraph), m_videoPipe);
+ GstPad *videopad = gst_element_get_pad (m_videoPipe, "sink");
+ gst_element_add_pad (m_videoGraph, gst_ghost_pad_new ("sink", videopad));
+ gst_object_unref (videopad);
+
+ if (m_pipeline && m_decodebin && m_audioGraph && m_videoGraph && m_audioPipe && m_videoPipe)
+ m_isValid = true;
+ else
+ m_backend->logMessage("Could not create pipeline for media object", Backend::Warning);
+}
+
+/**
+ * !reimp
+ */
+State MediaObject::state() const
+{
+ return m_state;
+}
+
+/**
+ * !reimp
+ */
+bool MediaObject::hasVideo() const
+{
+ return m_hasVideo;
+}
+
+/**
+ * !reimp
+ */
+bool MediaObject::isSeekable() const
+{
+ return m_seekable;
+}
+
+/**
+ * !reimp
+ */
+qint64 MediaObject::currentTime() const
+{
+ if (m_resumeState)
+ return m_oldPos;
+
+ switch (state()) {
+ case Phonon::PausedState:
+ case Phonon::BufferingState:
+ case Phonon::PlayingState:
+ return getPipelinePos();
+ case Phonon::StoppedState:
+ case Phonon::LoadingState:
+ return 0;
+ case Phonon::ErrorState:
+ break;
+ }
+ return -1;
+}
+
+/**
+ * !reimp
+ */
+qint32 MediaObject::tickInterval() const
+{
+ return m_tickInterval;
+}
+
+/**
+ * !reimp
+ */
+void MediaObject::setTickInterval(qint32 newTickInterval)
+{
+ m_tickInterval = newTickInterval;
+ if (m_tickInterval <= 0)
+ m_tickTimer->setInterval(50);
+ else
+ m_tickTimer->setInterval(newTickInterval);
+}
+
+/**
+ * !reimp
+ */
+void MediaObject::play()
+{
+ setState(Phonon::PlayingState);
+ m_resumeState = false;
+}
+
+/**
+ * !reimp
+ */
+QString MediaObject::errorString() const
+{
+ return m_errorString;
+}
+
+/**
+ * !reimp
+ */
+Phonon::ErrorType MediaObject::errorType() const
+{
+ return m_error;
+}
+
+/**
+ * Set the current state of the mediaObject.
+ *
+ * !### Note that both Playing and Paused states are set immediately
+ * This should obviously be done in response to actual gstreamer state changes
+ */
+void MediaObject::setState(State newstate)
+{
+ if (!isValid())
+ return;
+
+ if (m_state == newstate)
+ return;
+
+ if (m_loading) {
+ // We are still loading. The state will be requested
+ // when loading has completed.
+ m_pendingState = newstate;
+ return;
+ }
+
+ GstState currentState;
+ gst_element_get_state (m_pipeline, &currentState, NULL, 1000);
+
+ switch (newstate) {
+ case Phonon::BufferingState:
+ m_backend->logMessage("phonon state request: buffering", Backend::Info, this);
+ break;
+
+ case Phonon::PausedState:
+ m_backend->logMessage("phonon state request: paused", Backend::Info, this);
+ if (currentState == GST_STATE_PAUSED) {
+ changeState(Phonon::PausedState);
+ } else if (gst_element_set_state(m_pipeline, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) {
+ m_pendingState = Phonon::PausedState;
+ } else {
+ m_backend->logMessage("phonon state request failed", Backend::Info, this);
+ }
+ break;
+
+ case Phonon::StoppedState:
+ m_backend->logMessage("phonon state request: Stopped", Backend::Info, this);
+ if (currentState == GST_STATE_READY) {
+ changeState(Phonon::StoppedState);
+ } else if (gst_element_set_state(m_pipeline, GST_STATE_READY) != GST_STATE_CHANGE_FAILURE) {
+ m_pendingState = Phonon::StoppedState;
+ } else {
+ m_backend->logMessage("phonon state request failed", Backend::Info, this);
+ }
+ m_atEndOfStream = false;
+ break;
+
+ case Phonon::PlayingState:
+ if (m_resetNeeded) {
+ // ### Note this is a workaround and it should really be gracefully
+ // handled by medianode when we implement live connections.
+ // This generally happens if medianodes have been connected after the MediaSource was set
+ // Note that a side-effect of this is that we resend all meta data.
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ m_resetNeeded = false;
+ // Send a source change so the X11 renderer
+ // will re-set the overlay
+ MediaNodeEvent event(MediaNodeEvent::SourceChanged);
+ notify(&event);
+ }
+ m_backend->logMessage("phonon state request: Playing", Backend::Info, this);
+ if (m_atEndOfStream) {
+ m_backend->logMessage("EOS already reached", Backend::Info, this);
+ } else if (currentState == GST_STATE_PLAYING) {
+ changeState(Phonon::PlayingState);
+ } else if (gst_element_set_state(m_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
+ m_pendingState = Phonon::PlayingState;
+ } else {
+ m_backend->logMessage("phonon state request failed", Backend::Info, this);
+ }
+ break;
+
+ case Phonon::ErrorState:
+ m_backend->logMessage("phonon state request : Error", Backend::Warning, this);
+ m_backend->logMessage(QString("Last error : %0").arg(errorString()) , Backend::Warning, this);
+ changeState(Phonon::ErrorState); //immediately set error state
+ break;
+
+ case Phonon::LoadingState:
+ m_backend->logMessage("phonon state request: Loading", Backend::Info, this);
+ changeState(Phonon::LoadingState);
+ break;
+ }
+}
+
+/*
+ * Signals that the requested state has completed
+ * by emitting stateChanged and updates the internal state.
+ */
+void MediaObject::changeState(State newstate)
+{
+ if (newstate == m_state)
+ return;
+
+ Phonon::State oldState = m_state;
+ m_state = newstate; // m_state must be set before emitting, since
+ // Error state requires that state() will return the new value
+ m_pendingState = newstate;
+ emit stateChanged(newstate, oldState);
+
+ switch (newstate) {
+ case Phonon::PausedState:
+ m_backend->logMessage("phonon state changed: paused", Backend::Info, this);
+ break;
+
+ case Phonon::BufferingState:
+ m_backend->logMessage("phonon state changed: buffering", Backend::Info, this);
+ break;
+
+ case Phonon::PlayingState:
+ m_backend->logMessage("phonon state changed: Playing", Backend::Info, this);
+ break;
+
+ case Phonon::StoppedState:
+ m_backend->logMessage("phonon state changed: Stopped", Backend::Info, this);
+ // We must reset the pipeline when playing again
+ m_resetNeeded = true;
+ m_tickTimer->stop();
+ break;
+
+ case Phonon::ErrorState:
+ m_loading = false;
+ m_backend->logMessage("phonon state changed : Error", Backend::Info, this);
+ m_backend->logMessage(errorString(), Backend::Warning, this);
+ break;
+
+ case Phonon::LoadingState:
+ m_backend->logMessage("phonon state changed: Loading", Backend::Info, this);
+ break;
+ }
+}
+
+void MediaObject::setError(const QString &errorString, Phonon::ErrorType error)
+{
+ m_errorString = errorString;
+ m_error = error;
+ m_tickTimer->stop();
+
+ if (error == Phonon::FatalError) {
+ m_hasVideo = false;
+ emit hasVideoChanged(false);
+ gst_element_set_state(m_pipeline, GST_STATE_READY);
+ changeState(Phonon::ErrorState);
+ } else {
+ if (m_loading) //Flag error only after loading has completed
+ m_pendingState = Phonon::ErrorState;
+ else
+ changeState(Phonon::ErrorState);
+ }
+}
+
+qint64 MediaObject::totalTime() const
+{
+ return m_totalTime;
+}
+
+qint32 MediaObject::prefinishMark() const
+{
+ return m_prefinishMark;
+}
+
+qint32 MediaObject::transitionTime() const
+{
+ return m_transitionTime;
+}
+
+void MediaObject::setTransitionTime(qint32 time)
+{
+ m_transitionTime = time;
+}
+
+qint64 MediaObject::remainingTime() const
+{
+ return totalTime() - currentTime();
+}
+
+MediaSource MediaObject::source() const
+{
+ return m_source;
+}
+
+void MediaObject::setNextSource(const MediaSource &source)
+{
+ if (source.type() == MediaSource::Invalid &&
+ source.type() == MediaSource::Empty)
+ return;
+ m_nextSource = source;
+}
+
+/**
+ * Update total time value from the pipeline
+ */
+bool MediaObject::updateTotalTime()
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration = 0;
+ if (gst_element_query_duration (GST_ELEMENT(m_pipeline), &format, &duration)) {
+ setTotalTime(duration / GST_MSECOND);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Checks if the current source is seekable
+ */
+void MediaObject::updateSeekable()
+{
+ if (!isValid())
+ return;
+
+ GstQuery *query;
+ gboolean result;
+ gint64 start, stop;
+ query = gst_query_new_seeking(GST_FORMAT_TIME);
+ result = gst_element_query (m_pipeline, query);
+ if (result) {
+ gboolean seekable;
+ GstFormat format;
+ gst_query_parse_seeking (query, &format, &seekable, &start, &stop);
+
+ if (m_seekable != seekable) {
+ m_seekable = seekable;
+ emit seekableChanged(m_seekable);
+ }
+
+ if (m_seekable)
+ m_backend->logMessage("Stream is seekable", Backend::Info, this);
+ else
+ m_backend->logMessage("Stream is non-seekable", Backend::Info, this);
+ } else {
+ m_backend->logMessage("updateSeekable query failed", Backend::Info, this);
+ }
+ gst_query_unref (query);
+}
+
+qint64 MediaObject::getPipelinePos() const
+{
+ Q_ASSERT(m_pipeline);
+
+ // Note some formats (usually mpeg) do not allow us to accurately seek to the
+ // beginning or end of the file so we 'fake' it here rather than exposing the front end to potential issues.
+ if (m_atEndOfStream)
+ return totalTime();
+ if (m_atStartOfStream)
+ return 0;
+ if (m_posAtSeek >= 0)
+ return m_posAtSeek;
+
+ gint64 pos = 0;
+ GstFormat format = GST_FORMAT_TIME;
+ gst_element_query_position (GST_ELEMENT(m_pipeline), &format, &pos);
+ return (pos / GST_MSECOND);
+}
+
+/*
+ * Internal method to set a new total time for the media object
+ */
+void MediaObject::setTotalTime(qint64 newTime)
+{
+
+ if (newTime == m_totalTime)
+ return;
+
+ m_totalTime = newTime;
+
+ emit totalTimeChanged(m_totalTime);
+}
+
+/*
+ * !reimp
+ */
+void MediaObject::setSource(const MediaSource &source)
+{
+ if (!isValid())
+ return;
+
+ // We have to reset the state completely here, otherwise
+ // remnants of the old pipeline can result in strangenes
+ // such as failing duration queries etc
+ GstState state;
+ gst_element_set_state(m_pipeline, GST_STATE_NULL);
+ gst_element_get_state(m_pipeline, &state, NULL, 2000);
+
+ m_source = source;
+ emit currentSourceChanged(m_source);
+ m_previousTickTime = -1;
+ m_missingCodecs.clear();
+
+ // Go into to loading state
+ changeState(Phonon::LoadingState);
+ m_loading = true;
+ // IMPORTANT: Honor the m_resetNeeded flag as it currently stands.
+ // See https://qa.mandriva.com/show_bug.cgi?id=56807
+ //m_resetNeeded = false;
+ m_resumeState = false;
+ m_pendingState = Phonon::StoppedState;
+
+ // Make sure we start out unconnected
+ if (GST_ELEMENT_PARENT(m_audioGraph))
+ gst_bin_remove(GST_BIN(m_pipeline), m_audioGraph);
+ if (GST_ELEMENT_PARENT(m_videoGraph))
+ gst_bin_remove(GST_BIN(m_pipeline), m_videoGraph);
+
+ // Clear any existing errors
+ m_aboutToFinishEmitted = false;
+ m_error = NoError;
+ m_errorString.clear();
+
+ m_bufferPercent = 0;
+ m_prefinishMarkReachedNotEmitted = true;
+ m_aboutToFinishEmitted = false;
+ m_hasAudio = false;
+ m_videoStreamFound = false;
+ setTotalTime(-1);
+ m_atEndOfStream = false;
+
+ m_availableTitles = 0;
+ m_pendingTitle = 1;
+ m_currentTitle = 1;
+
+ // Clear existing meta tags
+ m_metaData.clear();
+ m_isStream = false;
+
+ switch (source.type()) {
+ case MediaSource::Url: {
+ if (!createPipefromURL(source.url()))
+ setError(tr("Could not open media source."));
+ }
+ break;
+
+ case MediaSource::LocalFile: {
+ if (!createPipefromURL(QUrl::fromLocalFile(source.fileName())))
+ setError(tr("Could not open media source."));
+ }
+ break;
+
+ case MediaSource::Invalid:
+ setError(tr("Invalid source type."), Phonon::NormalError);
+ break;
+
+ case MediaSource::Empty:
+ break;
+
+ case MediaSource::Stream:
+ if (!createPipefromStream(source))
+ setError(tr("Could not open media source."));
+ break;
+
+ case MediaSource::Disc:
+ {
+ QString mediaUrl;
+ switch (source.discType()) {
+ case Phonon::NoDisc:
+ qWarning() << "I should never get to see a MediaSource that is a disc but doesn't specify which one";
+ return;
+ case Phonon::Cd: // CD tracks can be specified by setting the url in the following way uri=cdda:4
+ mediaUrl = QLatin1String("cdda://");
+ break;
+ case Phonon::Dvd:
+ mediaUrl = QLatin1String("dvd://");
+ break;
+ case Phonon::Vcd:
+ mediaUrl = QLatin1String("vcd://");
+ break;
+ default:
+ qWarning() << "media " << source.discType() << " not implemented";
+ return;
+ }
+ if (mediaUrl.isEmpty() || !createPipefromURL(QUrl(mediaUrl)))
+ setError(tr("Could not open media source."));
+ }
+ break;
+
+ default:
+ m_backend->logMessage("Source type not currently supported", Backend::Warning, this);
+ setError(tr("Could not open media source."), Phonon::NormalError);
+ break;
+ }
+
+ MediaNodeEvent event(MediaNodeEvent::SourceChanged);
+ notify(&event);
+
+ // We need to link this node to ensure that fake sinks are connected
+ // before loading, otherwise the stream will be blocked
+ link();
+ beginLoad();
+}
+
+void MediaObject::beginLoad()
+{
+ if (gst_element_set_state(m_pipeline, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) {
+ m_backend->logMessage("Begin source load", Backend::Info, this);
+ } else {
+ setError(tr("Could not open media source."));
+ }
+}
+
+// Called when we are ready to leave the loading state
+void MediaObject::loadingComplete()
+{
+ if (m_videoStreamFound) {
+ MediaNodeEvent event(MediaNodeEvent::VideoAvailable);
+ notify(&event);
+ }
+ getStreamInfo();
+ m_loading = false;
+
+ setState(m_pendingState);
+ emit metaDataChanged(m_metaData);
+}
+
+void MediaObject::getStreamInfo()
+{
+ updateSeekable();
+ updateTotalTime();
+
+ if (m_videoStreamFound != m_hasVideo) {
+ m_hasVideo = m_videoStreamFound;
+ emit hasVideoChanged(m_hasVideo);
+ }
+
+ if (m_source.discType() == Phonon::Cd) {
+ gint64 titleCount;
+ GstFormat format = gst_format_get_by_nick("track");
+ if (gst_element_query_duration (m_pipeline, &format, &titleCount)) {
+ //check if returned format is still "track",
+ //gstreamer sometimes returns the total time, if tracks information is not available.
+ if (qstrcmp(gst_format_get_name(format), "track") == 0) {
+ int oldAvailableTitles = m_availableTitles;
+ m_availableTitles = (int)titleCount;
+ if (m_availableTitles != oldAvailableTitles) {
+ emit availableTitlesChanged(m_availableTitles);
+ m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this);
+ }
+ }
+ }
+ }
+}
+
+void MediaObject::setPrefinishMark(qint32 newPrefinishMark)
+{
+ m_prefinishMark = newPrefinishMark;
+ if (currentTime() < totalTime() - m_prefinishMark) // not about to finish
+ m_prefinishMarkReachedNotEmitted = true;
+}
+
+void MediaObject::pause()
+{
+ m_backend->logMessage("pause()", Backend::Info, this);
+ if (state() != Phonon::PausedState)
+ setState(Phonon::PausedState);
+ m_resumeState = false;
+}
+
+void MediaObject::stop()
+{
+ if (state() != Phonon::StoppedState) {
+ setState(Phonon::StoppedState);
+ m_prefinishMarkReachedNotEmitted = true;
+ }
+ m_resumeState = false;
+}
+
+void MediaObject::seek(qint64 time)
+{
+ if (!isValid())
+ return;
+
+ if (isSeekable()) {
+ switch (state()) {
+ case Phonon::PlayingState:
+ case Phonon::StoppedState:
+ case Phonon::PausedState:
+ case Phonon::BufferingState:
+ m_backend->logMessage(QString("Seek to pos %0").arg(time), Backend::Info, this);
+
+ if (time <= 0)
+ m_atStartOfStream = true;
+ else
+ m_atStartOfStream = false;
+
+ m_posAtSeek = getPipelinePos();
+ m_tickTimer->stop();
+
+ if (gst_element_seek(m_pipeline, 1.0, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
+ time * GST_MSECOND, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
+ break;
+ case Phonon::LoadingState:
+ case Phonon::ErrorState:
+ return;
+ }
+
+ quint64 current = currentTime();
+ quint64 total = totalTime();
+
+ if (current < total - m_prefinishMark)
+ m_prefinishMarkReachedNotEmitted = true;
+ if (current < total - ABOUT_TO_FINNISH_TIME)
+ m_aboutToFinishEmitted = false;
+ m_atEndOfStream = false;
+ }
+}
+
+void MediaObject::emitTick()
+{
+ if (m_resumeState) {
+ return;
+ }
+
+ qint64 currentTime = getPipelinePos();
+ qint64 totalTime = m_totalTime;
+
+ if (m_tickInterval > 0 && currentTime != m_previousTickTime) {
+ emit tick(currentTime);
+ m_previousTickTime = currentTime;
+ }
+ if (m_state == Phonon::PlayingState) {
+ if (currentTime >= totalTime - m_prefinishMark) {
+ if (m_prefinishMarkReachedNotEmitted) {
+ m_prefinishMarkReachedNotEmitted = false;
+ emit prefinishMarkReached(totalTime - currentTime);
+ }
+ }
+ // Prepare load of next source
+ if (currentTime >= totalTime - ABOUT_TO_FINNISH_TIME) {
+ if (m_source.type() == MediaSource::Disc &&
+ m_autoplayTitles &&
+ m_availableTitles > 1 &&
+ m_currentTitle < m_availableTitles) {
+ m_aboutToFinishEmitted = false;
+ } else if (!m_aboutToFinishEmitted) {
+ m_aboutToFinishEmitted = true; // track is about to finish
+ emit aboutToFinish();
+ }
+ }
+ }
+}
+
+
+/*
+ * Used to iterate through the gst_tag_list and extract values
+ */
+void foreach_tag_function(const GstTagList *list, const gchar *tag, gpointer user_data)
+{
+ TagMap *newData = static_cast<TagMap *>(user_data);
+ QString value;
+ GType type = gst_tag_get_type(tag);
+ switch (type) {
+ case G_TYPE_STRING: {
+ char *str = 0;
+ gst_tag_list_get_string(list, tag, &str);
+ value = QString::fromUtf8(str);
+ g_free(str);
+ }
+ break;
+
+ case G_TYPE_BOOLEAN: {
+ int bval;
+ gst_tag_list_get_boolean(list, tag, &bval);
+ value = QString::number(bval);
+ }
+ break;
+
+ case G_TYPE_INT: {
+ int ival;
+ gst_tag_list_get_int(list, tag, &ival);
+ value = QString::number(ival);
+ }
+ break;
+
+ case G_TYPE_UINT: {
+ unsigned int uival;
+ gst_tag_list_get_uint(list, tag, &uival);
+ value = QString::number(uival);
+ }
+ break;
+
+ case G_TYPE_FLOAT: {
+ float fval;
+ gst_tag_list_get_float(list, tag, &fval);
+ value = QString::number(fval);
+ }
+ break;
+
+ case G_TYPE_DOUBLE: {
+ double dval;
+ gst_tag_list_get_double(list, tag, &dval);
+ value = QString::number(dval);
+ }
+ break;
+
+ default:
+ //qDebug("Unsupported tag type: %s", g_type_name(type));
+ break;
+ }
+
+ QString key = QString(tag).toUpper();
+ QString currVal = newData->value(key);
+ if (!value.isEmpty() && !(newData->contains(key) && currVal == value))
+ newData->insert(key, value);
+}
+
+/**
+ * Triggers playback after a song has completed in the current media queue
+ */
+void MediaObject::beginPlay()
+{
+ setSource(m_nextSource);
+ m_nextSource = MediaSource();
+ m_pendingState = Phonon::PlayingState;
+}
+
+/**
+ * Handle GStreamer bus messages
+ */
+void MediaObject::handleBusMessage(const Message &message)
+{
+
+ if (!isValid())
+ return;
+
+ GstMessage *gstMessage = message.rawMessage();
+ Q_ASSERT(m_pipeline);
+
+ if (m_backend->debugLevel() >= Backend::Debug) {
+ int type = GST_MESSAGE_TYPE(gstMessage);
+ gchar* name = gst_element_get_name(gstMessage->src);
+ QString msgString = QString("Bus: %0 (%1)").arg(gst_message_type_get_name ((GstMessageType)type)).arg(name);
+ g_free(name);
+ m_backend->logMessage(msgString, Backend::Debug, this);
+ }
+
+ switch (GST_MESSAGE_TYPE (gstMessage)) {
+
+ case GST_MESSAGE_EOS:
+ m_backend->logMessage("EOS received", Backend::Info, this);
+ handleEndOfStream();
+ break;
+
+ case GST_MESSAGE_TAG: {
+ GstTagList* tag_list = 0;
+ gst_message_parse_tag(gstMessage, &tag_list);
+ if (tag_list) {
+ TagMap newTags;
+ gst_tag_list_foreach (tag_list, &foreach_tag_function, &newTags);
+ gst_tag_list_free(tag_list);
+
+ // Determine if we should no fake the album/artist tags.
+ // This is a little confusing as we want to fake it on initial
+ // connection where title, album and artist are all missing.
+ // There are however times when we get just other information,
+ // e.g. codec, and so we want to only do clever stuff if we
+ // have a commonly available tag (ORGANIZATION) or we have a
+ // change in title
+ bool fake_it =
+ (m_isStream
+ && ((!newTags.contains("TITLE")
+ && newTags.contains("ORGANIZATION"))
+ || (newTags.contains("TITLE")
+ && m_metaData.value("TITLE") != newTags.value("TITLE")))
+ && !newTags.contains("ALBUM")
+ && !newTags.contains("ARTIST"));
+
+ TagMap oldMap = m_metaData; // Keep a copy of the old one for reference
+
+ // Now we've checked the new data, append any new meta tags to the existing tag list
+ // We cannot use TagMap::iterator as this is a multimap and when streaming data
+ // could in theory be lost.
+ QList<QString> keys = newTags.keys();
+ for (QList<QString>::iterator i = keys.begin(); i != keys.end(); ++i) {
+ QString key = *i;
+ if (m_isStream) {
+ // If we're streaming, we need to remove data in m_metaData
+ // in order to stop it filling up indefinitely (as it's a multimap)
+ m_metaData.remove(key);
+ }
+ QList<QString> values = newTags.values(key);
+ for (QList<QString>::iterator j = values.begin(); j != values.end(); ++j) {
+ QString value = *j;
+ QString currVal = m_metaData.value(key);
+ if (!m_metaData.contains(key) || currVal != value) {
+ m_metaData.insert(key, value);
+ }
+ }
+ }
+
+ m_backend->logMessage("Meta tags found", Backend::Info, this);
+ if (oldMap != m_metaData) {
+ // This is a bit of a hack to ensure that stream metadata is
+ // returned. We get as much as we can from the Shoutcast server's
+ // StreamTitle= header. If further info is decoded from the stream
+ // itself later, then it will overwrite this info.
+ if (m_isStream && fake_it) {
+ m_metaData.remove("ALBUM");
+ m_metaData.remove("ARTIST");
+
+ // Detect whether we want to "fill in the blanks"
+ QString str;
+ if (m_metaData.contains("TITLE"))
+ {
+ str = m_metaData.value("TITLE");
+ int splitpoint;
+ // Check to see if our title matches "%s - %s"
+ // Where neither %s are empty...
+ if ((splitpoint = str.indexOf(" - ")) > 0
+ && str.size() > (splitpoint+3)) {
+ m_metaData.insert("ARTIST", str.left(splitpoint));
+ m_metaData.replace("TITLE", str.mid(splitpoint+3));
+ }
+ } else {
+ str = m_metaData.value("GENRE");
+ if (!str.isEmpty())
+ m_metaData.insert("TITLE", str);
+ else
+ m_metaData.insert("TITLE", "Streaming Data");
+ }
+ if (!m_metaData.contains("ARTIST")) {
+ str = m_metaData.value("LOCATION");
+ if (!str.isEmpty())
+ m_metaData.insert("ARTIST", str);
+ else
+ m_metaData.insert("ARTIST", "Streaming Data");
+ }
+ str = m_metaData.value("ORGANIZATION");
+ if (!str.isEmpty())
+ m_metaData.insert("ALBUM", str);
+ else
+ m_metaData.insert("ALBUM", "Streaming Data");
+ }
+ // As we manipulate the title, we need to recompare
+ // oldMap and m_metaData here...
+ if (oldMap != m_metaData && !m_loading)
+ emit metaDataChanged(m_metaData);
+ }
+ }
+ }
+ break;
+
+ case GST_MESSAGE_STATE_CHANGED : {
+
+ if (gstMessage->src != GST_OBJECT(m_pipeline))
+ return;
+
+ GstState oldState;
+ GstState newState;
+ GstState pendingState;
+ gst_message_parse_state_changed (gstMessage, &oldState, &newState, &pendingState);
+
+ if (newState == pendingState)
+ return;
+
+ m_posAtSeek = -1;
+
+ switch (newState) {
+
+ case GST_STATE_PLAYING :
+ m_atStartOfStream = false;
+ m_backend->logMessage("gstreamer: pipeline state set to playing", Backend::Info, this);
+ m_tickTimer->start();
+ changeState(Phonon::PlayingState);
+ if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) {
+ setTrack(m_pendingTitle);
+ }
+ if (m_resumeState && m_oldState == Phonon::PlayingState) {
+ seek(m_oldPos);
+ m_resumeState = false;
+ }
+ break;
+
+ case GST_STATE_NULL:
+ m_backend->logMessage("gstreamer: pipeline state set to null", Backend::Info, this);
+ m_tickTimer->stop();
+ break;
+
+ case GST_STATE_PAUSED :
+ m_backend->logMessage("gstreamer: pipeline state set to paused", Backend::Info, this);
+ m_tickTimer->start();
+ if (state() == Phonon::LoadingState) {
+ // No_more_pads is not emitted from the decodebin in older versions (0.10.4)
+ noMorePadsAvailable();
+ loadingComplete();
+ } else if (m_resumeState && m_oldState == Phonon::PausedState) {
+ changeState(Phonon::PausedState);
+ m_resumeState = false;
+ break;
+ } else {
+ // A lot of autotests can break if we allow all paused changes through.
+ if (m_pendingState == Phonon::PausedState) {
+ changeState(Phonon::PausedState);
+ }
+ }
+ break;
+
+ case GST_STATE_READY :
+ if (!m_loading && m_pendingState == Phonon::StoppedState)
+ changeState(Phonon::StoppedState);
+ m_backend->logMessage("gstreamer: pipeline state set to ready", Backend::Debug, this);
+ m_tickTimer->stop();
+ if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) {
+ setTrack(m_pendingTitle);
+ }
+ break;
+
+ case GST_STATE_VOID_PENDING :
+ m_backend->logMessage("gstreamer: pipeline state set to pending (void)", Backend::Debug, this);
+ m_tickTimer->stop();
+ break;
+ }
+ break;
+ }
+
+ case GST_MESSAGE_ERROR: {
+ gchar *debug;
+ GError *err;
+ QString logMessage;
+ gst_message_parse_error (gstMessage, &err, &debug);
+ gchar *errorMessage = gst_error_get_message (err->domain, err->code);
+ logMessage.sprintf("Error: %s Message:%s (%s) Code:%d", debug, err->message, errorMessage, err->code);
+ m_backend->logMessage(logMessage, Backend::Warning);
+ g_free(errorMessage);
+ g_free (debug);
+
+ if (err->domain == GST_RESOURCE_ERROR) {
+ if (err->code == GST_RESOURCE_ERROR_NOT_FOUND) {
+ setError(tr("Could not locate media source."), Phonon::FatalError);
+ } else if (err->code == GST_RESOURCE_ERROR_OPEN_READ) {
+ setError(tr("Could not open media source."), Phonon::FatalError);
+ } else if (err->code == GST_RESOURCE_ERROR_BUSY) {
+ // We need to check if this comes from an audio device by looking at sink caps
+ GstPad* sinkPad = gst_element_get_static_pad(GST_ELEMENT(gstMessage->src), "sink");
+ if (sinkPad) {
+ GstCaps *caps = gst_pad_get_caps (sinkPad);
+ GstStructure *str = gst_caps_get_structure (caps, 0);
+ if (g_strrstr (gst_structure_get_name (str), "audio"))
+ setError(tr("Could not open audio device. The device is already in use."), Phonon::NormalError);
+ else
+ setError(err->message, Phonon::FatalError);
+ gst_caps_unref (caps);
+ gst_object_unref (sinkPad);
+ }
+ } else {
+ setError(QString(err->message), Phonon::FatalError);
+ }
+ } else if (err->domain == GST_STREAM_ERROR) {
+ switch (err->code) {
+ case GST_STREAM_ERROR_WRONG_TYPE:
+ case GST_STREAM_ERROR_TYPE_NOT_FOUND:
+ setError(tr("Could not decode media source."), Phonon::FatalError);
+ break;
+ default:
+ setError(tr("Could not open media source."), Phonon::FatalError);
+ break;
+ }
+ } else {
+ setError(QString(err->message), Phonon::FatalError);
+ }
+ g_error_free (err);
+ break;
+ }
+
+ case GST_MESSAGE_WARNING: {
+ gchar *debug;
+ GError *err;
+ gst_message_parse_warning(gstMessage, &err, &debug);
+ QString msgString;
+ msgString.sprintf("Warning: %s\nMessage:%s", debug, err->message);
+ m_backend->logMessage(msgString, Backend::Warning);
+ g_free (debug);
+ g_error_free (err);
+ break;
+ }
+
+ case GST_MESSAGE_ELEMENT: {
+ GstMessage *gstMessage = message.rawMessage();
+ const GstStructure *gstStruct = gst_message_get_structure(gstMessage); //do not free this
+ if (g_strrstr (gst_structure_get_name (gstStruct), "prepare-xwindow-id")) {
+ MediaNodeEvent videoHandleEvent(MediaNodeEvent::VideoHandleRequest);
+ notify(&videoHandleEvent);
+ }
+ break;
+ }
+
+ case GST_MESSAGE_DURATION: {
+ m_backend->logMessage("GST_MESSAGE_DURATION", Backend::Debug, this);
+ updateTotalTime();
+ break;
+ }
+
+ case GST_MESSAGE_BUFFERING: {
+ gint percent = 0;
+ gst_structure_get_int (gstMessage->structure, "buffer-percent", &percent); //gst_message_parse_buffering was introduced in 0.10.11
+
+ if (m_bufferPercent != percent) {
+ emit bufferStatus(percent);
+ m_backend->logMessage(QString("Stream buffering %0").arg(percent), Backend::Debug, this);
+ m_bufferPercent = percent;
+ }
+
+ if (m_state != Phonon::BufferingState)
+ emit stateChanged(m_state, Phonon::BufferingState);
+ else if (percent == 100)
+ emit stateChanged(Phonon::BufferingState, m_state);
+ break;
+ }
+ //case GST_MESSAGE_INFO:
+ //case GST_MESSAGE_STREAM_STATUS:
+ //case GST_MESSAGE_CLOCK_PROVIDE:
+ //case GST_MESSAGE_NEW_CLOCK:
+ //case GST_MESSAGE_STEP_DONE:
+ //case GST_MESSAGE_LATENCY: only from 0.10.12
+ //case GST_MESSAGE_ASYNC_DONE: only from 0.10.13
+ default:
+ break;
+ }
+}
+
+void MediaObject::handleEndOfStream()
+{
+ // If the stream is not seekable ignore
+ // otherwise chained radio broadcasts would stop
+
+
+ if (m_atEndOfStream)
+ return;
+
+ if (!m_seekable)
+ m_atEndOfStream = true;
+
+ if (m_source.type() == MediaSource::Disc &&
+ m_autoplayTitles &&
+ m_availableTitles > 1 &&
+ m_currentTitle < m_availableTitles) {
+ _iface_setCurrentTitle(m_currentTitle + 1);
+ return;
+ }
+
+ if (m_nextSource.type() != MediaSource::Invalid
+ && m_nextSource.type() != MediaSource::Empty) { // We only emit finish when the queue is actually empty
+ QTimer::singleShot (qMax(0, transitionTime()), this, SLOT(beginPlay()));
+ } else {
+ m_pendingState = Phonon::PausedState;
+ emit finished();
+ if (!m_seekable) {
+ setState(Phonon::StoppedState);
+ // Note the behavior for live streams is not properly defined
+ // But since we cant seek to 0, we don't have much choice other than stopping
+ // the stream
+ } else {
+ // Only emit paused if the finished signal
+ // did not result in a new state
+ if (m_pendingState == Phonon::PausedState)
+ setState(m_pendingState);
+ }
+ }
+}
+
+void MediaObject::invalidateGraph()
+{
+ m_resetNeeded = true;
+ if (m_state == Phonon::PlayingState || m_state == Phonon::PausedState) {
+ changeState(Phonon::StoppedState);
+ }
+}
+
+// Notifes the pipeline about state changes in the media object
+void MediaObject::notifyStateChange(Phonon::State newstate, Phonon::State oldstate)
+{
+ Q_UNUSED(oldstate);
+ MediaNodeEvent event(MediaNodeEvent::StateChanged, &newstate);
+ notify(&event);
+}
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+//interface management
+bool MediaObject::hasInterface(Interface iface) const
+{
+ return iface == AddonInterface::TitleInterface;
+}
+
+QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> &params)
+{
+ if (hasInterface(iface)) {
+
+ switch (iface)
+ {
+ case TitleInterface:
+ switch (command)
+ {
+ case availableTitles:
+ return _iface_availableTitles();
+ case title:
+ return _iface_currentTitle();
+ case setTitle:
+ _iface_setCurrentTitle(params.first().toInt());
+ break;
+ case autoplayTitles:
+ return m_autoplayTitles;
+ case setAutoplayTitles:
+ m_autoplayTitles = params.first().toBool();
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QVariant();
+}
+#endif
+
+int MediaObject::_iface_availableTitles() const
+{
+ return m_availableTitles;
+}
+
+int MediaObject::_iface_currentTitle() const
+{
+ return m_currentTitle;
+}
+
+void MediaObject::_iface_setCurrentTitle(int title)
+{
+ m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this);
+ if ((title == m_currentTitle) || (title == m_pendingTitle))
+ return;
+
+ m_pendingTitle = title;
+
+ if (m_state == Phonon::PlayingState || m_state == Phonon::StoppedState) {
+ setTrack(m_pendingTitle);
+ } else {
+ setState(Phonon::StoppedState);
+ }
+}
+
+void MediaObject::setTrack(int title)
+{
+ if (((m_state != Phonon::PlayingState) && (m_state != Phonon::StoppedState)) || (title < 1) || (title > m_availableTitles))
+ return;
+
+
+ //let's seek to the beginning of the song
+ GstFormat trackFormat = gst_format_get_by_nick("track");
+ m_backend->logMessage(QString("setTrack %0").arg(title), Backend::Info, this);
+ if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, title - 1)) {
+ m_currentTitle = title;
+ updateTotalTime();
+ m_atEndOfStream = false;
+ emit titleChanged(title);
+ emit totalTimeChanged(totalTime());
+ }
+}
+
+} // ns Gstreamer
+} // ns Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_mediaobject.cpp"
diff --git a/src/3rdparty/phonon/gstreamer/mediaobject.h b/src/3rdparty/phonon/gstreamer/mediaobject.h
new file mode 100644
index 0000000..d588ffc
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/mediaobject.h
@@ -0,0 +1,294 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_MEDIAOBJECT_H
+#define Phonon_GSTREAMER_MEDIAOBJECT_H
+
+#include "backend.h"
+#include "common.h"
+#include "medianode.h"
+#include <phonon/mediaobjectinterface.h>
+#include <phonon/addoninterface.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtCore/QObject>
+#include <QtCore/QDate>
+#include <QtCore/QEvent>
+#include <QtCore/QUrl>
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTimer;
+typedef QMultiMap<QString, QString> TagMap;
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class VideoWidget;
+class AudioPath;
+class VideoPath;
+class AudioOutput;
+
+class MediaObject : public QObject, public MediaObjectInterface
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ , public AddonInterface
+#endif
+ , public MediaNode
+{
+ friend class Stream;
+ friend class AudioDataOutput;
+ Q_OBJECT
+ Q_INTERFACES(Phonon::MediaObjectInterface
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ Phonon::AddonInterface
+#endif
+ Phonon::Gstreamer::MediaNode
+ )
+
+public:
+
+ MediaObject(Backend *backend, QObject *parent);
+ ~MediaObject();
+ Phonon::State state() const;
+
+ bool hasVideo() const;
+ bool isSeekable() const;
+
+ qint64 currentTime() const;
+ qint32 tickInterval() const;
+
+ void setTickInterval(qint32 newTickInterval);
+
+ void play();
+ void pause();
+ void stop();
+ void seek(qint64 time);
+
+ QString errorString() const;
+ Phonon::ErrorType errorType() const;
+
+ QUrl url() const;
+ qint64 totalTime() const;
+
+ qint32 prefinishMark() const;
+ void setPrefinishMark(qint32 newPrefinishMark);
+
+ qint32 transitionTime() const;
+ void setTransitionTime(qint32);
+ qint64 remainingTime() const;
+
+ void setSource(const MediaSource &source);
+ void setNextSource(const MediaSource &source);
+ MediaSource source() const;
+
+ // No additional interfaces currently supported
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ bool hasInterface(Interface) const;
+ QVariant interfaceCall(Interface, int, const QList<QVariant> &);
+#endif
+ bool isLoading()
+ {
+ return m_loading;
+ }
+
+ bool audioAvailable()
+ {
+ return m_hasAudio;
+ }
+
+ bool videoAvailable()
+ {
+ return m_hasVideo;
+ }
+
+ GstElement *audioGraph()
+ {
+ return m_audioGraph;
+ }
+
+ GstElement *videoGraph()
+ {
+ return m_videoGraph;
+ }
+
+ GstElement *pipeline()
+ {
+ return m_pipeline;
+ };
+
+ gulong capsHandler()
+ {
+ return m_capsHandler;
+ };
+
+ void connectVideo(GstPad *videoPad);
+ void connectAudio(GstPad *audioPad);
+ void handleBusMessage(const Message &msg);
+ void handleEndOfStream();
+ void addMissingCodecName(const QString &codec) { m_missingCodecs.append(codec); }
+ void invalidateGraph();
+
+ static void cb_newpad (GstElement *decodebin, GstPad *pad, gboolean last, gpointer data);
+ static void cb_pad_added (GstElement *decodebin, GstPad *pad, gpointer data);
+ static void cb_unknown_type (GstElement *decodebin, GstPad *pad, GstCaps *caps, gpointer data);
+ static void cb_no_more_pads (GstElement * decodebin, gpointer data);
+ void saveState();
+ void resumeState();
+
+public Q_SLOTS:
+ void setState(State);
+
+Q_SIGNALS:
+ void currentSourceChanged(const MediaSource &newSource);
+ void stateChanged(Phonon::State newstate, Phonon::State oldstate);
+ void tick(qint64 time);
+ void metaDataChanged(QMultiMap<QString, QString>);
+ void seekableChanged(bool);
+ void hasVideoChanged(bool);
+
+ void finished();
+ void prefinishMarkReached(qint32);
+ void aboutToFinish();
+ void totalTimeChanged(qint64 length);
+ void bufferStatus(int percentFilled);
+
+ QMultiMap<QString, QString> metaData();
+ void setMetaData(QMultiMap<QString, QString> newData);
+
+ // AddonInterface:
+ void titleChanged(int);
+ void availableTitlesChanged(int);
+
+ // Not implemented
+ void chapterChanged(int);
+ void availableChaptersChanged(int);
+ void angleChanged(int);
+ void availableAnglesChanged(int);
+
+ void availableSubtitlesChanged();
+ void availableAudioChannelsChanged();
+
+protected:
+ void beginLoad();
+ void loadingComplete();
+ void newPadAvailable (GstPad *pad);
+ void changeState(State);
+ void setError(const QString &errorString, Phonon::ErrorType error = NormalError);
+ /*
+ * @param encodedUrl percent-encoded QString for source compat reasons. Should change to QUrl
+ */
+ bool createPipefromURL(const QUrl &url);
+ bool createPipefromStream(const MediaSource &);
+
+private Q_SLOTS:
+ void noMorePadsAvailable();
+ void getStreamInfo();
+ void emitTick();
+ void beginPlay();
+ void setVideoCaps(GstCaps *caps);
+ void notifyStateChange(Phonon::State newstate, Phonon::State oldstate);
+protected:
+ GstElement *audioElement()
+ {
+ Q_ASSERT(m_audioPipe);
+ return m_audioPipe;
+ }
+
+ GstElement *videoElement()
+ {
+ Q_ASSERT(m_videoPipe);
+ return m_videoPipe;
+ }
+
+private:
+
+ // GStreamer specific :
+ void createPipeline();
+ bool addToPipeline(GstElement *elem);
+ void setTotalTime(qint64 newTime);
+ void getStreamsInfo();
+ bool updateTotalTime();
+ void updateSeekable();
+ qint64 getPipelinePos() const;
+
+ int _iface_availableTitles() const;
+ int _iface_currentTitle() const;
+ void _iface_setCurrentTitle(int title);
+ void setTrack(int title);
+
+ bool m_resumeState;
+ State m_oldState;
+ quint64 m_oldPos;
+
+ State m_state;
+ State m_pendingState;
+ QTimer *m_tickTimer;
+ qint32 m_tickInterval;
+
+ MediaSource m_source;
+ MediaSource m_nextSource;
+ qint32 m_prefinishMark;
+ qint32 m_transitionTime;
+ bool m_isStream;
+
+ qint64 m_posAtSeek;
+
+ bool m_prefinishMarkReachedNotEmitted;
+ bool m_aboutToFinishEmitted;
+ bool m_loading;
+ gulong m_capsHandler;
+
+ GstElement *m_datasource;
+ GstElement *m_decodebin;
+
+ GstElement *m_audioPipe;
+ GstElement *m_videoPipe;
+
+ qint64 m_totalTime;
+ int m_bufferPercent;
+ bool m_hasVideo;
+ bool m_videoStreamFound;
+ bool m_hasAudio;
+ bool m_seekable;
+ bool m_atEndOfStream;
+ bool m_atStartOfStream;
+ Phonon::ErrorType m_error;
+ QString m_errorString;
+
+ GstElement *m_pipeline;
+ GstElement *m_audioGraph;
+ GstElement *m_videoGraph;
+ int m_previousTickTime;
+ bool m_resetNeeded;
+ QStringList m_missingCodecs;
+ QMultiMap<QString, QString> m_metaData;
+ bool m_autoplayTitles;
+ int m_availableTitles;
+ int m_currentTitle;
+ int m_pendingTitle;
+};
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_MEDIAOBJECT_H
diff --git a/src/3rdparty/phonon/gstreamer/message.cpp b/src/3rdparty/phonon/gstreamer/message.cpp
new file mode 100644
index 0000000..154e0bb
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/message.cpp
@@ -0,0 +1,75 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gst/gst.h>
+
+#include "message.h"
+
+
+QT_BEGIN_NAMESPACE
+
+static int wuchi = qRegisterMetaType<Phonon::Gstreamer::Message>();
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+/*!
+ \class gstreamer::Message
+ \internal
+*/
+Message::Message():
+ m_message(0),
+ m_source(0)
+{}
+
+Message::Message(GstMessage* message, MediaObject *source):
+ m_message(message),
+ m_source(source)
+{
+ Q_ASSERT(m_message);
+ gst_message_ref(m_message);
+}
+
+Message::Message(const Message &other)
+{
+ m_message = other.m_message;
+ gst_message_ref(m_message);
+ m_source = other.m_source;
+}
+
+Message::~Message()
+{
+ gst_message_unref(m_message);
+}
+
+GstMessage* Message::rawMessage() const
+{
+ return m_message;
+}
+
+MediaObject *Message::source() const
+{
+ return m_source;
+}
+
+} // ns gstreamer
+} // ns phonon
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/gstreamer/message.h b/src/3rdparty/phonon/gstreamer/message.h
new file mode 100644
index 0000000..cadb948
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/message.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_MESSAGE_H
+#define Phonon_GSTREAMER_MESSAGE_H
+
+#include "common.h"
+
+#include <QtCore/QMetaType>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class MediaObject;
+class Message
+{
+public:
+ Message();
+ Message(GstMessage* message, MediaObject *source);
+ ~Message();
+
+ GstMessage* rawMessage() const;
+ MediaObject *source() const;
+ Message(const Message &other);
+
+private:
+ GstMessage* m_message;
+ MediaObject *m_source;
+};
+
+} // ns gstreamer
+} // ns phonon
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Phonon::Gstreamer::Message)
+
+#endif // Phonon_GSTREAMER_MESSAGE_H
diff --git a/src/3rdparty/phonon/gstreamer/phononsrc.cpp b/src/3rdparty/phonon/gstreamer/phononsrc.cpp
new file mode 100644
index 0000000..97d7220
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/phononsrc.cpp
@@ -0,0 +1,285 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesrc.h>
+#include "phononsrc.h"
+#include "streamreader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+static GstStaticPadTemplate srctemplate =
+ GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC (phonon_src_debug);
+
+// PhononSrc args
+enum
+{
+ ARG_0,
+ ARG_PHONONSRC
+};
+
+static void phonon_src_finalize (GObject * object);
+
+static void phonon_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void phonon_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static gboolean phonon_src_start (GstBaseSrc * basesrc);
+static gboolean phonon_src_stop (GstBaseSrc * basesrc);
+
+static gboolean phonon_src_is_seekable (GstBaseSrc * src);
+static gboolean phonon_src_get_size (GstBaseSrc * src, guint64 * size);
+static GstFlowReturn phonon_src_create (GstBaseSrc * src, guint64 offset,
+ guint length, GstBuffer ** buffer);
+
+static void _do_init (GType filesrc_type)
+{
+ Q_UNUSED(filesrc_type);
+ GST_DEBUG_CATEGORY_INIT (phonon_src_debug, "phononsrc", 0, "QIODevice element");
+}
+
+GST_BOILERPLATE_FULL (PhononSrc, phonon_src, GstBaseSrc, GST_TYPE_BASE_SRC, _do_init)
+
+// Register element details
+static void phonon_src_base_init (gpointer g_class) {
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ static gchar longname[] = "Phonon Stream Source",
+ klass[] = "Source/File",
+ description[] = "Read from a Phonon StreamInterface",
+ author[] = "Nokia Corporation and/or its subsidiary(-ies) <qt-info@nokia.com>";
+ GstElementDetails details = GST_ELEMENT_DETAILS (longname,
+ klass,
+ description,
+ author);
+ gst_element_class_set_details (gstelement_class, &details);
+ gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate));
+}
+
+static void phonon_src_class_init (PhononSrcClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSrcClass *gstbasesrc_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gstelement_class = GST_ELEMENT_CLASS (klass);
+ gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
+
+ gobject_class->set_property = phonon_src_set_property;
+ gobject_class->get_property = phonon_src_get_property;
+
+ g_object_class_install_property (gobject_class, ARG_PHONONSRC,
+ g_param_spec_pointer ("iodevice", "A Phonon StreamReader",
+ "A Phonon::GStreamer::StreamReader to read from", GParamFlags(G_PARAM_READWRITE)));
+
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (phonon_src_finalize);
+
+ gstbasesrc_class->start = GST_DEBUG_FUNCPTR (phonon_src_start);
+ gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (phonon_src_stop);
+ gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (phonon_src_is_seekable);
+ gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (phonon_src_get_size);
+ gstbasesrc_class->create = GST_DEBUG_FUNCPTR (phonon_src_create);
+}
+
+static void phonon_src_init (PhononSrc * src, PhononSrcClass * g_class)
+{
+ Q_UNUSED(g_class);
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ src->device = 0;
+#else
+ Q_UNUSED(src);
+#endif
+}
+
+static void phonon_src_finalize (GObject * object)
+{
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ PhononSrc *src;
+ src = GST_PHONON_SRC (object);
+ delete src->device;
+ src->device = 0;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+static gboolean phonon_src_set_device(PhononSrc * src, StreamReader* device)
+{
+ GstState state;
+ // The element must be stopped in order to do this
+ GST_OBJECT_LOCK (src);
+ state = GST_STATE (src);
+
+ if (state != GST_STATE_READY && state != GST_STATE_NULL)
+ goto wrong_state;
+
+ GST_OBJECT_UNLOCK (src);
+
+ src->device = device;
+ g_object_notify (G_OBJECT (src), "iodevice");
+ return TRUE;
+
+ // Error
+wrong_state:
+ {
+ //GST_DEBUG_OBJECT (src, "setting location in wrong state");
+ GST_OBJECT_UNLOCK (src);
+ return FALSE;
+ }
+}
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+static void phonon_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ PhononSrc *src;
+ g_return_if_fail (GST_IS_PHONON_SRC (object));
+ src = GST_PHONON_SRC (object);
+
+ switch (prop_id) {
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ case ARG_PHONONSRC:
+ {
+ StreamReader *dev = (StreamReader*)(g_value_get_pointer(value));
+ if (dev)
+ phonon_src_set_device(src, dev);
+ break;
+ }
+#else
+ Q_UNUSED(value);
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void phonon_src_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ PhononSrc *src;
+ g_return_if_fail (GST_IS_PHONON_SRC (object));
+ src = GST_PHONON_SRC (object);
+
+ switch (prop_id) {
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ case ARG_PHONONSRC:
+ g_value_set_pointer(value, src->device);
+ break;
+#else //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ Q_UNUSED(value);
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstFlowReturn phonon_src_create_read (PhononSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
+{
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ Q_ASSERT(src->device);
+ if (!src->device)
+ return GST_FLOW_ERROR;
+
+ GstBuffer *buf = gst_buffer_new_and_alloc (length);
+ GST_BUFFER_SIZE (buf) = length;
+ GST_BUFFER_OFFSET (buf) = offset;
+ GST_BUFFER_OFFSET_END (buf) = offset + length;
+
+ bool success = src->device->read(offset, length, (char*)GST_BUFFER_DATA (buf));
+ //GST_LOG_OBJECT (src, "Reading %d bytes", length);
+
+ if (success) {
+ *buffer = buf;
+ return GST_FLOW_OK;
+ }
+
+ gst_mini_object_unref(GST_MINI_OBJECT(buf));
+ return GST_FLOW_ERROR;
+#else //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ Q_UNUSED(src);
+ Q_UNUSED(offset);
+ Q_UNUSED(length);
+ Q_UNUSED(buffer);
+ return GST_FLOW_ERROR;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+}
+
+static GstFlowReturn phonon_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
+{
+ PhononSrc *src;
+ GstFlowReturn ret;
+ src = GST_PHONON_SRC (basesrc);
+ ret = phonon_src_create_read (src, offset, length, buffer);
+ return ret;
+}
+
+static gboolean phonon_src_is_seekable (GstBaseSrc * basesrc)
+{
+ PhononSrc *src = GST_PHONON_SRC (basesrc);
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (src->device)
+ return src->device->streamSeekable();
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ return false;
+}
+
+static gboolean phonon_src_get_size (GstBaseSrc * basesrc, guint64 * size)
+{
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ PhononSrc *src;
+ src = GST_PHONON_SRC (basesrc);
+ if (src->device && src->device->streamSeekable()) {
+ *size = src->device->streamSize();
+ return TRUE;
+ }
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ *size = 0;
+ return FALSE;
+}
+
+// Necessary to go to READY state
+static gboolean phonon_src_start (GstBaseSrc * basesrc)
+{
+ Q_UNUSED(basesrc);
+ // Opening the device is handled by the frontend
+ // We can only assume it is already open
+ return TRUE;
+}
+
+static gboolean phonon_src_stop (GstBaseSrc * basesrc)
+{
+ Q_UNUSED(basesrc);
+ // Closing the device is handled by the frontend
+ return TRUE;
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/phononsrc.h b/src/3rdparty/phonon/gstreamer/phononsrc.h
new file mode 100644
index 0000000..a50f8a2
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/phononsrc.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __PHONON_SRC_H__
+#define __PHONON_SRC_H__
+
+#include <sys/types.h>
+#include <gst/gst.h>
+#include <gst/base/gstbasesrc.h>
+#include "streamreader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_PHONON_SRC \
+ (phonon_src_get_type())
+#define GST_PHONON_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PHONON_SRC,PhononSrc))
+#define GST_PHONON_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PHONON_SRC,PhononSrcClass))
+#define GST_IS_PHONON_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PHONON_SRC))
+#define GST_IS_PHONON_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PHONON_SRC))
+
+typedef struct _PhononSrc PhononSrc;
+typedef struct _PhononSrcClass PhononSrcClass;
+
+// PhononSrc:
+struct _PhononSrc {
+ GstBaseSrc element;
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ StreamReader *device;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+};
+
+struct _PhononSrcClass {
+ GstBaseSrcClass parent_class;
+};
+
+GType phonon_src_get_type (void);
+
+G_END_DECLS
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+
+#endif // __PHONON_SRC_H__
diff --git a/src/3rdparty/phonon/gstreamer/qwidgetvideosink.cpp b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.cpp
new file mode 100644
index 0000000..89d5a9d
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.cpp
@@ -0,0 +1,221 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QApplication>
+#include "videowidget.h"
+#include "qwidgetvideosink.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+static GstVideoSinkClass* parentClass;
+
+/*!
+ \class gstreamer::QWidgetVideoSink
+ \internal
+*/
+
+template <VideoFormat FMT>
+GstCaps* QWidgetVideoSink<FMT>::get_caps(GstBaseSink* sink)
+{
+ Q_UNUSED(sink);
+ return 0;
+}
+
+template <>
+const char* QWidgetVideoSinkClass<VideoFormat_YUV>::get_name()
+{
+ return "QWidgetVideoSinkYUV";
+}
+
+template <>
+const char* QWidgetVideoSinkClass<VideoFormat_RGB>::get_name()
+{
+ return "QWidgetVideoSinkRGB";
+}
+
+template <VideoFormat FMT>
+gboolean QWidgetVideoSink<FMT>::set_caps(GstBaseSink* sink, GstCaps* caps)
+{
+ GstStructure* data;
+ QWidgetVideoSink<FMT> *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass<FMT>::get_type(), QWidgetVideoSink<FMT>);
+
+ data = gst_caps_get_structure(caps, 0);
+
+ gst_structure_get_int(data, "width", &self->width);
+ gst_structure_get_int(data, "height", &self->height);
+ gst_structure_get_int(data, "bpp", &self->bpp);
+ gst_structure_get_int(data, "depth", &self->depth);
+ return TRUE;
+}
+
+template <VideoFormat FMT>
+GstStateChangeReturn QWidgetVideoSink<FMT>::change_state(GstElement* element, GstStateChange transition)
+{
+ return GST_ELEMENT_CLASS(parentClass)->change_state(element, transition);
+}
+
+template <VideoFormat FMT>
+GstFlowReturn QWidgetVideoSink<FMT>::render(GstBaseSink* sink, GstBuffer* buf)
+{
+ GstFlowReturn rc = GST_FLOW_OK;
+
+ if (buf != 0)
+ {
+ QWidgetVideoSink<FMT> *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass<FMT>::get_type(), QWidgetVideoSink<FMT>);
+ QByteArray frame;
+ frame.resize(buf->size);
+ memcpy(frame.data(), buf->data, buf->size);
+ NewFrameEvent *frameEvent = new NewFrameEvent(frame, self->width, self->height);
+ QApplication::postEvent(self->renderWidget, frameEvent);
+ }
+ else
+ rc = GST_FLOW_ERROR;
+ return rc;
+}
+
+static GstStaticPadTemplate template_factory_yuv =
+ GST_STATIC_PAD_TEMPLATE("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS("video/x-raw-yuv, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ],"
+ "bpp = (int) 32"));
+
+static GstStaticPadTemplate template_factory_rgb =
+ 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 ],"
+ "bpp = (int) 32"));
+
+template <VideoFormat FMT>
+struct template_factory;
+
+
+template <>
+struct template_factory<VideoFormat_YUV>
+{
+ static GstStaticPadTemplate *getFactory()
+ {
+ return &template_factory_yuv;
+ }
+};
+
+template <>
+struct template_factory<VideoFormat_RGB>
+{
+ static GstStaticPadTemplate *getFactory()
+ {
+ return &template_factory_rgb;
+ }
+};
+
+template <VideoFormat FMT>
+void QWidgetVideoSink<FMT>::base_init(gpointer g_class)
+{
+ gst_element_class_add_pad_template(GST_ELEMENT_CLASS(g_class),
+ gst_static_pad_template_get(template_factory<FMT>::getFactory()));
+}
+
+template <VideoFormat FMT>
+void QWidgetVideoSink<FMT>::instance_init(GTypeInstance *instance, gpointer g_class)
+{
+ Q_UNUSED(g_class);
+
+ QWidgetVideoSink<FMT>* self = reinterpret_cast<QWidgetVideoSink<FMT>*>(instance);
+
+ self->renderWidget = 0;
+ self->width = 0;
+ self->height = 0;
+ self->bpp = 0;
+ self->depth = 0;
+}
+
+// QWidgetVideoSinkClass
+template <VideoFormat FMT>
+void QWidgetVideoSinkClass<FMT>::class_init(gpointer g_class, gpointer class_data)
+{
+ Q_UNUSED(class_data);
+ GstBaseSinkClass* gstBaseSinkClass = (GstBaseSinkClass*)g_class;
+ GstElementClass* gstElementClass = (GstElementClass*)g_class;
+
+ parentClass = reinterpret_cast<GstVideoSinkClass*>(g_type_class_peek_parent(g_class));
+
+ // base
+ gstBaseSinkClass->set_caps = QWidgetVideoSink<FMT>::set_caps;
+ gstBaseSinkClass->preroll = QWidgetVideoSink<FMT>::render;
+ gstBaseSinkClass->render = QWidgetVideoSink<FMT>::render;
+
+ // element
+ gstElementClass->change_state = QWidgetVideoSink<FMT>::change_state;
+}
+
+template <VideoFormat FMT>
+GType QWidgetVideoSinkClass<FMT>::get_type()
+{
+ static GType type = 0;
+
+ if (type == 0)
+ {
+ static const GTypeInfo info =
+ {
+ sizeof(QWidgetVideoSinkClass<FMT>), // class_size
+ QWidgetVideoSink<FMT>::base_init, // base init
+ NULL, // base_finalize
+
+ QWidgetVideoSinkClass<FMT>::class_init, // class_init
+ NULL, // class_finalize
+ NULL, // class_data
+
+ sizeof(QWidgetVideoSink<FMT>), // instance_size
+ 0, // n_preallocs
+ QWidgetVideoSink<FMT>::instance_init, // instance_init
+ 0 // value_table
+ };
+
+ type = g_type_register_static(GST_TYPE_VIDEO_SINK,
+ QWidgetVideoSinkClass<FMT>::get_name(),
+ &info,
+ GTypeFlags(0));
+ }
+ return type;
+}
+
+GType get_type_YUV()
+{
+ return QWidgetVideoSinkClass<VideoFormat_YUV>::get_type();
+}
+
+GType get_type_RGB()
+{
+ return QWidgetVideoSinkClass<VideoFormat_RGB>::get_type();
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h
new file mode 100644
index 0000000..f83dba5
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_VIDEOSINK_H
+#define Phonon_GSTREAMER_VIDEOSINK_H
+
+#include "common.h"
+#include "qwidgetvideosink.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QEvent>
+
+#include <gst/video/gstvideosink.h>
+
+QT_BEGIN_NAMESPACE
+
+class NewFrameEvent : public QEvent
+{
+public:
+ NewFrameEvent(const QByteArray &newFrame, int w, int h) :
+ QEvent(QEvent::User),
+ frame(newFrame),
+ width(w),
+ height(h)
+ {
+ }
+
+ QByteArray frame;
+ int width;
+ int height;
+};
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+enum VideoFormat {
+ VideoFormat_YUV,
+ VideoFormat_RGB
+};
+
+class QWidgetVideoSinkBase
+{
+public:
+ GstVideoSink videoSink;
+
+ QWidget * renderWidget;
+ gint width;
+ gint height;
+ gint bpp;
+ gint depth;
+};
+
+template <VideoFormat FMT>
+class QWidgetVideoSink : public QWidgetVideoSinkBase
+{
+public:
+ static GstCaps* get_caps(GstBaseSink* sink);
+ static gboolean set_caps(GstBaseSink* sink, GstCaps* caps);
+ static GstStateChangeReturn change_state(GstElement* element, GstStateChange transition);
+ static GstFlowReturn render(GstBaseSink* sink, GstBuffer* buf);
+ static void base_init(gpointer g_class);
+ static void instance_init(GTypeInstance *instance, gpointer g_class);
+};
+
+template <VideoFormat FMT>
+struct QWidgetVideoSinkClass
+{
+ GstVideoSinkClass parent_class;
+ static void class_init(gpointer g_class, gpointer class_data);
+ static GType get_type();
+ static const char* get_name();
+};
+
+GType get_type_YUV();
+GType get_type_RGB();
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_VIDEOSINK_H
diff --git a/src/3rdparty/phonon/gstreamer/streamreader.cpp b/src/3rdparty/phonon/gstreamer/streamreader.cpp
new file mode 100644
index 0000000..f8219e6
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/streamreader.cpp
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "streamreader.h"
+#include <QtCore/QMutex>
+#include <phonon/streaminterface.h>
+
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+bool StreamReader::read(quint64 pos, int length, char * buffer)
+{
+ if (currentPos() - currentBufferSize() != pos) {
+ if (!streamSeekable())
+ return false;
+ setCurrentPos(pos);
+ }
+
+ while (currentBufferSize() < length) {
+ int oldSize = currentBufferSize();
+ needData();
+ if (oldSize == currentBufferSize())
+ return false; // We didn't get any data
+ }
+
+ qMemCopy(buffer, m_buffer.data(), length);
+ //truncate the buffer
+ m_buffer = m_buffer.mid(pos);
+ return true;
+}
+
+}
+}
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/gstreamer/streamreader.h b/src/3rdparty/phonon/gstreamer/streamreader.h
new file mode 100644
index 0000000..387370c
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/streamreader.h
@@ -0,0 +1,100 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_IODEVICEREADER_H
+#define PHONON_IODEVICEREADER_H
+
+#include <phonon/mediasource.h>
+#include <phonon/streaminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+ class MediaSource;
+ namespace Gstreamer
+ {
+ class StreamReader : public Phonon::StreamInterface
+ {
+ public:
+
+ StreamReader(const Phonon::MediaSource &source)
+ : m_pos(0)
+ , m_size(0)
+ , m_seekable(false)
+ {
+ connectToSource(source);
+ }
+
+ int currentBufferSize() const
+ {
+ return m_buffer.size();
+ }
+
+ void writeData(const QByteArray &data) {
+ m_pos += data.size();
+ m_buffer += data;
+ }
+
+ void setCurrentPos(qint64 pos)
+ {
+ m_pos = pos;
+ seekStream(pos);
+ m_buffer.clear();
+ }
+
+ quint64 currentPos() const
+ {
+ return m_pos;
+ }
+
+ bool read(quint64 offset, int length, char * buffer);
+
+ void endOfData() {}
+
+ void setStreamSize(qint64 newSize) {
+ m_size = newSize;
+ }
+
+ qint64 streamSize() const {
+ return m_size;
+ }
+
+ void setStreamSeekable(bool s) {
+ m_seekable = s;
+ }
+
+ bool streamSeekable() const {
+ return m_seekable;
+ }
+
+private:
+ QByteArray m_buffer;
+ quint64 m_pos;
+ quint64 m_size;
+ bool m_seekable;
+ };
+ }
+}
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/gstreamer/videowidget.cpp b/src/3rdparty/phonon/gstreamer/videowidget.cpp
new file mode 100644
index 0000000..a4c6f79
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/videowidget.cpp
@@ -0,0 +1,393 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "videowidget.h"
+#include <QtCore/QEvent>
+#include <QtGui/QResizeEvent>
+#include <QtGui/QPalette>
+#include <QtGui/QImage>
+#include <QtGui/QPainter>
+#include <QtGui/QBoxLayout>
+#include <QApplication>
+#include <gst/gst.h>
+#include <gst/interfaces/propertyprobe.h>
+#include "mediaobject.h"
+#include "message.h"
+#include "common.h"
+
+#include "glrenderer.h"
+#include "widgetrenderer.h"
+#ifdef Q_WS_X11
+#include "x11renderer.h"
+#endif
+
+#ifndef QT_NO_PHONON_VIDEO
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+VideoWidget::VideoWidget(Backend *backend, QWidget *parent) :
+ QWidget(parent),
+ MediaNode(backend, VideoSink),
+ m_videoBin(0),
+ m_renderer(0),
+ m_aspectRatio(Phonon::VideoWidget::AspectRatioAuto),
+ m_brightness(0.0),
+ m_hue(0.0),
+ m_contrast(0.0),
+ m_saturation(0.0),
+ m_scaleMode(Phonon::VideoWidget::FitInView),
+ m_videoBalance(0),
+ m_colorspace(0),
+ m_videoplug(0)
+{
+ setupVideoBin();
+}
+
+VideoWidget::~VideoWidget()
+{
+ if (m_videoBin) {
+ gst_element_set_state (m_videoBin, GST_STATE_NULL);
+ gst_object_unref (m_videoBin);
+ }
+
+ if (m_renderer)
+ delete m_renderer;
+}
+
+
+void VideoWidget::setupVideoBin()
+{
+
+ m_renderer = m_backend->deviceManager()->createVideoRenderer(this);
+ GstElement *videoSink = m_renderer->videoSink();
+
+ m_videoBin = gst_bin_new (NULL);
+ Q_ASSERT(m_videoBin);
+ gst_object_ref (GST_OBJECT (m_videoBin)); //Take ownership
+ gst_object_sink (GST_OBJECT (m_videoBin));
+
+ //The videoplug element is the final element before the pluggable videosink
+ m_videoplug = gst_element_factory_make ("identity", NULL);
+
+ //Colorspace ensures that the output of the stream matches the input format accepted by our video sink
+ m_colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+
+ //Video scale is used to prepare the correct aspect ratio and scale.
+ GstElement *videoScale = gst_element_factory_make ("videoscale", NULL);
+
+ //We need a queue to support the tee from parent node
+ GstElement *queue = gst_element_factory_make ("queue", NULL);
+
+ if (queue && m_videoBin && videoScale && m_colorspace && videoSink && m_videoplug) {
+ //Ensure that the bare essentials are prepared
+ gst_bin_add_many (GST_BIN (m_videoBin), queue, m_colorspace, m_videoplug, videoScale, videoSink, (const char*)NULL);
+ bool success = false;
+ //Video balance controls color/sat/hue in the YUV colorspace
+ m_videoBalance = gst_element_factory_make ("videobalance", NULL);
+ if (m_videoBalance) {
+ // For video balance to work we have to first ensure that the video is in YUV colorspace,
+ // then hand it off to the videobalance filter before finally converting it back to RGB.
+ // Hence we nede a videoFilter to convert the colorspace before and after videobalance
+ GstElement *m_colorspace2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
+ gst_bin_add_many(GST_BIN(m_videoBin), m_videoBalance, m_colorspace2, (const char*)NULL);
+ success = gst_element_link_many(queue, m_colorspace, m_videoBalance, m_colorspace2, videoScale, m_videoplug, videoSink, (const char*)NULL);
+ } else {
+ //If video balance is not available, just connect to sink directly
+ success = gst_element_link_many(queue, m_colorspace, videoScale, m_videoplug, videoSink, (const char*)NULL);
+ }
+
+ if (success) {
+ GstPad *videopad = gst_element_get_pad (queue, "sink");
+ gst_element_add_pad (m_videoBin, gst_ghost_pad_new ("sink", videopad));
+ gst_object_unref (videopad);
+#ifndef Q_WS_QPA
+ QWidget *parentWidget = qobject_cast<QWidget*>(parent());
+ if (parentWidget)
+ parentWidget->winId(); // Due to some existing issues with alien in 4.4,
+ // we must currently force the creation of a parent widget.
+#endif
+ m_isValid = true; //initialization ok, accept input
+ }
+ }
+}
+
+void VideoWidget::paintEvent(QPaintEvent *event)
+{
+ Q_ASSERT(m_renderer);
+ m_renderer->handlePaint(event);
+}
+
+void VideoWidget::setVisible(bool val) {
+ Q_ASSERT(m_renderer);
+
+ // Disable overlays for graphics view
+ if (root() && window() && window()->testAttribute(Qt::WA_DontShowOnScreen) && !m_renderer->paintsOnWidget()) {
+ m_backend->logMessage(QString("Widget rendering forced"), Backend::Info, this);
+ GstElement *videoSink = m_renderer->videoSink();
+ Q_ASSERT(videoSink);
+
+ gst_element_set_state (videoSink, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(m_videoBin), videoSink);
+ delete m_renderer;
+ m_renderer = 0;
+
+ // Use widgetRenderer as a fallback
+ m_renderer = new WidgetRenderer(this);
+ videoSink = m_renderer->videoSink();
+ gst_bin_add(GST_BIN(m_videoBin), videoSink);
+ gst_element_link(m_videoplug, videoSink);
+ gst_element_set_state (videoSink, GST_STATE_PAUSED);
+
+ // Request return to current state
+ root()->invalidateGraph();
+ root()->setState(root()->state());
+ }
+ QWidget::setVisible(val);
+}
+
+bool VideoWidget::event(QEvent *event)
+{
+ if (m_renderer && m_renderer->eventFilter(event))
+ return true;
+ return QWidget::event(event);
+}
+
+Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
+{
+ return m_aspectRatio;
+}
+
+QSize VideoWidget::sizeHint() const
+{
+ if (!m_movieSize.isEmpty())
+ return m_movieSize;
+ else
+ return QSize(640, 480);
+}
+
+void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio)
+{
+ m_aspectRatio = aspectRatio;
+ if (m_renderer)
+ m_renderer->aspectRatioChanged(aspectRatio);
+}
+
+Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
+{
+ return m_scaleMode;
+}
+
+QRect VideoWidget::scaleToAspect(QRect srcRect, int w, int h) const
+{
+ float width = srcRect.width();
+ float height = srcRect.width() * (float(h) / float(w));
+ if (height > srcRect.height()) {
+ height = srcRect.height();
+ width = srcRect.height() * (float(w) / float(h));
+ }
+ return QRect(0, 0, (int)width, (int)height);
+}
+
+/***
+ * Calculates the actual rectangle the movie will be presented with
+ **/
+QRect VideoWidget::calculateDrawFrameRect() const
+{
+ QRect widgetRect = rect();
+ QRect drawFrameRect;
+ // Set m_drawFrameRect to be the size of the smallest possible
+ // rect conforming to the aspect and containing the whole frame:
+ switch (aspectRatio()) {
+
+ case Phonon::VideoWidget::AspectRatioWidget:
+ drawFrameRect = widgetRect;
+ // No more calculations needed.
+ return drawFrameRect;
+
+ case Phonon::VideoWidget::AspectRatio4_3:
+ drawFrameRect = scaleToAspect(widgetRect, 4, 3);
+ break;
+
+ case Phonon::VideoWidget::AspectRatio16_9:
+ drawFrameRect = scaleToAspect(widgetRect, 16, 9);
+ break;
+
+ case Phonon::VideoWidget::AspectRatioAuto:
+ default:
+ drawFrameRect = QRect(0, 0, movieSize().width(), movieSize().height());
+ break;
+ }
+
+ // Scale m_drawFrameRect to fill the widget
+ // without breaking aspect:
+ float widgetWidth = widgetRect.width();
+ float widgetHeight = widgetRect.height();
+ float frameWidth = widgetWidth;
+ float frameHeight = drawFrameRect.height() * float(widgetWidth) / float(drawFrameRect.width());
+
+ switch (scaleMode()) {
+ case Phonon::VideoWidget::ScaleAndCrop:
+ if (frameHeight < widgetHeight) {
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ case Phonon::VideoWidget::FitInView:
+ default:
+ if (frameHeight > widgetHeight) {
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ }
+ drawFrameRect.setSize(QSize(int(frameWidth), int(frameHeight)));
+ drawFrameRect.moveTo(int((widgetWidth - frameWidth) / 2.0f),
+ int((widgetHeight - frameHeight) / 2.0f));
+ return drawFrameRect;
+}
+
+void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+{
+ m_scaleMode = scaleMode;
+ if (m_renderer)
+ m_renderer->scaleModeChanged(scaleMode);
+}
+
+qreal VideoWidget::brightness() const
+{
+ return m_brightness;
+}
+
+qreal clampedValue(qreal val)
+{
+ if (val > 1.0 )
+ return 1.0;
+ else if (val < -1.0)
+ return -1.0;
+ else return val;
+}
+
+void VideoWidget::setBrightness(qreal newValue)
+{
+ newValue = clampedValue(newValue);
+
+ if (newValue == m_brightness)
+ return;
+
+ m_brightness = newValue;
+
+ if (m_videoBalance)
+ g_object_set(G_OBJECT(m_videoBalance), "brightness", newValue, (const char*)NULL); //gstreamer range is [-1, 1]
+
+}
+
+qreal VideoWidget::contrast() const
+{
+ return m_contrast;
+}
+
+void VideoWidget::setContrast(qreal newValue)
+{
+ newValue = clampedValue(newValue);
+
+ if (newValue == m_contrast)
+ return;
+
+ m_contrast = newValue;
+
+ if (m_videoBalance)
+ g_object_set(G_OBJECT(m_videoBalance), "contrast", (newValue + 1.0), (const char*)NULL); //gstreamer range is [0-2]
+}
+
+qreal VideoWidget::hue() const
+{
+ return m_hue;
+}
+
+void VideoWidget::setHue(qreal newValue)
+{
+ if (newValue == m_hue)
+ return;
+
+ newValue = clampedValue(newValue);
+
+ m_hue = newValue;
+
+ if (m_videoBalance)
+ g_object_set(G_OBJECT(m_videoBalance), "hue", newValue, (const char*)NULL); //gstreamer range is [-1, 1]
+}
+
+qreal VideoWidget::saturation() const
+{
+ return m_saturation;
+}
+
+void VideoWidget::setSaturation(qreal newValue)
+{
+ newValue = clampedValue(newValue);
+
+ if (newValue == m_saturation)
+ return;
+
+ m_saturation = newValue;
+
+ if (m_videoBalance)
+ g_object_set(G_OBJECT(m_videoBalance), "saturation", newValue + 1.0, (const char*)NULL); //gstreamer range is [0, 2]
+}
+
+
+void VideoWidget::setMovieSize(const QSize &size)
+{
+ m_backend->logMessage(QString("New video size %0 x %1").arg(size.width()).arg(size.height()), Backend::Info);
+ if (size == m_movieSize)
+ return;
+ m_movieSize = size;
+ widget()->updateGeometry();
+ widget()->update();
+
+ if (m_renderer)
+ m_renderer->movieSizeChanged(m_movieSize);
+}
+
+void VideoWidget::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()) {
+ case MediaNodeEvent::VideoSizeChanged: {
+ const QSize *size = static_cast<const QSize*>(event->data());
+ setMovieSize(*size);
+ }
+ break;
+ default:
+ break;
+ }
+
+ // Forward events to renderer
+ if (m_renderer)
+ m_renderer->handleMediaNodeEvent(event);
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_VIDEO
+
+#include "moc_videowidget.cpp"
diff --git a/src/3rdparty/phonon/gstreamer/videowidget.h b/src/3rdparty/phonon/gstreamer/videowidget.h
new file mode 100644
index 0000000..8603f6a
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/videowidget.h
@@ -0,0 +1,108 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2 //Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).007 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_VIDEOWIDGET_H
+#define Phonon_GSTREAMER_VIDEOWIDGET_H
+
+#include <phonon/videowidget.h>
+#include <phonon/videowidgetinterface.h>
+
+#include "backend.h"
+#include "common.h"
+#include "medianode.h"
+#include "abstractrenderer.h"
+#include "videowidget.h"
+
+#include <gst/gst.h>
+
+#ifndef QT_NO_PHONON_VIDEO
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class VideoWidget : public QWidget, public Phonon::VideoWidgetInterface, public MediaNode
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VideoWidgetInterface Phonon::Gstreamer::MediaNode)
+public:
+ VideoWidget(Backend *backend, QWidget *parent = 0);
+ ~VideoWidget();
+
+ void setupVideoBin();
+ void paintEvent(QPaintEvent *event);
+ void mediaNodeEvent(const MediaNodeEvent *event);
+ void setVisible(bool);
+
+ Phonon::VideoWidget::AspectRatio aspectRatio() const;
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio);
+ Phonon::VideoWidget::ScaleMode scaleMode() const;
+ void setScaleMode(Phonon::VideoWidget::ScaleMode);
+ qreal brightness() const;
+ void setBrightness(qreal);
+ qreal contrast() const;
+ void setContrast(qreal);
+ qreal hue() const;
+ void setHue(qreal);
+ qreal saturation() const;
+ void setSaturation(qreal);
+ void setMovieSize(const QSize &size);
+ QSize sizeHint() const;
+ QRect scaleToAspect(QRect srcRect, int w, int h) const;
+ QRect calculateDrawFrameRect() const;
+
+ GstElement *videoElement()
+ {
+ Q_ASSERT(m_videoBin);
+ return m_videoBin;
+ }
+
+ QSize movieSize() const {
+ return m_movieSize;
+ }
+
+ bool event(QEvent *);
+
+ QWidget *widget() {
+ return this;
+ }
+
+protected:
+ GstElement *m_videoBin;
+ QSize m_movieSize;
+ AbstractRenderer *m_renderer;
+
+private:
+ Phonon::VideoWidget::AspectRatio m_aspectRatio;
+ qreal m_brightness, m_hue, m_contrast, m_saturation;
+ Phonon::VideoWidget::ScaleMode m_scaleMode;
+
+ GstElement *m_videoBalance;
+ GstElement *m_colorspace;
+ GstElement *m_videoplug;
+};
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_VIDEO
+#endif // Phonon_GSTREAMER_VIDEOWIDGET_H
diff --git a/src/3rdparty/phonon/gstreamer/volumefadereffect.cpp b/src/3rdparty/phonon/gstreamer/volumefadereffect.cpp
new file mode 100644
index 0000000..bf0d646
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/volumefadereffect.cpp
@@ -0,0 +1,162 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "volumefadereffect.h"
+#include "common.h"
+#include <QtCore>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+namespace Phonon
+{
+namespace Gstreamer
+{
+VolumeFaderEffect::VolumeFaderEffect(Backend *backend, QObject *parent)
+ : Effect(backend, parent, AudioSource | AudioSink)
+ , m_fadeCurve(Phonon::VolumeFaderEffect::Fade3Decibel)
+ , m_fadeTimer(0)
+ , m_fadeDuration(0)
+ , m_fadeFromVolume(0)
+ , m_fadeToVolume(0)
+{
+ m_effectElement = gst_element_factory_make ("volume", NULL);
+ if (m_effectElement)
+ init();
+}
+
+VolumeFaderEffect::~VolumeFaderEffect()
+{
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+}
+
+GstElement* VolumeFaderEffect::createEffectBin()
+{
+ GstElement *audioBin = gst_bin_new(NULL);
+
+ // We need a queue to handle tee-connections from parent node
+ GstElement *queue= gst_element_factory_make ("queue", NULL);
+ gst_bin_add(GST_BIN(audioBin), queue);
+
+ GstElement *mconv= gst_element_factory_make ("audioconvert", NULL);
+ gst_bin_add(GST_BIN(audioBin), mconv);
+ gst_bin_add(GST_BIN(audioBin), m_effectElement);
+
+ // Link src pad
+ GstPad *srcPad= gst_element_get_pad (m_effectElement, "src");
+ gst_element_add_pad (audioBin, gst_ghost_pad_new ("src", srcPad));
+ gst_object_unref (srcPad);
+
+ // Link sink pad
+ gst_element_link_many(queue, mconv, m_effectElement, (const char*)NULL);
+ GstPad *sinkpad = gst_element_get_pad (queue, "sink");
+ gst_element_add_pad (audioBin, gst_ghost_pad_new ("sink", sinkpad));
+ gst_object_unref (sinkpad);
+ return audioBin;
+}
+
+float VolumeFaderEffect::volume() const
+{
+ gdouble val = 0.0;
+ if (m_effectElement)
+ g_object_get(G_OBJECT(m_effectElement), "volume", &val, (const char*)NULL);
+ return (float)val;
+}
+
+void VolumeFaderEffect::setVolume(float volume)
+{
+ g_object_set(G_OBJECT(m_effectElement), "volume", volume, (const char*)NULL);
+}
+
+Phonon::VolumeFaderEffect::FadeCurve VolumeFaderEffect::fadeCurve() const
+{
+ return m_fadeCurve;
+}
+
+void VolumeFaderEffect::setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve)
+{
+ m_fadeCurve = fadeCurve;
+}
+
+void VolumeFaderEffect::fadeTo(float targetVolume, int fadeTime)
+{
+ m_fadeToVolume = targetVolume;
+ m_fadeDuration = fadeTime;
+ m_fadeFromVolume = volume();
+ m_fadeStartTime.start();
+
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+ m_fadeTimer = startTimer(30);
+}
+
+void VolumeFaderEffect::updateFade()
+{
+ double currVal = 0.0;
+ float step = float(m_fadeStartTime.elapsed()) / float(m_fadeDuration);
+ if (step > 1){
+ step = 1;
+ if (m_fadeTimer) {
+ killTimer(m_fadeTimer);
+ m_fadeTimer = 0;
+ }
+ }
+ // This is a very loose and interpretation of the API
+ // But in fact when fading between arbitrary values, the decibel values make no sense
+ // Note : seems like we will change the API to re-use names from QTimeline for this
+ switch (fadeCurve()) {
+ case Phonon::VolumeFaderEffect::Fade3Decibel: // Slow in the beginning
+ currVal = step * step;
+ break;
+ case Phonon::VolumeFaderEffect::Fade6Decibel: // Linear fade
+ currVal = step;
+ break;
+ case Phonon::VolumeFaderEffect::Fade9Decibel: // Fast in the beginning / Linear
+ currVal = step * 0.5 + (1.0-(1.0-step)*(1.0-step)) * 0.5;
+ break;
+ case Phonon::VolumeFaderEffect::Fade12Decibel: // Fast in the beginning
+ currVal = 1.0 - (1.0-step) * (1.0-step);
+ break;
+ default:
+ break;
+ }
+ const double volume = (1.0 - currVal) * m_fadeFromVolume + currVal * m_fadeToVolume;
+ setVolume(volume);
+}
+
+bool VolumeFaderEffect::event(QEvent *event)
+{
+ switch (event->type()){
+ case QEvent::Timer:
+ {
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
+ if (timerEvent->timerId() == m_fadeTimer)
+ updateFade();
+ break;
+ }
+ default:
+ break;
+ }
+ return QObject::event(event);
+}
+
+}} //namespace Phonon::Gstreamer
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+QT_END_NAMESPACE
+
+#include "moc_volumefadereffect.cpp"
diff --git a/src/3rdparty/phonon/gstreamer/volumefadereffect.h b/src/3rdparty/phonon/gstreamer/volumefadereffect.h
new file mode 100644
index 0000000..748d2d6
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/volumefadereffect.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_VOLUMEFADEREFFECT_H
+#define Phonon_GSTREAMER_VOLUMEFADEREFFECT_H
+
+#include "medianode.h"
+#include "effect.h"
+
+#include <phonon/effectinterface.h>
+#include <phonon/effectparameter.h>
+#include <phonon/volumefaderinterface.h>
+
+#include <QtCore>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+namespace Phonon
+{
+namespace Gstreamer
+{
+ class VolumeFaderEffect : public Effect, public VolumeFaderInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VolumeFaderInterface)
+
+ public:
+ VolumeFaderEffect(Backend *backend, QObject *parent = 0);
+ ~VolumeFaderEffect();
+
+ GstElement* createEffectBin();
+ GstElement *audioElement() { return m_effectBin; }
+ bool event(QEvent *);
+ void updateFade();
+
+ // VolumeFaderInterface:
+ float volume() const;
+ void setVolume(float volume);
+ Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const;
+ void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve);
+ void fadeTo(float volume, int fadeTime);
+
+ Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve;
+ int m_fadeTimer;
+ int m_fadeDuration;
+ float m_fadeFromVolume;
+ float m_fadeToVolume;
+ QTime m_fadeStartTime;
+ };
+}} //namespace Phonon::Gstreamer
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_VOLUMEFADEREFFECT_H
diff --git a/src/3rdparty/phonon/gstreamer/widgetrenderer.cpp b/src/3rdparty/phonon/gstreamer/widgetrenderer.cpp
new file mode 100644
index 0000000..423af9d
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/widgetrenderer.cpp
@@ -0,0 +1,152 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QtGui/QPainter>
+#include <gst/gst.h>
+#include "common.h"
+#include "message.h"
+#include "mediaobject.h"
+#include "qwidgetvideosink.h"
+#include "widgetrenderer.h"
+#include "qrgb.h"
+
+// support old OpenGL installations (1.2)
+// assume that if TEXTURE0 isn't defined, none are
+#ifndef GL_TEXTURE0
+# define GL_TEXTURE0 0x84C0
+# define GL_TEXTURE1 0x84C1
+# define GL_TEXTURE2 0x84C2
+#endif
+
+#ifndef QT_NO_PHONON_VIDEO
+QT_BEGIN_NAMESPACE
+
+static void frameRendered()
+{
+ static QString displayFps = qgetenv("PHONON_GST_FPS");
+ if (displayFps.isEmpty())
+ return;
+
+ static int frames = 0;
+ static QTime lastTime = QTime::currentTime();
+ QTime time = QTime::currentTime();
+
+ int delta = lastTime.msecsTo(time);
+ if (delta > 2000) {
+ printf("FPS: %f\n", 1000.0 * frames / qreal(delta));
+ lastTime = time;
+ frames = 0;
+ }
+
+ ++frames;
+}
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+WidgetRenderer::WidgetRenderer(VideoWidget *videoWidget)
+ : AbstractRenderer(videoWidget)
+ , m_width(0)
+ , m_height(0)
+{
+ videoWidget->backend()->logMessage("Creating QWidget renderer");
+ if ((m_videoSink = GST_ELEMENT(g_object_new(get_type_RGB(), NULL)))) {
+ gst_object_ref (GST_OBJECT (m_videoSink)); //Take ownership
+ gst_object_sink (GST_OBJECT (m_videoSink));
+
+ QWidgetVideoSinkBase* sink = reinterpret_cast<QWidgetVideoSinkBase*>(m_videoSink);
+ // Let the videosink know which widget to direct frame updates to
+ sink->renderWidget = videoWidget;
+ }
+
+ // Clear the background with black by default
+ QPalette palette;
+ palette.setColor(QPalette::Background, Qt::black);
+ m_videoWidget->setPalette(palette);
+ m_videoWidget->setAutoFillBackground(true);
+ m_videoWidget->setAttribute(Qt::WA_NoSystemBackground, false);
+ m_videoWidget->setAttribute(Qt::WA_PaintOnScreen, false);
+}
+
+void WidgetRenderer::setNextFrame(const QByteArray &array, int w, int h)
+{
+ if (m_videoWidget->root()->state() == Phonon::LoadingState)
+ return;
+
+ m_frame = QImage();
+ {
+ m_frame = QImage((uchar *)array.constData(), w, h, QImage::Format_RGB32);
+ }
+
+ m_array = array;
+ m_width = w;
+ m_height = h;
+
+ m_videoWidget->update();
+}
+
+void WidgetRenderer::handleMediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()) {
+ case MediaNodeEvent::SourceChanged:
+ {
+ clearFrame();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void WidgetRenderer::clearFrame()
+{
+ m_frame = QImage();
+ m_array = QByteArray();
+ m_videoWidget->update();
+}
+
+const QImage &WidgetRenderer::currentFrame() const
+{
+ return m_frame;
+}
+
+void WidgetRenderer::handlePaint(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+ QPainter painter(m_videoWidget);
+ m_drawFrameRect = m_videoWidget->calculateDrawFrameRect();
+ painter.drawImage(drawFrameRect(), currentFrame());
+ frameRendered();
+}
+
+bool WidgetRenderer::eventFilter(QEvent * event)
+{
+ if (event->type() == QEvent::User) {
+ NewFrameEvent *frameEvent= static_cast <NewFrameEvent *>(event);
+ setNextFrame(frameEvent->frame, frameEvent->width, frameEvent->height);
+ return true;
+ }
+ return false;
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/gstreamer/widgetrenderer.h b/src/3rdparty/phonon/gstreamer/widgetrenderer.h
new file mode 100644
index 0000000..03ee9c0
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/widgetrenderer.h
@@ -0,0 +1,64 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_WIDGETRENDERER_H
+#define Phonon_GSTREAMER_WIDGETRENDERER_H
+
+#include "videowidget.h"
+#include "common.h"
+
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL/QGLFormat>
+#include <QtOpenGL/QGLWidget>
+#endif
+
+#ifndef QT_NO_PHONON_VIDEO
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class WidgetRenderer : public AbstractRenderer
+{
+public:
+ WidgetRenderer(VideoWidget *videoWidget);
+ bool eventFilter(QEvent * event);
+ void handlePaint(QPaintEvent *paintEvent);
+ void handleMediaNodeEvent(const MediaNodeEvent *event);
+ const QImage& currentFrame() const;
+ QRect drawFrameRect() const { return m_drawFrameRect; }
+ void setNextFrame(const QByteArray &array, int width, int height);
+ bool frameIsSet() { return !m_array.isNull(); }
+ void clearFrame();
+private:
+ mutable QImage m_frame;
+ QByteArray m_array;
+ int m_width;
+ int m_height;
+ QRect m_drawFrameRect;
+};
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+#endif //QT_NO_PHONON_VIDEO
+#endif // Phonon_GSTREAMER_WIDGETRENDERER_H
diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.cpp b/src/3rdparty/phonon/gstreamer/x11renderer.cpp
new file mode 100644
index 0000000..968f3a8
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/x11renderer.cpp
@@ -0,0 +1,195 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "videowidget.h"
+#include "x11renderer.h"
+
+#ifndef Q_WS_QWS
+
+#include <QtGui/QPalette>
+#include <QtGui/QApplication>
+#include <QtGui/QPainter>
+#include <X11/Xlib.h>
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/propertyprobe.h>
+#include "common.h"
+#include "mediaobject.h"
+#include "message.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class OverlayWidget : public QWidget
+{
+public:
+ OverlayWidget(VideoWidget *videoWidget, X11Renderer *renderer) :
+ QWidget(videoWidget),
+ m_videoWidget(videoWidget),
+ m_renderer(renderer) { }
+ void paintEvent(QPaintEvent *) {
+ Phonon::State state = m_videoWidget->root() ? m_videoWidget->root()->state() : Phonon::LoadingState;
+ if (state == Phonon::PlayingState || state == Phonon::PausedState) {
+ m_renderer->windowExposed();
+ } else {
+ QPainter painter(this);
+ painter.fillRect(m_videoWidget->rect(), m_videoWidget->palette().background());
+ }
+ }
+private:
+ VideoWidget *m_videoWidget;
+ X11Renderer *m_renderer;
+};
+
+X11Renderer::X11Renderer(VideoWidget *videoWidget)
+ : AbstractRenderer(videoWidget)
+{
+ m_renderWidget = new OverlayWidget(videoWidget, this);
+ videoWidget->backend()->logMessage("Creating X11 overlay renderer");
+ QPalette palette;
+ palette.setColor(QPalette::Background, Qt::black);
+ m_videoWidget->setPalette(palette);
+ m_videoWidget->setAutoFillBackground(true);
+ m_renderWidget->setMouseTracking(true);
+ m_videoSink = createVideoSink();
+ aspectRatioChanged(videoWidget->aspectRatio());
+ setOverlay();
+}
+
+X11Renderer::~X11Renderer()
+{
+ m_renderWidget->setAttribute(Qt::WA_PaintOnScreen, false);
+ m_renderWidget->setAttribute(Qt::WA_NoSystemBackground, false);
+ delete m_renderWidget;
+}
+
+GstElement* X11Renderer::createVideoSink()
+{
+ GstElement *videoSink = gst_element_factory_make ("xvimagesink", NULL);
+ if (videoSink) {
+ // Check if the xv sink is usable
+ if (gst_element_set_state(videoSink, GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS) {
+ gst_object_unref(GST_OBJECT(videoSink));
+ videoSink = 0;
+ } else {
+ // Note that this should not really be necessary as these are
+ // default values, though under certain conditions values are retained
+ // even between application instances. (reproducible on 0.10.16/Gutsy)
+ g_object_set(G_OBJECT(videoSink), "brightness", 0, (const char*)NULL);
+ g_object_set(G_OBJECT(videoSink), "contrast", 0, (const char*)NULL);
+ g_object_set(G_OBJECT(videoSink), "hue", 0, (const char*)NULL);
+ g_object_set(G_OBJECT(videoSink), "saturation", 0, (const char*)NULL);
+ }
+ }
+
+ if (!videoSink)
+ videoSink = gst_element_factory_make ("ximagesink", NULL);
+
+ gst_object_ref (GST_OBJECT (videoSink)); //Take ownership
+ gst_object_sink (GST_OBJECT (videoSink));
+
+ return videoSink;
+}
+
+void X11Renderer::handleMediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()) {
+ case MediaNodeEvent::SourceChanged:
+ setOverlay(); // We need to do this whenever the pipeline is reset
+ break; // otherwise the videosink will open in its own window
+ default:
+ break;
+ }
+}
+
+
+void X11Renderer::aspectRatioChanged(Phonon::VideoWidget::AspectRatio)
+{
+ if (m_renderWidget) {
+ m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ }
+}
+
+void X11Renderer::scaleModeChanged(Phonon::VideoWidget::ScaleMode)
+{
+ if (m_renderWidget) {
+ m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ }
+}
+
+void X11Renderer::movieSizeChanged(const QSize &movieSize)
+{
+ Q_UNUSED(movieSize);
+
+ if (m_renderWidget) {
+ m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ }
+}
+
+bool X11Renderer::eventFilter(QEvent *e)
+{
+ if (e->type() == QEvent::Show) {
+ // Setting these values ensures smooth resizing since it
+ // will prevent the system from clearing the background
+ m_renderWidget->setAttribute(Qt::WA_NoSystemBackground, true);
+ m_renderWidget->setAttribute(Qt::WA_PaintOnScreen, true);
+ setOverlay();
+ } else if (e->type() == QEvent::Resize) {
+ // This is a workaround for missing background repaints
+ // when reducing window size
+ m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
+ windowExposed();
+ }
+ return false;
+}
+
+void X11Renderer::handlePaint(QPaintEvent *)
+{
+ QPainter painter(m_videoWidget);
+ painter.fillRect(m_videoWidget->rect(), m_videoWidget->palette().background());
+}
+
+void X11Renderer::setOverlay()
+{
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) {
+ WId windowId = m_renderWidget->winId();
+ // Even if we have created a winId at this point, other X applications
+ // need to be aware of it.
+ QApplication::syncX();
+ gst_x_overlay_set_xwindow_id ( GST_X_OVERLAY(m_videoSink) , windowId );
+ }
+ windowExposed();
+ m_overlaySet = true;
+}
+
+void X11Renderer::windowExposed()
+{
+ QApplication::syncX();
+ if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink))
+ gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink));
+}
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Q_WS_QWS
diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.h b/src/3rdparty/phonon/gstreamer/x11renderer.h
new file mode 100644
index 0000000..8e2ea19
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/x11renderer.h
@@ -0,0 +1,64 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_X11RENDERER_H
+#define Phonon_GSTREAMER_X11RENDERER_H
+
+#include "videowidget.h"
+#include "common.h"
+
+#include <QtGui/QWidget>
+
+#include <gst/gst.h>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+
+class OverlayWidget;
+class X11Renderer : public AbstractRenderer
+{
+public:
+ X11Renderer(VideoWidget *videoWidget);
+ ~X11Renderer();
+ void handlePaint(QPaintEvent *event);
+ void aspectRatioChanged(Phonon::VideoWidget::AspectRatio aspectRatio);
+ void scaleModeChanged(Phonon::VideoWidget::ScaleMode scaleMode);
+ void movieSizeChanged(const QSize &movieSize);
+ void handleMediaNodeEvent(const MediaNodeEvent *event);
+ bool eventFilter(QEvent *);
+ bool paintsOnWidget() { return false; }
+ bool overlaySet() const { return m_overlaySet; }
+ void setOverlay();
+ void windowExposed();
+ GstElement *createVideoSink();
+private:
+ OverlayWidget *m_renderWidget;
+ bool m_overlaySet;
+};
+
+}
+} //namespace Phonon::Gstreamer
+
+QT_END_NAMESPACE
+
+#endif // Phonon_GSTREAMER_X11RENDERER_H
diff --git a/src/3rdparty/phonon/includes/CMakeLists.txt b/src/3rdparty/phonon/includes/CMakeLists.txt
new file mode 100644
index 0000000..dff86c3
--- /dev/null
+++ b/src/3rdparty/phonon/includes/CMakeLists.txt
@@ -0,0 +1,49 @@
+install( FILES
+ Phonon/AbstractAudioOutput
+ Phonon/AbstractMediaStream
+ Phonon/AbstractVideoOutput
+ Phonon/AddonInterface
+ Phonon/AudioDevice
+ Phonon/AudioDeviceEnumerator
+ Phonon/AudioOutput
+ Phonon/AudioOutputDevice
+ Phonon/AudioOutputDeviceModel
+ Phonon/AudioOutputInterface
+ Phonon/BackendCapabilities
+ Phonon/BackendInterface
+ Phonon/Effect
+ Phonon/EffectDescription
+ Phonon/EffectDescriptionModel
+ Phonon/EffectInterface
+ Phonon/EffectParameter
+ Phonon/EffectWidget
+ Phonon/Global
+ Phonon/MediaController
+ Phonon/MediaNode
+ Phonon/MediaObject
+ Phonon/MediaObjectInterface
+ Phonon/MediaSource
+ Phonon/ObjectDescription
+ Phonon/ObjectDescriptionModel
+ Phonon/Path
+ Phonon/PlatformPlugin
+ Phonon/SeekSlider
+ Phonon/StreamInterface
+ Phonon/VideoPlayer
+ Phonon/VideoWidget
+ Phonon/VideoWidgetInterface
+ Phonon/VolumeFaderEffect
+ Phonon/VolumeFaderInterface
+ Phonon/VolumeSlider
+DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/Phonon COMPONENT Devel)
+
+install(FILES
+ Phonon/Experimental/AbstractVideoDataOutput
+ Phonon/Experimental/AudioDataOutput
+ Phonon/Experimental/SnapshotInterface
+ Phonon/Experimental/VideoDataOutput
+ Phonon/Experimental/VideoDataOutputInterface
+ Phonon/Experimental/VideoFrame
+ Phonon/Experimental/VideoFrame2
+ Phonon/Experimental/Visualization
+DESTINATION ${INCLUDE_INSTALL_DIR}/KDE/Phonon/Experimental COMPONENT Devel)
diff --git a/src/3rdparty/phonon/includes/Phonon/AbstractAudioOutput b/src/3rdparty/phonon/includes/Phonon/AbstractAudioOutput
new file mode 100644
index 0000000..46d7668
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AbstractAudioOutput
@@ -0,0 +1 @@
+#include "../../phonon/abstractaudiooutput.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AbstractMediaStream b/src/3rdparty/phonon/includes/Phonon/AbstractMediaStream
new file mode 100644
index 0000000..77837cf
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AbstractMediaStream
@@ -0,0 +1 @@
+#include "../../phonon/abstractmediastream.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AbstractVideoOutput b/src/3rdparty/phonon/includes/Phonon/AbstractVideoOutput
new file mode 100644
index 0000000..da05eb0
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AbstractVideoOutput
@@ -0,0 +1 @@
+#include "../../phonon/abstractvideooutput.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AddonInterface b/src/3rdparty/phonon/includes/Phonon/AddonInterface
new file mode 100644
index 0000000..448993a
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AddonInterface
@@ -0,0 +1 @@
+#include "../../phonon/addoninterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AudioDevice b/src/3rdparty/phonon/includes/Phonon/AudioDevice
new file mode 100644
index 0000000..b1b5162
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AudioDevice
@@ -0,0 +1 @@
+#include "../../phonon/audiodevice.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AudioDeviceEnumerator b/src/3rdparty/phonon/includes/Phonon/AudioDeviceEnumerator
new file mode 100644
index 0000000..d971a3d
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AudioDeviceEnumerator
@@ -0,0 +1 @@
+#include "../../phonon/audiodeviceenumerator.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AudioOutput b/src/3rdparty/phonon/includes/Phonon/AudioOutput
new file mode 100644
index 0000000..d67ac91
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AudioOutput
@@ -0,0 +1 @@
+#include "../../phonon/audiooutput.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AudioOutputDevice b/src/3rdparty/phonon/includes/Phonon/AudioOutputDevice
new file mode 100644
index 0000000..3f75a1d
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AudioOutputDevice
@@ -0,0 +1 @@
+#include "../../phonon/objectdescription.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AudioOutputDeviceModel b/src/3rdparty/phonon/includes/Phonon/AudioOutputDeviceModel
new file mode 100644
index 0000000..eae8aec
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AudioOutputDeviceModel
@@ -0,0 +1 @@
+#include "../../phonon/objectdescriptionmodel.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/AudioOutputInterface b/src/3rdparty/phonon/includes/Phonon/AudioOutputInterface
new file mode 100644
index 0000000..b0ef2e7
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/AudioOutputInterface
@@ -0,0 +1 @@
+#include "../../phonon/audiooutputinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/BackendCapabilities b/src/3rdparty/phonon/includes/Phonon/BackendCapabilities
new file mode 100644
index 0000000..b123613
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/BackendCapabilities
@@ -0,0 +1 @@
+#include "../../phonon/backendcapabilities.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/BackendInterface b/src/3rdparty/phonon/includes/Phonon/BackendInterface
new file mode 100644
index 0000000..389c124
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/BackendInterface
@@ -0,0 +1 @@
+#include "../../phonon/backendinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Effect b/src/3rdparty/phonon/includes/Phonon/Effect
new file mode 100644
index 0000000..009eb15
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Effect
@@ -0,0 +1 @@
+#include "../../phonon/effect.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/EffectDescription b/src/3rdparty/phonon/includes/Phonon/EffectDescription
new file mode 100644
index 0000000..3f75a1d
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/EffectDescription
@@ -0,0 +1 @@
+#include "../../phonon/objectdescription.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/EffectDescriptionModel b/src/3rdparty/phonon/includes/Phonon/EffectDescriptionModel
new file mode 100644
index 0000000..eae8aec
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/EffectDescriptionModel
@@ -0,0 +1 @@
+#include "../../phonon/objectdescriptionmodel.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/EffectInterface b/src/3rdparty/phonon/includes/Phonon/EffectInterface
new file mode 100644
index 0000000..d5a5bc3
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/EffectInterface
@@ -0,0 +1 @@
+#include "../../phonon/effectinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/EffectParameter b/src/3rdparty/phonon/includes/Phonon/EffectParameter
new file mode 100644
index 0000000..301fe16
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/EffectParameter
@@ -0,0 +1 @@
+#include "../../phonon/effectparameter.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/EffectWidget b/src/3rdparty/phonon/includes/Phonon/EffectWidget
new file mode 100644
index 0000000..72e687f
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/EffectWidget
@@ -0,0 +1 @@
+#include "../../phonon/effectwidget.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/AbstractVideoDataOutput b/src/3rdparty/phonon/includes/Phonon/Experimental/AbstractVideoDataOutput
new file mode 100644
index 0000000..c019215
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/AbstractVideoDataOutput
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/abstractvideodataoutput.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/AudioDataOutput b/src/3rdparty/phonon/includes/Phonon/Experimental/AudioDataOutput
new file mode 100644
index 0000000..06d181d
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/AudioDataOutput
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/audiodataoutput.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/SnapshotInterface b/src/3rdparty/phonon/includes/Phonon/Experimental/SnapshotInterface
new file mode 100644
index 0000000..5e59306
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/SnapshotInterface
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/snapshotinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutput b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutput
new file mode 100644
index 0000000..9878ccf
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutput
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/videodataoutput.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutputInterface b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutputInterface
new file mode 100644
index 0000000..870f683
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoDataOutputInterface
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/videodataoutputinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame
new file mode 100644
index 0000000..97c137e
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/videoframe.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame2 b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame2
new file mode 100644
index 0000000..29d1af9
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/VideoFrame2
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/videoframe2.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Experimental/Visualization b/src/3rdparty/phonon/includes/Phonon/Experimental/Visualization
new file mode 100644
index 0000000..b5aab38
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Experimental/Visualization
@@ -0,0 +1 @@
+#include "../../../phonon/experimental/visualization.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Global b/src/3rdparty/phonon/includes/Phonon/Global
new file mode 100644
index 0000000..4215e3b
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Global
@@ -0,0 +1 @@
+#include "../../phonon/phononnamespace.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/MediaController b/src/3rdparty/phonon/includes/Phonon/MediaController
new file mode 100644
index 0000000..666be3e
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/MediaController
@@ -0,0 +1 @@
+#include "../../phonon/mediacontroller.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/MediaNode b/src/3rdparty/phonon/includes/Phonon/MediaNode
new file mode 100644
index 0000000..8083158
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/MediaNode
@@ -0,0 +1 @@
+#include "../../phonon/medianode.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/MediaObject b/src/3rdparty/phonon/includes/Phonon/MediaObject
new file mode 100644
index 0000000..fa6d33b
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/MediaObject
@@ -0,0 +1 @@
+#include "../../phonon/mediaobject.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/MediaObjectInterface b/src/3rdparty/phonon/includes/Phonon/MediaObjectInterface
new file mode 100644
index 0000000..c78243b
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/MediaObjectInterface
@@ -0,0 +1 @@
+#include "../../phonon/mediaobjectinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/MediaSource b/src/3rdparty/phonon/includes/Phonon/MediaSource
new file mode 100644
index 0000000..6ee2a72
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/MediaSource
@@ -0,0 +1 @@
+#include "../../phonon/mediasource.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/ObjectDescription b/src/3rdparty/phonon/includes/Phonon/ObjectDescription
new file mode 100644
index 0000000..3f75a1d
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/ObjectDescription
@@ -0,0 +1 @@
+#include "../../phonon/objectdescription.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/ObjectDescriptionModel b/src/3rdparty/phonon/includes/Phonon/ObjectDescriptionModel
new file mode 100644
index 0000000..eae8aec
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/ObjectDescriptionModel
@@ -0,0 +1 @@
+#include "../../phonon/objectdescriptionmodel.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/Path b/src/3rdparty/phonon/includes/Phonon/Path
new file mode 100644
index 0000000..1b3d2d5
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/Path
@@ -0,0 +1 @@
+#include "../../phonon/path.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/PlatformPlugin b/src/3rdparty/phonon/includes/Phonon/PlatformPlugin
new file mode 100644
index 0000000..258f339
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/PlatformPlugin
@@ -0,0 +1 @@
+#include "../../phonon/platformplugin.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/SeekSlider b/src/3rdparty/phonon/includes/Phonon/SeekSlider
new file mode 100644
index 0000000..3dde9a8
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/SeekSlider
@@ -0,0 +1 @@
+#include "../../phonon/seekslider.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/StreamInterface b/src/3rdparty/phonon/includes/Phonon/StreamInterface
new file mode 100644
index 0000000..efd8c20
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/StreamInterface
@@ -0,0 +1 @@
+#include "../../phonon/streaminterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/VideoPlayer b/src/3rdparty/phonon/includes/Phonon/VideoPlayer
new file mode 100644
index 0000000..68c0fd3
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/VideoPlayer
@@ -0,0 +1 @@
+#include "../../phonon/videoplayer.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/VideoWidget b/src/3rdparty/phonon/includes/Phonon/VideoWidget
new file mode 100644
index 0000000..9420f6b
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/VideoWidget
@@ -0,0 +1 @@
+#include "../../phonon/videowidget.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/VideoWidgetInterface b/src/3rdparty/phonon/includes/Phonon/VideoWidgetInterface
new file mode 100644
index 0000000..173dd33
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/VideoWidgetInterface
@@ -0,0 +1 @@
+#include "../../phonon/videowidgetinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/VolumeFaderEffect b/src/3rdparty/phonon/includes/Phonon/VolumeFaderEffect
new file mode 100644
index 0000000..9e64400
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/VolumeFaderEffect
@@ -0,0 +1 @@
+#include "../../phonon/volumefadereffect.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/VolumeFaderInterface b/src/3rdparty/phonon/includes/Phonon/VolumeFaderInterface
new file mode 100644
index 0000000..47bfe26
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/VolumeFaderInterface
@@ -0,0 +1 @@
+#include "../../phonon/volumefaderinterface.h"
diff --git a/src/3rdparty/phonon/includes/Phonon/VolumeSlider b/src/3rdparty/phonon/includes/Phonon/VolumeSlider
new file mode 100644
index 0000000..f4d50f7
--- /dev/null
+++ b/src/3rdparty/phonon/includes/Phonon/VolumeSlider
@@ -0,0 +1 @@
+#include "../../phonon/volumeslider.h"
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp
new file mode 100644
index 0000000..9b64ab3
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp
@@ -0,0 +1,195 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "mediaobject.h"
+
+#include "abstractaudioeffect.h"
+#include "audioplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AbstractAudioEffect
+ \internal
+*/
+
+/*! \namespace Phonon::MMF
+ \internal
+*/
+
+AbstractAudioEffect::AbstractAudioEffect(QObject *parent,
+ const QList<EffectParameter> &params)
+ : MediaNode(parent)
+ , m_params(params)
+ , m_player(0)
+{
+
+}
+
+QList<Phonon::EffectParameter> AbstractAudioEffect::parameters() const
+{
+ // Convert from QList<MMF::EffectParameter> to QList<Phonon::EffectParameter>
+ QList<Phonon::EffectParameter> result;
+ EffectParameter param;
+ foreach (param, m_params)
+ result += param;
+ return result;
+}
+
+QVariant AbstractAudioEffect::parameterValue(const Phonon::EffectParameter &queriedParam) const
+{
+ const QVariant &val = m_values.value(queriedParam.id());
+
+ if (val.isNull())
+ return queriedParam.defaultValue();
+ else
+ return val;
+}
+
+void AbstractAudioEffect::setParameterValue(const Phonon::EffectParameter &param,
+ const QVariant &newValue)
+{
+ m_values.insert(param.id(), newValue);
+
+ if (m_effect.data()) {
+ const EffectParameter& internalParam = internalParameter(param.id());
+ int err = parameterChanged(internalParam, newValue);
+ // TODO: handle audio effect errors
+ Q_UNUSED(err);
+ }
+}
+
+void AbstractAudioEffect::abstractPlayerChanged(AbstractPlayer *player)
+{
+ m_player = qobject_cast<AbstractMediaPlayer *>(player);
+ m_effect.reset();
+}
+
+void AbstractAudioEffect::stateChanged(Phonon::State newState,
+ Phonon::State oldState)
+{
+ if (Phonon::LoadingState == oldState
+ && Phonon::LoadingState != newState)
+ createEffect();
+}
+
+void AbstractAudioEffect::connectMediaObject(MediaObject *mediaObject)
+{
+ Q_ASSERT_X(!m_player, Q_FUNC_INFO, "Player already connected");
+ Q_ASSERT_X(!m_effect.data(), Q_FUNC_INFO, "Effect already created");
+
+ abstractPlayerChanged(mediaObject->abstractPlayer());
+
+ connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
+ SLOT(stateChanged(Phonon::State, Phonon::State)));
+
+ connect(mediaObject, SIGNAL(abstractPlayerChanged(AbstractPlayer *)),
+ SLOT(abstractPlayerChanged(AbstractPlayer *)));
+
+ if (mediaObject->state() != Phonon::LoadingState)
+ createEffect();
+}
+
+void AbstractAudioEffect::disconnectMediaObject(MediaObject *mediaObject)
+{
+ mediaObject->disconnect(this);
+ abstractPlayerChanged(0);
+}
+
+void AbstractAudioEffect::setEnabled(bool enabled)
+{
+ TInt err = KErrNone;
+
+ if (enabled)
+ // TODO: handle audio effect errors
+ TRAP(err, m_effect->EnableL())
+ else
+ // TODO: handle audio effect errors
+ TRAP(err, m_effect->DisableL())
+
+ Q_UNUSED(err);
+}
+
+void AbstractAudioEffect::createEffect()
+{
+ Q_ASSERT_X(m_player, Q_FUNC_INFO, "Invalid media player pointer");
+
+ if (AudioPlayer *audioPlayer = qobject_cast<AudioPlayer *>(m_player)) {
+ createEffect(audioPlayer->nativePlayer());
+ }
+
+ if (m_effect.data()) {
+ EffectParameter param;
+ int err = 0;
+ foreach (param, m_params) {
+ const QVariant value = parameterValue(param);
+ err = parameterChanged(param, value);
+ }
+ Q_UNUSED(err)
+ }
+}
+
+const MMF::EffectParameter& AbstractAudioEffect::internalParameter(int id) const
+{
+ const EffectParameter *result = 0;
+ for (int i=0; i<m_params.count() && !result; ++i) {
+ if (m_params[i].id() == id)
+ result = &m_params[i];
+ }
+ Q_ASSERT_X(result, Q_FUNC_INFO, "Parameter not found");
+ return *result;
+}
+
+int AbstractAudioEffect::parameterChanged(const EffectParameter &param,
+ const QVariant &value)
+{
+ int err = 0;
+
+ switch (param.id()) {
+ case ParameterEnable:
+ setEnabled(value.toBool());
+ break;
+ default:
+ {
+ const EffectParameter& internalParam = internalParameter(param.id());
+ err = effectParameterChanged(internalParam, value);
+ }
+ break;
+ }
+
+ if (!err)
+ TRAP(err, m_effect->ApplyL());
+
+ return err;
+}
+
+int AbstractAudioEffect::effectParameterChanged(
+ const EffectParameter &param, const QVariant &value)
+{
+ // Default implementation
+ Q_UNUSED(param)
+ Q_UNUSED(value)
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Effect has no parameters");
+ return 0;
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h
new file mode 100644
index 0000000..517a334
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h
@@ -0,0 +1,142 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ABSTRACTEFFECT_H
+#define PHONON_MMF_ABSTRACTEFFECT_H
+
+#include <QScopedPointer>
+
+#include <AudioEffectBase.h>
+
+#include <phonon/effectinterface.h>
+
+#include "audioplayer.h"
+#include "effectparameter.h"
+#include "mmf_medianode.h"
+
+class CMdaAudioOutputStream;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+class AbstractPlayer;
+class AbstractMediaPlayer;
+
+/**
+ * @short Base class for all effects for MMF.
+ *
+ * Adhering to Phonon with MMF is cumbersome because of a number of reasons:
+ *
+ * - MMF has no concept of effect chaining. Simply, an effect is a applied
+ * to PlayerUtility, that's it. This means that the order of effects is
+ * undefined.
+ * - We apply an effect to a PlayerUtility, and MediaObject has that one.
+ * However, effects might be created before MediaObject, but nevertheless
+ * needs to work. We solve this by that we are aware of the whole connection
+ * chain, and whenever a connection happens, we walk the chain, find effects
+ * that aren't applied, and apply it if we have a media object.
+ * - There are plenty of corner cases which we don't handle and where behavior
+ * are undefined. For instance, graphs with more than one MediaObject.
+ */
+class AbstractAudioEffect : public MediaNode
+ , public EffectInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface)
+public:
+ AbstractAudioEffect(QObject *parent,
+ const QList<EffectParameter> &params);
+
+ // Phonon::EffectInterface
+ virtual QList<Phonon::EffectParameter> parameters() const;
+ virtual QVariant parameterValue(const Phonon::EffectParameter &param) const;
+ virtual void setParameterValue(const Phonon::EffectParameter &,
+ const QVariant &newValue);
+
+ // Parameters which are shared by all effects
+ enum CommonParameters
+ {
+ ParameterEnable = 0,
+ ParameterBase // must be last entry in enum
+ };
+
+public Q_SLOTS:
+ void abstractPlayerChanged(AbstractPlayer *player);
+ void stateChanged(Phonon::State newState,
+ Phonon::State oldState);
+
+protected:
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
+
+ virtual void createEffect(AudioPlayer::NativePlayer *player) = 0;
+
+ // Effect-specific parameter changed
+ virtual int effectParameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+private:
+ void createEffect();
+ void setEnabled(bool enabled);
+ const EffectParameter& internalParameter(int id) const;
+ int parameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+protected:
+ QScopedPointer<CAudioEffect> m_effect;
+
+private:
+ const QList<EffectParameter> m_params;
+ AbstractMediaPlayer * m_player;
+ QHash<int, QVariant> m_values;
+};
+
+}
+}
+
+
+// Macro for defining functions which depend on the native class name
+// for each of the effects. Using this reduces repetition of boilerplate
+// in the implementations of the backend effect nodes.
+
+#ifdef Q_CC_NOKIAX86
+# pragma warn_illtokenpasting off
+#endif
+
+#define PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(Effect) \
+ \
+void Effect::createEffect(AudioPlayer::NativePlayer *player) \
+{ \
+ C##Effect *ptr = 0; \
+ QT_TRAP_THROWING(ptr = C##Effect::NewL(*player)); \
+ m_effect.reset(ptr); \
+} \
+ \
+C##Effect* Effect::concreteEffect() \
+{ \
+ return static_cast<C##Effect *>(m_effect.data()); \
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
new file mode 100644
index 0000000..4f7caff
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.cpp
@@ -0,0 +1,707 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QResource>
+#include <QUrl>
+
+#include "abstractmediaplayer.h"
+#include "defs.h"
+#include "mediaobject.h"
+#include "utils.h"
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AbstractMediaPlayer
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------------
+
+const int NullMaxVolume = -1;
+const int BufferStatusTimerInterval = 100; // ms
+
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::AbstractMediaPlayer::AbstractMediaPlayer
+ (MediaObject *parent, const AbstractPlayer *player)
+ : AbstractPlayer(player)
+ , m_parent(parent)
+ , m_pending(NothingPending)
+ , m_positionTimer(new QTimer(this))
+ , m_position(0)
+ , m_bufferStatusTimer(new QTimer(this))
+ , m_mmfMaxVolume(NullMaxVolume)
+ , m_prefinishMarkSent(false)
+ , m_aboutToFinishSent(false)
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ , m_download(0)
+ , m_downloadStalled(false)
+#endif
+{
+ connect(m_positionTimer.data(), SIGNAL(timeout()), this, SLOT(positionTick()));
+ connect(m_bufferStatusTimer.data(), SIGNAL(timeout()), this, SLOT(bufferStatusTick()));
+}
+
+//-----------------------------------------------------------------------------
+// MediaObjectInterface
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractMediaPlayer::play()
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::play, EAudioApi);
+ TRACE_ENTRY("state %d", privateState());
+
+ switch (privateState()) {
+ case GroundState:
+ setError(tr("Not ready to play"));
+ break;
+
+ case LoadingState:
+ setPending(PlayPending);
+ break;
+
+ case StoppedState:
+ case PausedState:
+ startPlayback();
+ break;
+
+ case PlayingState:
+ case BufferingState:
+ case ErrorState:
+ // Do nothing
+ break;
+
+ // Protection against adding new states and forgetting to update this switch
+ default:
+ TRACE_PANIC(InvalidStatePanic);
+ }
+
+ TRACE_EXIT("state %d", privateState());
+}
+
+void MMF::AbstractMediaPlayer::pause()
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::pause, EAudioApi);
+ TRACE_ENTRY("state %d", privateState());
+
+ stopTimers();
+
+ switch (privateState()) {
+ case GroundState:
+ case LoadingState:
+ case StoppedState:
+ setPending(PausePending);
+ break;
+
+ case PausedState:
+ // Do nothing
+ break;
+
+ case PlayingState:
+ case BufferingState:
+ changeState(PausedState);
+ // Fall through
+ case ErrorState:
+ doPause();
+ break;
+
+ // Protection against adding new states and forgetting to update this switch
+ default:
+ TRACE_PANIC(InvalidStatePanic);
+ }
+
+ TRACE_EXIT("state %d", privateState());
+}
+
+void MMF::AbstractMediaPlayer::stop()
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::stop, EAudioApi);
+ TRACE_ENTRY("state %d", privateState());
+
+ setPending(NothingPending);
+ stopTimers();
+
+ switch (privateState()) {
+ case GroundState:
+ case LoadingState:
+ case StoppedState:
+ case ErrorState:
+ // Do nothing
+ break;
+
+ case PlayingState:
+ case BufferingState:
+ case PausedState:
+ doStop();
+ changeState(StoppedState);
+ break;
+
+ // Protection against adding new states and forgetting to update this switch
+ default:
+ TRACE_PANIC(InvalidStatePanic);
+ }
+
+ TRACE_EXIT("state %d", privateState());
+}
+
+void MMF::AbstractMediaPlayer::seek(qint64 ms)
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::seek, EAudioApi);
+ TRACE_ENTRY("state %d pos %Ld", state(), ms);
+
+ switch (privateState()) {
+ // Fallthrough all these
+ case GroundState:
+ case StoppedState:
+ case PausedState:
+ case PlayingState:
+ case LoadingState:
+ {
+ bool wasPlaying = false;
+ if (state() == PlayingState) {
+ stopPositionTimer();
+ doPause();
+ wasPlaying = true;
+ }
+
+ doSeek(ms);
+ m_position = ms;
+ resetMarksIfRewound();
+
+ if(wasPlaying && state() != ErrorState) {
+ doPlay();
+ startPositionTimer();
+ }
+
+ break;
+ }
+ case BufferingState:
+ // Fallthrough
+ case ErrorState:
+ // Do nothing
+ break;
+ }
+
+ TRACE_EXIT_0();
+}
+
+bool MMF::AbstractMediaPlayer::isSeekable() const
+{
+ return true;
+}
+
+qint64 MMF::AbstractMediaPlayer::currentTime() const
+{
+ return m_position;
+}
+
+void MMF::AbstractMediaPlayer::doSetTickInterval(qint32 interval)
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::doSetTickInterval, EAudioApi);
+ TRACE_ENTRY("state %d m_interval %d interval %d", privateState(), tickInterval(), interval);
+
+ m_positionTimer->setInterval(interval);
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractMediaPlayer::open()
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::open, EAudioApi);
+ const MediaSource source = m_parent->source();
+ TRACE_ENTRY("state %d source.type %d", privateState(), source.type());
+
+ close();
+ changeState(GroundState);
+
+ TInt symbianErr = KErrNone;
+ QString errorMessage;
+
+ switch (source.type()) {
+ case MediaSource::LocalFile: {
+ RFile *const file = m_parent->file();
+ Q_ASSERT(file);
+ symbianErr = openFile(*file);
+ if (KErrNone != symbianErr)
+ errorMessage = tr("Error opening file");
+ break;
+ }
+
+ case MediaSource::Url: {
+ const QUrl url(source.url());
+ if (url.scheme() == QLatin1String("file")) {
+ RFile *const file = m_parent->file();
+ Q_ASSERT(file);
+ symbianErr = openFile(*file);
+ if (KErrNone != symbianErr)
+ errorMessage = tr("Error opening file");
+ }
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ else if (url.scheme() == QLatin1String("http")) {
+ Q_ASSERT(!m_download);
+ m_download = new Download(url, this);
+ connect(m_download, SIGNAL(lengthChanged(qint64)),
+ this, SLOT(downloadLengthChanged(qint64)));
+ connect(m_download, SIGNAL(stateChanged(Download::State)),
+ this, SLOT(downloadStateChanged(Download::State)));
+ int iap = m_parent->currentIAP();
+ TRACE("HTTP Url: Using IAP %d", iap);
+ m_download->start(iap);
+ }
+#endif
+ else {
+ int iap = m_parent->currentIAP();
+ TRACE("Using IAP %d", iap);
+ symbianErr = openUrl(url.toString(), iap);
+ if (KErrNone != symbianErr)
+ errorMessage = tr("Error opening URL");
+ }
+
+ break;
+ }
+
+ case MediaSource::Stream: {
+ QResource *const resource = m_parent->resource();
+ if (resource) {
+ m_buffer.Set(resource->data(), resource->size());
+ symbianErr = openDescriptor(m_buffer);
+ if (KErrNone != symbianErr)
+ errorMessage = tr("Error opening resource");
+ } else {
+ errorMessage = tr("Error opening source: resource not opened");
+ }
+ break;
+ }
+
+ // Other source types are handled in MediaObject::createPlayer
+
+ // Protection against adding new media types and forgetting to update this switch
+ default:
+ TRACE_PANIC(InvalidMediaTypePanic);
+ }
+
+ if (errorMessage.isEmpty()) {
+ changeState(LoadingState);
+ } else {
+ if (symbianErr)
+ setError(errorMessage, symbianErr);
+ else
+ setError(errorMessage);
+ }
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractMediaPlayer::close()
+{
+ doClose();
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ delete m_download;
+ m_download = 0;
+#endif
+ m_position = 0;
+}
+
+void MMF::AbstractMediaPlayer::volumeChanged(qreal volume)
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::volumeChanged, EAudioInternal);
+ TRACE_ENTRY("state %d", privateState());
+
+ AbstractPlayer::volumeChanged(volume);
+ doVolumeChanged();
+
+ TRACE_EXIT_0();
+}
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractMediaPlayer::startPositionTimer()
+{
+ m_positionTimer->start(tickInterval());
+}
+
+void MMF::AbstractMediaPlayer::stopPositionTimer()
+{
+ m_positionTimer->stop();
+}
+
+void MMF::AbstractMediaPlayer::startBufferStatusTimer()
+{
+ m_bufferStatusTimer->start(BufferStatusTimerInterval);
+}
+
+void MMF::AbstractMediaPlayer::stopBufferStatusTimer()
+{
+ m_bufferStatusTimer->stop();
+}
+
+void MMF::AbstractMediaPlayer::stopTimers()
+{
+ stopPositionTimer();
+ stopBufferStatusTimer();
+}
+
+void MMF::AbstractMediaPlayer::doVolumeChanged()
+{
+ switch (privateState()) {
+ case GroundState:
+ case LoadingState:
+ case ErrorState:
+ // Do nothing
+ break;
+
+ case StoppedState:
+ case PausedState:
+ case PlayingState:
+ case BufferingState: {
+ const qreal volume = (m_volume * m_mmfMaxVolume) + 0.5;
+ const int err = setDeviceVolume(volume);
+
+ if (KErrNone != err) {
+ setError(tr("Setting volume failed"), err);
+ }
+ break;
+ }
+
+ // Protection against adding new states and forgetting to update this
+ // switch
+ default:
+ Utils::panic(InvalidStatePanic);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Protected functions
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractMediaPlayer::bufferingStarted()
+{
+ m_stateBeforeBuffering = privateState();
+ changeState(BufferingState);
+ bufferStatusTick();
+ startBufferStatusTimer();
+}
+
+void MMF::AbstractMediaPlayer::bufferingComplete()
+{
+ stopBufferStatusTimer();
+ emit MMF::AbstractPlayer::bufferStatus(100);
+ if (!progressiveDownloadStalled())
+ changeState(m_stateBeforeBuffering);
+}
+
+void MMF::AbstractMediaPlayer::maxVolumeChanged(int mmfMaxVolume)
+{
+ m_mmfMaxVolume = mmfMaxVolume;
+ doVolumeChanged();
+}
+
+void MMF::AbstractMediaPlayer::loadingComplete(int error)
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::loadingComplete, EAudioApi);
+ TRACE_ENTRY("state %d error %d", state(), error);
+ if (progressiveDownloadStalled()) {
+ Q_ASSERT(Phonon::BufferingState == state());
+ if (KErrNone == error) {
+ bufferingComplete();
+ doSeek(m_position);
+ startPlayback();
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ m_downloadStalled = false;
+#endif
+ }
+ } else {
+ Q_ASSERT(Phonon::LoadingState == state());
+ if (KErrNone == error) {
+ updateMetaData();
+ changeState(StoppedState);
+ } else {
+ if (isProgressiveDownload() && KErrCorrupt == error) {
+ setProgressiveDownloadStalled();
+ } else {
+ setError(tr("Loading clip failed"), error);
+ }
+ }
+ }
+}
+
+void MMF::AbstractMediaPlayer::playbackComplete(int error)
+{
+ stopTimers();
+
+ if (KErrNone == error && !m_aboutToFinishSent) {
+ const qint64 total = totalTime();
+ emit MMF::AbstractPlayer::tick(total);
+ m_aboutToFinishSent = true;
+ emit aboutToFinish();
+ }
+
+ if (KErrNone == error) {
+ changeState(PausedState);
+
+ // MediaObject::switchToNextSource deletes the current player, so we
+ // call it via delayed slot invokation to ensure that this object does
+ // not get deleted during execution of a member function.
+ QMetaObject::invokeMethod(m_parent, "switchToNextSource", Qt::QueuedConnection);
+ }
+ else {
+ if (isProgressiveDownload() && KErrCorrupt == error) {
+ setProgressiveDownloadStalled();
+ } else {
+ setError(tr("Playback complete"), error);
+ emit finished();
+ }
+ }
+}
+
+qint64 MMF::AbstractMediaPlayer::toMilliSeconds(const TTimeIntervalMicroSeconds &in)
+{
+ return in.Int64() / 1000;
+}
+
+bool MMF::AbstractMediaPlayer::isProgressiveDownload() const
+{
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ return (0 != m_download);
+#else
+ return false;
+#endif
+}
+
+bool MMF::AbstractMediaPlayer::progressiveDownloadStalled() const
+{
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ return m_downloadStalled;
+#else
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Slots
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractMediaPlayer::positionTick()
+{
+ const qint64 pos = getCurrentTime();
+ if (pos > m_position) {
+ m_position = pos;
+ emitMarksIfReached(m_position);
+ emit MMF::AbstractPlayer::tick(m_position);
+ }
+}
+
+void MMF::AbstractMediaPlayer::emitMarksIfReached(qint64 current)
+{
+ const qint64 total = totalTime();
+ const qint64 remaining = total - current;
+
+ if (prefinishMark() && !m_prefinishMarkSent) {
+ if (remaining < (prefinishMark() + tickInterval()/2)) {
+ m_prefinishMarkSent = true;
+ emit prefinishMarkReached(remaining);
+ }
+ }
+
+ if (!m_aboutToFinishSent) {
+ if (remaining < tickInterval()) {
+ m_aboutToFinishSent = true;
+ emit aboutToFinish();
+ }
+ }
+}
+
+void MMF::AbstractMediaPlayer::resetMarksIfRewound()
+{
+ const qint64 current = getCurrentTime();
+ const qint64 total = totalTime();
+ const qint64 remaining = total - current;
+
+ if (prefinishMark() && m_prefinishMarkSent)
+ if (remaining >= (prefinishMark() + tickInterval()/2))
+ m_prefinishMarkSent = false;
+
+ if (m_aboutToFinishSent)
+ if (remaining >= tickInterval())
+ m_aboutToFinishSent = false;
+}
+
+void MMF::AbstractMediaPlayer::setPending(Pending pending)
+{
+ const Phonon::State oldState = state();
+ m_pending = pending;
+ const Phonon::State newState = state();
+ if (newState != oldState)
+ emit stateChanged(newState, oldState);
+}
+
+void MMF::AbstractMediaPlayer::startPlayback()
+{
+ doPlay();
+ startPositionTimer();
+ changeState(PlayingState);
+}
+
+void MMF::AbstractMediaPlayer::setProgressiveDownloadStalled()
+{
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ TRACE_CONTEXT(AbstractMediaPlayer::setProgressiveDownloadStalled, EAudioApi);
+ TRACE_ENTRY("state %d", state());
+ Q_ASSERT(isProgressiveDownload());
+ m_downloadStalled = true;
+ doClose();
+ bufferingStarted();
+ // Video player loses window handle when closed - need to reapply it here
+ videoOutputChanged();
+ m_download->resume();
+#endif
+}
+
+void MMF::AbstractMediaPlayer::bufferStatusTick()
+{
+ // During progressive download, there is no way to detect the buffering status.
+ // Phonon does not support a "buffering; amount unknown" signal, therefore we
+ // return a buffering status of zero.
+ const int status = progressiveDownloadStalled() ? 0 : bufferStatus();
+ emit MMF::AbstractPlayer::bufferStatus(status);
+}
+
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+void MMF::AbstractMediaPlayer::downloadLengthChanged(qint64 length)
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::downloadLengthChanged, EAudioApi);
+ TRACE_ENTRY("length %Ld", length);
+ Q_UNUSED(length)
+ if (m_downloadStalled) {
+ bufferingComplete();
+ int err = m_parent->openFileHandle(m_download->targetFileName());
+ if (KErrNone == err)
+ err = openFile(*m_parent->file());
+ if (KErrNone != err)
+ setError(tr("Error opening file"));
+ }
+}
+
+void MMF::AbstractMediaPlayer::downloadStateChanged(Download::State state)
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::downloadStateChanged, EAudioApi);
+ TRACE_ENTRY("state %d", state);
+ switch (state) {
+ case Download::Idle:
+ case Download::Initializing:
+ break;
+ case Download::Downloading:
+ {
+ int err = m_parent->openFileHandle(m_download->targetFileName());
+ if (KErrNone == err)
+ err = openFile(*m_parent->file());
+ else if (KErrCorrupt == err)
+ // Insufficient data downloaded - enter Buffering state
+ setProgressiveDownloadStalled();
+ if (KErrNone != err)
+ setError(tr("Error opening file"));
+ }
+ break;
+ case Download::Complete:
+ break;
+ case Download::Error:
+ setError(tr("Download error"));
+ break;
+ }
+}
+#endif // PHONON_MMF_PROGRESSIVE_DOWNLOAD
+
+Phonon::State MMF::AbstractMediaPlayer::phononState(PrivateState state) const
+{
+ Phonon::State result = AbstractPlayer::phononState(state);
+
+ if (PausePending == m_pending) {
+ Q_ASSERT(Phonon::StoppedState == result || Phonon::LoadingState == result);
+ result = Phonon::PausedState;
+ }
+
+ return result;
+}
+
+void MMF::AbstractMediaPlayer::changeState(PrivateState newState)
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::changeState, EAudioInternal);
+
+ const Phonon::State oldPhononState = phononState(privateState());
+ const Phonon::State newPhononState = phononState(newState);
+
+ if (LoadingState == oldPhononState && StoppedState == newPhononState) {
+ switch (m_pending) {
+ case NothingPending:
+ AbstractPlayer::changeState(newState);
+ break;
+
+ case PlayPending:
+ changeState(PlayingState); // necessary in order to apply initial volume
+ doVolumeChanged();
+ startPlayback();
+ break;
+
+ case PausePending:
+ AbstractPlayer::changeState(PausedState);
+ break;
+ }
+
+ setPending(NothingPending);
+ } else {
+ AbstractPlayer::changeState(newState);
+ }
+}
+
+void MMF::AbstractMediaPlayer::updateMetaData()
+{
+ TRACE_CONTEXT(AbstractMediaPlayer::updateMetaData, EAudioInternal);
+ TRACE_ENTRY_0();
+
+ m_metaData.clear();
+
+ const int numberOfEntries = numberOfMetaDataEntries();
+ for(int i=0; i<numberOfEntries; ++i) {
+ const QPair<QString, QString> entry = metaDataEntry(i);
+
+ // Note that we capitalize the key, as required by the Ogg Vorbis
+ // metadata standard to which Phonon adheres:
+ // http://xiph.org/vorbis/doc/v-comment.html
+ m_metaData.insert(entry.first.toUpper(), entry.second);
+ }
+
+ emit metaDataChanged(m_metaData);
+
+ TRACE_EXIT_0();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/abstractmediaplayer.h b/src/3rdparty/phonon/mmf/abstractmediaplayer.h
new file mode 100644
index 0000000..df0a42f
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractmediaplayer.h
@@ -0,0 +1,161 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ABSTRACTMEDIAPLAYER_H
+#define PHONON_MMF_ABSTRACTMEDIAPLAYER_H
+
+#include <QTimer>
+#include <QScopedPointer>
+#include <e32std.h>
+#include "abstractplayer.h"
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+# include "download.h"
+#endif
+
+class RFile;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+class AudioOutput;
+class MediaObject;
+
+/**
+ * Interface via which MMF client APIs for both audio and video can be
+ * accessed.
+ */
+class AbstractMediaPlayer : public AbstractPlayer
+{
+ Q_OBJECT
+
+protected:
+ AbstractMediaPlayer(MediaObject *parent, const AbstractPlayer *player);
+
+public:
+ virtual void open();
+ virtual void close();
+
+ // MediaObjectInterface
+ virtual void play();
+ virtual void pause();
+ virtual void stop();
+ virtual void seek(qint64 milliseconds);
+ virtual bool isSeekable() const;
+ virtual qint64 currentTime() const;
+ virtual void volumeChanged(qreal volume);
+
+protected:
+ // AbstractPlayer
+ virtual void doSetTickInterval(qint32 interval);
+ virtual Phonon::State phononState(PrivateState state) const;
+ virtual void changeState(PrivateState newState);
+
+ virtual void doPlay() = 0;
+ virtual void doPause() = 0;
+ virtual void doStop() = 0;
+ virtual void doSeek(qint64 pos) = 0;
+ virtual int setDeviceVolume(int mmfVolume) = 0;
+ virtual int openFile(const QString &fileName) = 0;
+ virtual int openFile(RFile& file) = 0;
+ virtual int openUrl(const QString& url, int iap) = 0;
+ virtual int openDescriptor(const TDesC8 &des) = 0;
+ virtual int bufferStatus() const = 0;
+ virtual void doClose() = 0;
+
+ void updateMetaData();
+ virtual qint64 getCurrentTime() const = 0;
+ virtual int numberOfMetaDataEntries() const = 0;
+ virtual QPair<QString, QString> metaDataEntry(int index) const = 0;
+
+protected:
+ void bufferingStarted();
+ void bufferingComplete();
+ void maxVolumeChanged(int maxVolume);
+ void loadingComplete(int error);
+ void playbackComplete(int error);
+
+ static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &);
+
+ bool isProgressiveDownload() const;
+ bool progressiveDownloadStalled() const;
+
+private:
+ void startPositionTimer();
+ void stopPositionTimer();
+ void startBufferStatusTimer();
+ void stopBufferStatusTimer();
+ void stopTimers();
+ void doVolumeChanged();
+ void emitMarksIfReached(qint64 position);
+ void resetMarksIfRewound();
+ void startPlayback();
+ void setProgressiveDownloadStalled();
+
+ enum Pending {
+ NothingPending,
+ PausePending,
+ PlayPending
+ };
+
+ void setPending(Pending pending);
+
+private Q_SLOTS:
+ void positionTick();
+ void bufferStatusTick();
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ void downloadLengthChanged(qint64);
+ void downloadStateChanged(Download::State);
+#endif
+
+private:
+ MediaObject *const m_parent;
+
+ Pending m_pending;
+
+ QScopedPointer<QTimer> m_positionTimer;
+ qint64 m_position;
+
+ QScopedPointer<QTimer> m_bufferStatusTimer;
+ PrivateState m_stateBeforeBuffering;
+
+ int m_mmfMaxVolume;
+
+ bool m_prefinishMarkSent;
+ bool m_aboutToFinishSent;
+
+ // Used for playback of resource files
+ TPtrC8 m_buffer;
+
+#ifdef PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ Download *m_download;
+ bool m_downloadStalled;
+#endif
+
+ QMultiMap<QString, QString> m_metaData;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/abstractplayer.cpp b/src/3rdparty/phonon/mmf/abstractplayer.cpp
new file mode 100644
index 0000000..77d7ae0
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractplayer.cpp
@@ -0,0 +1,199 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "abstractplayer.h"
+#include "defs.h"
+#include "utils.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AbstractPlayer
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::AbstractPlayer::AbstractPlayer(const AbstractPlayer *player)
+ : m_videoOutput(0)
+ , m_volume(InitialVolume)
+ , m_state(GroundState)
+ , m_error(NoError)
+ , m_tickInterval(DefaultTickInterval)
+ , m_transitionTime(0)
+ , m_prefinishMark(0)
+{
+ if(player) {
+ m_videoOutput = player->m_videoOutput;
+ m_volume = player->m_volume;
+ m_tickInterval = player->m_tickInterval;
+ m_transitionTime = player->m_transitionTime;
+ m_prefinishMark = player->m_prefinishMark;
+
+ // This is to prevent unwanted state transitions occurring as a result
+ // of MediaObject::switchToNextSource() during playlist playback.
+ if (StoppedState == player->m_state)
+ m_state = player->m_state;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// MediaObjectInterface
+//-----------------------------------------------------------------------------
+
+qint32 MMF::AbstractPlayer::tickInterval() const
+{
+ return m_tickInterval;
+}
+
+void MMF::AbstractPlayer::setTickInterval(qint32 interval)
+{
+ m_tickInterval = interval;
+ doSetTickInterval(interval);
+}
+
+qint32 MMF::AbstractPlayer::prefinishMark() const
+{
+ return m_prefinishMark;
+}
+
+void MMF::AbstractPlayer::setPrefinishMark(qint32 mark)
+{
+ m_prefinishMark = mark;
+}
+
+qint32 MMF::AbstractPlayer::transitionTime() const
+{
+ return m_transitionTime;
+}
+
+void MMF::AbstractPlayer::setTransitionTime(qint32 time)
+{
+ m_transitionTime = time;
+}
+
+void MMF::AbstractPlayer::volumeChanged(qreal volume)
+{
+ m_volume = volume;
+}
+
+
+//-----------------------------------------------------------------------------
+// Video output
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractPlayer::setVideoOutput(AbstractVideoOutput* videoOutput)
+{
+ m_videoOutput = videoOutput;
+ videoOutputChanged();
+}
+
+void MMF::AbstractPlayer::videoOutputChanged()
+{
+ // Default behaviour is empty - overridden by VideoPlayer
+}
+
+void MMF::AbstractPlayer::setError(const QString &errorMessage)
+{
+ TRACE_CONTEXT(AbstractPlayer::setError, EAudioInternal);
+ TRACE_ENTRY("state %d", m_state);
+
+ m_error = Phonon::NormalError;
+ m_errorString = errorMessage;
+ changeState(ErrorState);
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractPlayer::setError(const QString &errorMessage, int symbianError)
+{
+ setError(errorMessage + ": " + Utils::symbianErrorToString(symbianError));
+}
+
+Phonon::ErrorType MMF::AbstractPlayer::errorType() const
+{
+ const Phonon::ErrorType result = (ErrorState == m_state)
+ ? m_error : NoError;
+ return result;
+}
+
+QString MMF::AbstractPlayer::errorString() const
+{
+ return m_errorString;
+}
+
+Phonon::State MMF::AbstractPlayer::phononState() const
+{
+ return phononState(m_state);
+}
+
+Phonon::State MMF::AbstractPlayer::phononState(PrivateState state) const
+{
+ const Phonon::State phononState =
+ GroundState == state
+ ? Phonon::LoadingState
+ : static_cast<Phonon::State>(state);
+
+ return phononState;
+}
+
+AbstractPlayer::PrivateState AbstractPlayer::privateState() const
+{
+ return m_state;
+}
+
+Phonon::State MMF::AbstractPlayer::state() const
+{
+ return phononState(m_state);
+}
+
+void MMF::AbstractPlayer::setState(PrivateState newState)
+{
+ m_state = newState;
+}
+
+void MMF::AbstractPlayer::changeState(PrivateState newState)
+{
+ TRACE_CONTEXT(AbstractPlayer::changeState, EAudioInternal);
+ TRACE_ENTRY("state %d newState %d", privateState(), newState);
+
+ // TODO: add some invariants to check that the transition is valid
+
+ const Phonon::State oldPhononState = phononState(privateState());
+
+ // We need to change the state before we emit stateChanged(), because
+ // some user code, for instance the mediaplayer, switch on MediaObject's
+ // state.
+ setState(newState);
+
+ const Phonon::State newPhononState = phononState(newState);
+
+ if (oldPhononState != newPhononState) {
+ TRACE("emit stateChanged(%d, %d)", newPhononState, oldPhononState);
+ emit stateChanged(newPhononState, oldPhononState);
+ }
+
+ TRACE_EXIT_0();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h
new file mode 100644
index 0000000..dd98c7c
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractplayer.h
@@ -0,0 +1,176 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ABSTRACTPLAYER_H
+#define PHONON_MMF_ABSTRACTPLAYER_H
+
+#include <phonon/phononnamespace.h>
+#include <phonon/mediasource.h>
+
+#include <QObject>
+
+#include "abstractvideooutput.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short Interface which abstracts from MediaObject the current
+ * media type
+ *
+ * This may be:
+ * - Nothing, in which case this interface is implemented by
+ * DummyPlayer
+ * - Audio, in which case the implementation is AudioPlayer
+ * - Video, in which case the implementation is VideoPlayer
+ */
+class AbstractPlayer : public QObject
+{
+ // Required although this class has no signals or slots
+ // Without this, qobject_cast will fail
+ Q_OBJECT
+
+public:
+ AbstractPlayer(const AbstractPlayer *player);
+
+ virtual void open() = 0;
+ virtual void close() = 0;
+
+ // MediaObjectInterface (implemented)
+ qint32 tickInterval() const;
+ void setTickInterval(qint32);
+ void setTransitionTime(qint32);
+ qint32 transitionTime() const;
+ void setPrefinishMark(qint32);
+ qint32 prefinishMark() const;
+
+ // MediaObjectInterface (abstract)
+ virtual void play() = 0;
+ virtual void pause() = 0;
+ virtual void stop() = 0;
+ virtual void seek(qint64 milliseconds) = 0;
+ virtual bool hasVideo() const = 0;
+ virtual bool isSeekable() const = 0;
+ virtual qint64 currentTime() const = 0;
+ virtual Phonon::ErrorType errorType() const;
+ virtual QString errorString() const;
+ virtual qint64 totalTime() const = 0;
+
+ virtual void volumeChanged(qreal volume);
+
+ void setVideoOutput(AbstractVideoOutput *videoOutput);
+
+ /**
+ * Records error message and changes state to ErrorState
+ */
+ void setError(const QString &errorMessage);
+
+ /**
+ * Records error message and changes state to ErrorState
+ *
+ * Appends a human-readable version of symbianErrorCode to the error message,
+ * e.g.
+ * @code
+ * setError("Opening file failed", KErrPermissionDenied)
+ * @endcode
+ * results in the following error message:
+ * "Opening file failed: permission denied"
+ */
+ void setError(const QString &errorMessage, int symbianErrorCode);
+
+ Phonon::State state() const;
+
+Q_SIGNALS:
+ void totalTimeChanged(qint64 length);
+ void finished();
+ void tick(qint64 time);
+ void bufferStatus(int percentFilled);
+ void stateChanged(Phonon::State newState,
+ Phonon::State oldState);
+ void metaDataChanged(const QMultiMap<QString, QString>& metaData);
+ void aboutToFinish();
+ void prefinishMarkReached(qint32 remaining);
+
+protected:
+ /**
+ * Defined private state enumeration in order to add GroundState
+ */
+ enum PrivateState {
+ LoadingState = Phonon::LoadingState,
+ StoppedState = Phonon::StoppedState,
+ PlayingState = Phonon::PlayingState,
+ BufferingState = Phonon::BufferingState,
+ PausedState = Phonon::PausedState,
+ ErrorState = Phonon::ErrorState,
+ GroundState
+ };
+
+ /**
+ * Converts PrivateState into the corresponding Phonon::State
+ */
+ Phonon::State phononState() const;
+
+ /**
+ * Converts PrivateState into the corresponding Phonon::State
+ */
+ virtual Phonon::State phononState(PrivateState state) const;
+
+ virtual void videoOutputChanged();
+
+ PrivateState privateState() const;
+
+ /**
+ * Changes state and emits stateChanged()
+ */
+ virtual void changeState(PrivateState newState);
+
+ /**
+ * Modifies m_state directly. Typically you want to call changeState(),
+ * which performs the business logic.
+ */
+ void setState(PrivateState newState);
+
+private:
+ virtual void doSetTickInterval(qint32 interval) = 0;
+
+protected:
+ // Not owned
+ AbstractVideoOutput* m_videoOutput;
+
+ qreal m_volume;
+
+private:
+ PrivateState m_state;
+ Phonon::ErrorType m_error;
+ QString m_errorString;
+ qint32 m_tickInterval;
+ qint32 m_transitionTime;
+ qint32 m_prefinishMark;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/abstractvideooutput.cpp b/src/3rdparty/phonon/mmf/abstractvideooutput.cpp
new file mode 100644
index 0000000..068118b
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractvideooutput.cpp
@@ -0,0 +1,172 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "abstractvideooutput.h"
+#include "utils.h"
+
+#ifndef QT_NO_DEBUG
+#include "objectdump.h"
+#endif
+
+#include <QtCore/private/qcore_symbian_p.h> // for qt_TSize2QSize
+
+#include <QMoveEvent>
+#include <QResizeEvent>
+
+#include <QApplication> // for QApplication::activeWindow
+
+#include <coecntrl.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AbstractVideoOutput
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------------
+
+static const Phonon::VideoWidget::AspectRatio DefaultAspectRatio =
+ Phonon::VideoWidget::AspectRatioAuto;
+static const Phonon::VideoWidget::ScaleMode DefaultScaleMode =
+ Phonon::VideoWidget::FitInView;
+
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::AbstractVideoOutput::AbstractVideoOutput(QWidget *parent)
+ : QWidget(parent)
+ , m_aspectRatio(DefaultAspectRatio)
+ , m_scaleMode(DefaultScaleMode)
+{
+ // Ensure that this widget has a native window handle
+ winId();
+}
+
+MMF::AbstractVideoOutput::~AbstractVideoOutput()
+{
+
+}
+
+void MMF::AbstractVideoOutput::setVideoSize(const QSize &frameSize)
+{
+ TRACE_CONTEXT(AbstractVideoOutput::setVideoSize, EVideoInternal);
+ TRACE("oldSize %d %d newSize %d %d",
+ m_videoFrameSize.width(), m_videoFrameSize.height(),
+ frameSize.width(), frameSize.height());
+
+ if (frameSize != m_videoFrameSize) {
+ m_videoFrameSize = frameSize;
+ updateGeometry();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// QWidget
+//-----------------------------------------------------------------------------
+
+QSize MMF::AbstractVideoOutput::sizeHint() const
+{
+ // TODO: replace this with a more sensible default
+ QSize result(320, 240);
+
+ if (!m_videoFrameSize.isNull())
+ result = m_videoFrameSize;
+
+ return result;
+}
+
+
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+RWindowBase* MMF::AbstractVideoOutput::videoWindow() const
+{
+ CCoeControl *control = internalWinId();
+ if (!control)
+ control = effectiveWinId();
+
+ RWindowBase *window = 0;
+ if (control)
+ window = control->DrawableWindow();
+
+ return window;
+}
+
+QSize MMF::AbstractVideoOutput::videoWindowSize() const
+{
+ QSize result;
+ if (RWindowBase *const window = videoWindow())
+ result = qt_TSize2QSize(window->Size());
+ return result;
+}
+
+Phonon::VideoWidget::AspectRatio MMF::AbstractVideoOutput::aspectRatio() const
+{
+ return m_aspectRatio;
+}
+
+void MMF::AbstractVideoOutput::setAspectRatio
+ (Phonon::VideoWidget::AspectRatio aspectRatio)
+{
+ if (m_aspectRatio != aspectRatio) {
+ m_aspectRatio = aspectRatio;
+ emit aspectRatioChanged();
+ }
+}
+
+Phonon::VideoWidget::ScaleMode MMF::AbstractVideoOutput::scaleMode() const
+{
+ return m_scaleMode;
+}
+
+void MMF::AbstractVideoOutput::setScaleMode
+ (Phonon::VideoWidget::ScaleMode scaleMode)
+{
+ if (m_scaleMode != scaleMode) {
+ m_scaleMode = scaleMode;
+ emit scaleModeChanged();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoOutput::dump() const
+{
+#ifndef QT_NO_DEBUG
+ TRACE_CONTEXT(AbstractVideoOutput::dump, EVideoInternal);
+ QScopedPointer<ObjectDump::QVisitor> visitor(new ObjectDump::QVisitor);
+ visitor->setPrefix("Phonon::MMF"); // to aid searchability of logs
+ ObjectDump::addDefaultAnnotators(*visitor);
+ ObjectDump::dumpTreeFromLeaf(*this, *visitor);
+#endif
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/abstractvideooutput.h b/src/3rdparty/phonon/mmf/abstractvideooutput.h
new file mode 100644
index 0000000..61bcd0f
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractvideooutput.h
@@ -0,0 +1,93 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ABSTRACTVIDEOOUTPUT_H
+#define PHONON_MMF_ABSTRACTVIDEOOUTPUT_H
+
+#include <QtGui/QWidget>
+#include <QVector>
+#include <QRect>
+#include "defs.h"
+
+#include <phonon/abstractvideooutput.h>
+#include <phonon/videowidget.h>
+
+#include <e32std.h>
+class RWindowBase;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short ABC for widget on which video is displayed
+ *
+ * @see DsaVideoOutput, SurfaceVideoOutput
+ */
+class AbstractVideoOutput
+ : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ~AbstractVideoOutput();
+
+ // Set size of video frame. Called by VideoPlayer.
+ void setVideoSize(const QSize &size);
+
+ RWindowBase* videoWindow() const;
+ QSize videoWindowSize() const;
+
+ Phonon::VideoWidget::AspectRatio aspectRatio() const;
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio);
+
+ Phonon::VideoWidget::ScaleMode scaleMode() const;
+ void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode);
+
+ // Debugging output
+ void dump() const;
+
+Q_SIGNALS:
+ void videoWindowChanged();
+ void aspectRatioChanged();
+ void scaleModeChanged();
+
+protected:
+ AbstractVideoOutput(QWidget *parent);
+
+private:
+ // QWidget
+ QSize sizeHint() const;
+
+private:
+ // Dimensions of the video clip
+ QSize m_videoFrameSize;
+
+ Phonon::VideoWidget::AspectRatio m_aspectRatio;
+ Phonon::VideoWidget::ScaleMode m_scaleMode;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
new file mode 100644
index 0000000..ad4ee83
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp
@@ -0,0 +1,518 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QDir>
+#include <QUrl>
+#include <QTimer>
+#include <QWidget>
+
+#include <coemain.h> // for CCoeEnv
+
+#include "abstractvideoplayer.h"
+#include "utils.h"
+
+#ifndef QT_NO_DEBUG
+#include "objectdump.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AbstractVideoPlayer
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::AbstractVideoPlayer::AbstractVideoPlayer(MediaObject *parent, const AbstractPlayer *player)
+ : AbstractMediaPlayer(parent, player)
+ , m_wsSession(CCoeEnv::Static()->WsSession())
+ , m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
+ , m_window(0)
+ , m_scaleWidth(1.0)
+ , m_scaleHeight(1.0)
+ , m_totalTime(0)
+{
+
+}
+
+void MMF::AbstractVideoPlayer::construct()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::AbstractVideoPlayer, EVideoApi);
+ TRACE_ENTRY_0();
+
+ if (m_videoOutput) {
+ initVideoOutput();
+ m_window = m_videoOutput->videoWindow();
+ }
+
+ createPlayer();
+
+ m_player->RegisterForVideoLoadingNotification(*this);
+
+ TRACE_EXIT_0();
+}
+
+MMF::AbstractVideoPlayer::~AbstractVideoPlayer()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::~AbstractVideoPlayer, EVideoApi);
+ TRACE_ENTRY_0();
+
+ // QObject destructor removes all signal-slot connections involving this
+ // object, so we do not need to disconnect from m_videoOutput here.
+
+ TRACE_EXIT_0();
+}
+
+CVideoPlayerUtility* MMF::AbstractVideoPlayer::nativePlayer() const
+{
+ return m_player.data();
+}
+
+//-----------------------------------------------------------------------------
+// Public API
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::doPlay()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::doPlay, EVideoApi);
+
+ handlePendingParametersChanged();
+
+ m_player->Play();
+}
+
+void MMF::AbstractVideoPlayer::doPause()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::doPause, EVideoApi);
+
+ TRAPD(err, m_player->PauseL());
+ if (KErrNone != err && state() != ErrorState) {
+ TRACE("PauseL error %d", err);
+ setError(tr("Pause failed"), err);
+ }
+}
+
+void MMF::AbstractVideoPlayer::doStop()
+{
+ m_player->Stop();
+}
+
+void MMF::AbstractVideoPlayer::doSeek(qint64 ms)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::doSeek, EVideoApi);
+
+ TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000)));
+
+ if (KErrNone != err)
+ setError(tr("Seek failed"), err);
+}
+
+int MMF::AbstractVideoPlayer::setDeviceVolume(int mmfVolume)
+{
+ TRAPD(err, m_player->SetVolumeL(mmfVolume));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::openFile(const QString &fileName)
+{
+ const QHBufC nativeFileName(QDir::toNativeSeparators(fileName));
+ TRAPD(err, m_player->OpenFileL(*nativeFileName));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::openFile(RFile &file)
+{
+ TRAPD(err, m_player->OpenFileL(file));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::openUrl(const QString &url, int iap)
+{
+ TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url), iap));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::openDescriptor(const TDesC8 &des)
+{
+ TRAPD(err, m_player->OpenDesL(des));
+ return err;
+}
+
+int MMF::AbstractVideoPlayer::bufferStatus() const
+{
+ int result = 0;
+ TRAP_IGNORE(m_player->GetVideoLoadingProgressL(result));
+ return result;
+}
+
+void MMF::AbstractVideoPlayer::doClose()
+{
+ m_player->Close();
+}
+
+bool MMF::AbstractVideoPlayer::hasVideo() const
+{
+ return true;
+}
+
+qint64 MMF::AbstractVideoPlayer::getCurrentTime() const
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::getCurrentTime, EVideoApi);
+
+ TTimeIntervalMicroSeconds us;
+ TRAPD(err, us = m_player->PositionL())
+
+ qint64 result = 0;
+
+ if (KErrNone == err) {
+ result = toMilliSeconds(us);
+ } else {
+ TRACE("PositionL error %d", err);
+
+ // If we don't cast away constness here, we simply have to ignore
+ // the error.
+ const_cast<AbstractVideoPlayer*>(this)->setError(tr("Getting position failed"), err);
+ }
+
+ return result;
+}
+
+qint64 MMF::AbstractVideoPlayer::totalTime() const
+{
+ return m_totalTime;
+}
+
+
+//-----------------------------------------------------------------------------
+// Public slots
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::videoWindowChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::videoWindowChanged, EVideoInternal);
+ TRACE_ENTRY("state %d", state());
+
+ m_window = m_videoOutput ? m_videoOutput->videoWindow() : 0;
+
+ if (m_videoOutput)
+ m_videoOutput->dump();
+
+ handleVideoWindowChanged();
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::aspectRatioChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::aspectRatioChanged, EVideoInternal);
+ TRACE_ENTRY("state %d aspectRatio %d", state());
+
+ if (m_videoOutput)
+ updateScaleFactors(m_videoOutput->videoWindowSize());
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::scaleModeChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::scaleModeChanged, EVideoInternal);
+ TRACE_ENTRY("state %d", state());
+
+ if (m_videoOutput)
+ updateScaleFactors(m_videoOutput->videoWindowSize());
+
+ TRACE_EXIT_0();
+}
+
+
+//-----------------------------------------------------------------------------
+// MVideoPlayerUtilityObserver callbacks
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::MvpuoOpenComplete(TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoOpenComplete, EVideoApi);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ __ASSERT_ALWAYS(LoadingState == state() ||
+ progressiveDownloadStalled() && BufferingState == state(),
+ Utils::panic(InvalidStatePanic));
+
+ if (KErrNone == aError)
+ m_player->Prepare();
+ else
+ setError(tr("Opening clip failed"), aError);
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::MvpuoPrepareComplete(TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPrepareComplete, EVideoApi);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ __ASSERT_ALWAYS(LoadingState == state() ||
+ progressiveDownloadStalled() && BufferingState == state(),
+ Utils::panic(InvalidStatePanic));
+
+ TRAPD(err, getVideoClipParametersL(aError));
+
+ if (KErrNone == err) {
+ if (m_videoOutput)
+ m_videoOutput->dump();
+
+ maxVolumeChanged(m_player->MaxVolume());
+
+ if (m_videoOutput)
+ m_videoOutput->setVideoSize(m_videoFrameSize);
+
+ prepareCompleted();
+ handlePendingParametersChanged();
+
+ emit totalTimeChanged(totalTime());
+ }
+
+ loadingComplete(aError);
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::getVideoClipParametersL(TInt aError)
+{
+ User::LeaveIfError(aError);
+
+ // Get frame size
+ TSize size;
+ m_player->VideoFrameSizeL(size);
+ m_videoFrameSize = QSize(size.iWidth, size.iHeight);
+
+ // Get duration
+ m_totalTime = toMilliSeconds(m_player->DurationL());
+}
+
+
+void MMF::AbstractVideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoFrameReady, EVideoApi);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ Q_UNUSED(aFrame);
+ Q_UNUSED(aError); // suppress warnings in release builds
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::MvpuoPlayComplete(TInt aError)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPlayComplete, EVideoApi)
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ // Call base class function which handles end of playback for both
+ // audio and video clips.
+ playbackComplete(aError);
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::MvpuoEvent, EVideoApi);
+ TRACE_ENTRY("state %d", state());
+
+ Q_UNUSED(aEvent);
+
+ TRACE_EXIT_0();
+}
+
+
+//-----------------------------------------------------------------------------
+// MVideoLoadingObserver callbacks
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::MvloLoadingStarted()
+{
+ bufferingStarted();
+}
+
+void MMF::AbstractVideoPlayer::MvloLoadingComplete()
+{
+ bufferingComplete();
+}
+
+
+//-----------------------------------------------------------------------------
+// Video window updates
+//-----------------------------------------------------------------------------
+
+void MMF::AbstractVideoPlayer::videoOutputChanged()
+{
+ TRACE_CONTEXT(AbstractVideoPlayer::videoOutputChanged, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ if (m_videoOutput)
+ initVideoOutput();
+
+ videoWindowChanged();
+
+ TRACE_EXIT_0();
+}
+
+void MMF::AbstractVideoPlayer::initVideoOutput()
+{
+ Q_ASSERT(m_videoOutput);
+
+ bool connected = connect(
+ m_videoOutput, SIGNAL(videoWindowChanged()),
+ this, SLOT(videoWindowChanged())
+ );
+ Q_ASSERT(connected);
+
+ connected = connect(
+ m_videoOutput, SIGNAL(aspectRatioChanged()),
+ this, SLOT(aspectRatioChanged())
+ );
+ Q_ASSERT(connected);
+
+ connected = connect(
+ m_videoOutput, SIGNAL(scaleModeChanged()),
+ this, SLOT(scaleModeChanged())
+ );
+ Q_ASSERT(connected);
+
+ // Suppress warnings in release builds
+ Q_UNUSED(connected);
+
+ m_videoOutput->setVideoSize(m_videoFrameSize);
+}
+
+// Helper function for aspect ratio / scale mode handling
+QSize scaleToAspect(const QSize &srcRect, int aspectWidth, int aspectHeight)
+{
+ const qreal aspectRatio = qreal(aspectWidth) / aspectHeight;
+
+ int width = srcRect.width();
+ int height = srcRect.width() / aspectRatio;
+ if (height > srcRect.height()){
+ height = srcRect.height();
+ width = srcRect.height() * aspectRatio;
+ }
+ return QSize(width, height);
+}
+
+void MMF::AbstractVideoPlayer::updateScaleFactors(const QSize &windowSize, bool apply)
+{
+ Q_ASSERT(m_videoOutput);
+
+ if (m_videoFrameSize.isValid()) {
+ QRect videoRect;
+
+ // Calculate size of smallest rect which contains video frame size
+ // and conforms to aspect ratio
+ switch (m_videoOutput->aspectRatio()) {
+ case Phonon::VideoWidget::AspectRatioAuto:
+ videoRect.setSize(m_videoFrameSize);
+ break;
+
+ case Phonon::VideoWidget::AspectRatioWidget:
+ videoRect.setSize(windowSize);
+ break;
+
+ case Phonon::VideoWidget::AspectRatio4_3:
+ videoRect.setSize(scaleToAspect(m_videoFrameSize, 4, 3));
+ break;
+
+ case Phonon::VideoWidget::AspectRatio16_9:
+ videoRect.setSize(scaleToAspect(m_videoFrameSize, 16, 9));
+ break;
+ }
+
+ // Scale to fill the window width
+ const int windowWidth = windowSize.width();
+ const int windowHeight = windowSize.height();
+ const qreal windowScaleFactor = qreal(windowWidth) / videoRect.width();
+ int videoWidth = windowWidth;
+ int videoHeight = videoRect.height() * windowScaleFactor;
+
+ const qreal windowToVideoHeightRatio = qreal(windowHeight) / videoHeight;
+
+ switch (m_videoOutput->scaleMode()) {
+ case Phonon::VideoWidget::ScaleAndCrop:
+ if (videoHeight < windowHeight) {
+ videoWidth *= windowToVideoHeightRatio;
+ videoHeight = windowHeight;
+ }
+ break;
+ case Phonon::VideoWidget::FitInView:
+ default:
+ if (videoHeight > windowHeight) {
+ videoWidth *= windowToVideoHeightRatio;
+ videoHeight = windowHeight;
+ }
+ break;
+ }
+
+ // Calculate scale factors
+ m_scaleWidth = 100.0f * videoWidth / m_videoFrameSize.width();
+ m_scaleHeight = 100.0f * videoHeight / m_videoFrameSize.height();
+
+ if (apply)
+ parametersChanged(ScaleFactors);
+ }
+}
+
+void MMF::AbstractVideoPlayer::parametersChanged(VideoParameters parameters)
+{
+ if (state() == LoadingState || progressiveDownloadStalled() && BufferingState == state())
+ m_pendingChanges |= parameters;
+ else
+ handleParametersChanged(parameters);
+}
+
+void MMF::AbstractVideoPlayer::handlePendingParametersChanged()
+{
+ if (m_pendingChanges)
+ handleParametersChanged(m_pendingChanges);
+ m_pendingChanges = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Metadata
+//-----------------------------------------------------------------------------
+
+int MMF::AbstractVideoPlayer::numberOfMetaDataEntries() const
+{
+ int numberOfEntries = 0;
+ TRAP_IGNORE(numberOfEntries = m_player->NumberOfMetaDataEntriesL());
+ return numberOfEntries;
+}
+
+QPair<QString, QString> MMF::AbstractVideoPlayer::metaDataEntry(int index) const
+{
+ CMMFMetaDataEntry *entry = 0;
+ QT_TRAP_THROWING(entry = m_player->MetaDataEntryL(index));
+ return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value()));
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.h b/src/3rdparty/phonon/mmf/abstractvideoplayer.h
new file mode 100644
index 0000000..21446d2
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.h
@@ -0,0 +1,173 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ABSTRACTVIDEOPLAYER_H
+#define PHONON_MMF_ABSTRACTVIDEOPLAYER_H
+
+#include <videoplayer.h> // from epoc32/include
+
+#include <QSize>
+
+#include "abstractmediaplayer.h"
+#include "abstractvideooutput.h"
+#include "defs.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short ABC for classes which wrap the MMF video player utility
+ *
+ * On devices which use the legacy graphics subsystem which does not
+ * support surfaces, video rendering is done via Direct Screen Access using
+ * the CVideoPlayerUtility API. On devices with a graphics subsystem which
+ * does support surfaces, video rendering is done using the
+ * CVideoPlayerUtility2 API. Because CVideoPlayerUtility2 inherits from
+ * CVideoPlayerUtility, AbstractVideoPlayer holds a pointer to the latter.
+ *
+ * @see DsaVideoPlayer, SurfaceVideoPlayer
+ */
+class AbstractVideoPlayer
+ : public AbstractMediaPlayer
+ , public MVideoPlayerUtilityObserver
+ , public MVideoLoadingObserver
+{
+ Q_OBJECT
+
+public:
+ ~AbstractVideoPlayer();
+
+ typedef CVideoPlayerUtility NativePlayer;
+ NativePlayer *nativePlayer() const;
+
+ // AbstractPlayer
+ virtual void doPlay();
+ virtual void doPause();
+ virtual void doStop();
+ virtual void doSeek(qint64 milliseconds);
+ virtual int setDeviceVolume(int mmfVolume);
+ virtual int openFile(const QString &fileName);
+ virtual int openFile(RFile &file);
+ virtual int openUrl(const QString &url, int iap);
+ virtual int openDescriptor(const TDesC8 &des);
+ virtual int bufferStatus() const;
+ virtual void doClose();
+
+ // MediaObjectInterface
+ virtual bool hasVideo() const;
+ virtual qint64 totalTime() const;
+
+ // AbstractPlayer
+ virtual void videoOutputChanged();
+
+ // AbstractMediaPlayer
+ virtual qint64 getCurrentTime() const;
+ virtual int numberOfMetaDataEntries() const;
+ virtual QPair<QString, QString> metaDataEntry(int index) const;
+
+public Q_SLOTS:
+ void videoWindowChanged();
+ void aspectRatioChanged();
+ void scaleModeChanged();
+
+protected:
+ AbstractVideoPlayer(MediaObject *parent, const AbstractPlayer *player);
+ void construct();
+ virtual void initVideoOutput();
+ void updateScaleFactors(const QSize &windowSize, bool apply = true);
+
+ // Called when a video parameter changes. If the underlying native API is
+ // ready to handle the change, it is propagated immediately, otherwise the
+ // change is recorded in m_pendingChanged and handled later by
+ // handlePendingParametersChanged().
+ void parametersChanged(VideoParameters parameter);
+
+ // Implementation must initialize the m_player pointer.
+ virtual void createPlayer() = 0;
+
+ // Called from the MvpuoPrepareComplete callback. Allows derived class to
+ // calculate clipping rectangles and scale factors prior to starting
+ // playback.
+ virtual void prepareCompleted() = 0;
+
+ // Called when native video window handle changes. Derived class may defer
+ // propagation of this change to the MMF video player utility by calling
+ // parametersChanged().
+ virtual void handleVideoWindowChanged() = 0;
+
+ // Called when the derived class must handle changes which have been made
+ // to video parameters such as window handle, screen rectangle and scale
+ // factors. Guaranteed to be called only when the underlying MMF video
+ // player object is ready to handle changes to these parameters.
+ virtual void handleParametersChanged(VideoParameters parameters) = 0;
+
+private:
+ void getVideoClipParametersL(TInt aError);
+
+ // Called when native player API enters a state in which it is able to
+ // handle pending changes such as new video window handle, updated scale
+ // factors etc.
+ void handlePendingParametersChanged();
+
+private:
+ // MVideoPlayerUtilityObserver
+ virtual void MvpuoOpenComplete(TInt aError);
+ virtual void MvpuoPrepareComplete(TInt aError);
+ virtual void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError);
+ virtual void MvpuoPlayComplete(TInt aError);
+ virtual void MvpuoEvent(const TMMFEvent &aEvent);
+
+ // MVideoLoadingObserver
+ virtual void MvloLoadingStarted();
+ virtual void MvloLoadingComplete();
+
+protected:
+ QScopedPointer<NativePlayer> m_player;
+
+ // Not owned
+ RWsSession& m_wsSession;
+ CWsScreenDevice& m_screenDevice;
+ RWindowBase* m_window;
+
+ // Scaling factors for video display, expressed as percentages
+ TReal32 m_scaleWidth;
+ TReal32 m_scaleHeight;
+
+ // Dimensions of the video clip
+ QSize m_videoFrameSize;
+
+private:
+ // Bitmask of parameters which have changed while the MMF video player
+ // object is not yet ready to receive these changes.
+ // See handlePendingParametersChanged().
+ VideoParameters m_pendingChanges;
+
+ // Duration of the video clip
+ qint64 m_totalTime;
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp
new file mode 100644
index 0000000..f0d1be2
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp
@@ -0,0 +1,179 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "ancestormovemonitor.h"
+#include "utils.h"
+
+#include "videooutput_dsa.h"
+
+#include <QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon::MMF;
+
+/*! \class Phonon::MMF::AncestorMoveMonitor
+ \internal
+ \brief Class which installs a global event filter, and listens for move
+ events which may affect the absolute position of widgets registered with
+ the monitor
+ See QTBUG-4956
+*/
+
+
+/*! \class Phonon::MMF::VideoOutputObserver
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+AncestorMoveMonitor::AncestorMoveMonitor(QObject *parent)
+ : QObject(parent)
+{
+ QCoreApplication::instance()->installEventFilter(this);
+}
+
+AncestorMoveMonitor::~AncestorMoveMonitor()
+{
+ QCoreApplication::instance()->removeEventFilter(this);
+}
+
+
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+void AncestorMoveMonitor::registerTarget(DsaVideoOutput *target)
+{
+ TRACE_CONTEXT(AncestorMoveMonitor::registerTarget, EVideoInternal);
+ TRACE_ENTRY("target 0x%08x", target);
+
+ // First un-register the target, in case this is being called as a result
+ // of re-parenting. This is not the most efficient way to update the
+ // target hash, but since this is not likely to be a frequent operation,
+ // simplicity is preferred over outright speed. In any case, re-parenting
+ // of the video widget leads to re-creation of native windows, which is
+ // likely to take far more processing than any implementation of this
+ // function.
+ unRegisterTarget(target);
+
+ QWidget *ancestor = target->parentWidget();
+ while(ancestor) {
+ const Hash::iterator it = m_hash.find(ancestor);
+ if(m_hash.end() == it) {
+ TargetList targetList;
+ targetList.append(target);
+ m_hash.insert(ancestor, targetList);
+ } else {
+ TargetList& targetList = it.value();
+ Q_ASSERT(targetList.indexOf(target) == -1);
+ targetList.append(target);
+ }
+ ancestor = ancestor->parentWidget();
+ }
+
+ dump();
+
+ TRACE_EXIT_0();
+}
+
+void AncestorMoveMonitor::unRegisterTarget(DsaVideoOutput *target)
+{
+ TRACE_CONTEXT(AncestorMoveMonitor::unRegisterTarget, EVideoInternal);
+ TRACE_ENTRY("target 0x%08x", target);
+
+ Hash::iterator it = m_hash.begin();
+ while(it != m_hash.end()) {
+ TargetList& targetList = it.value();
+ const int index = targetList.indexOf(target);
+ if(index != -1)
+ targetList.removeAt(index);
+ if(targetList.count())
+ ++it;
+ else
+ it = m_hash.erase(it);
+ }
+
+ dump();
+
+ TRACE_EXIT_0();
+}
+
+bool AncestorMoveMonitor::eventFilter(QObject *watched, QEvent *event)
+{
+ TRACE_CONTEXT(AncestorMoveMonitor::eventFilter, EVideoInternal);
+
+ if(event->type() == QEvent::Move || event->type() == QEvent::ParentChange) {
+
+ //TRACE_ENTRY("watched 0x%08x event.type %d", watched, event->type());
+
+ const Hash::const_iterator it = m_hash.find(watched);
+ if(it != m_hash.end()) {
+ const TargetList& targetList = it.value();
+ DsaVideoOutput* target = 0;
+ foreach(target, targetList) {
+ switch (event->type()) {
+
+ case QEvent::Move:
+ // Notify the target that its ancestor has moved
+ target->ancestorMoved();
+ break;
+
+ case QEvent::ParentChange:
+ // Update ancestor list for the target
+ registerTarget(target);
+ break;
+
+ default:
+ Q_ASSERT(false);
+ }
+ }
+ }
+
+ //TRACE_EXIT_0();
+ }
+
+ // The event is never consumed by this filter
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+void AncestorMoveMonitor::dump()
+{
+#ifndef QT_NO_DEBUG
+ TRACE_CONTEXT(AncestorMoveMonitor::dump, EVideoInternal);
+ for(Hash::const_iterator it = m_hash.begin();
+ it != m_hash.end(); ++it) {
+ const QObject *ancestor = it.key();
+ TRACE("ancestor 0x%08x", ancestor);
+ const TargetList& targetList = it.value();
+ DsaVideoOutput* target = 0;
+ foreach(target, targetList) {
+ TRACE(" target 0x%08x", target);
+ }
+ }
+#endif
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/ancestormovemonitor.h b/src/3rdparty/phonon/mmf/ancestormovemonitor.h
new file mode 100644
index 0000000..f3a022d
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/ancestormovemonitor.h
@@ -0,0 +1,95 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ANCESTORMOVEMONITOR_H
+#define PHONON_MMF_ANCESTORMOVEMONITOR_H
+
+#include <QObject>
+#include <QHash>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+class DsaVideoOutput;
+
+class AncestorMoveMonitor : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit AncestorMoveMonitor(QObject *parent);
+ ~AncestorMoveMonitor();
+
+ /**
+ * Register target widget for notification.
+ *
+ * The widget receives an ancestorMoveEvent callback when a move event
+ * is delivered to any of its ancestors:
+ *
+ * If the target is already registered, this function causes its
+ * ancestor list to be updated - therefore it should be called when
+ * the target receives a ParentChange event.
+ */
+ void registerTarget(DsaVideoOutput *target);
+
+ /**
+ * Remove target from the monitor.
+ *
+ * The target will no longer receive notification when move events are
+ * delivered to its ancestors.
+ */
+ void unRegisterTarget(DsaVideoOutput *target);
+
+protected:
+ /**
+ * Function which receives events from the global event filter.
+ */
+ bool eventFilter(QObject *watched, QEvent *event);
+
+ void dump();
+
+private:
+ /**
+ * List of registered target widgets which descend from a given
+ * ancestor.
+ *
+ * Note that the members of the list should be non-redundant; this
+ * invariant is checked in debug builds. Semantically, the value is
+ * therefore a set, however we use QList rather than QSet for
+ * efficiency of iteration.
+ */
+ typedef QList<DsaVideoOutput *> TargetList;
+
+ /**
+ * Map from widget on which the move event occurs, to widgets which
+ * descend from it and therefore need to be notified.
+ */
+ typedef QHash<QObject *, TargetList> Hash;
+ Hash m_hash;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif // !PHONON_MMF_ANCESTORMOVEMONITOR_H
diff --git a/src/3rdparty/phonon/mmf/audioequalizer.cpp b/src/3rdparty/phonon/mmf/audioequalizer.cpp
new file mode 100644
index 0000000..1d2bbd4
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/audioequalizer.cpp
@@ -0,0 +1,106 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <AudioEqualizerBase.h>
+#include "audioequalizer.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AudioEqualizer
+ \internal
+*/
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(AudioEqualizer)
+
+AudioEqualizer::AudioEqualizer(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+int AudioEqualizer::effectParameterChanged(const EffectParameter &param,
+ const QVariant &value)
+{
+ const int band = param.id() - ParameterBase + 1;
+
+ const qreal externalLevel = value.toReal();
+ const int internalLevel = param.toInternalValue(externalLevel);
+
+ TRAPD(err, concreteEffect()->SetBandLevelL(band, internalLevel));
+ return err;
+}
+
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* AudioEqualizer::description()
+{
+ return "Audio equalizer";
+}
+
+bool AudioEqualizer::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters)
+{
+ bool supported = false;
+
+ QScopedPointer<CAudioEqualizer> effect;
+ TRAPD(err, effect.reset(CAudioEqualizer::NewL(*stream)));
+
+ if (KErrNone == err) {
+ supported = true;
+
+ TInt32 dbMin;
+ TInt32 dbMax;
+ effect->DbLevelLimits(dbMin, dbMax);
+
+ const int bandCount = effect->NumberOfBands();
+
+ for (int i = 0; i < bandCount; ++i) {
+ // For some reason, band IDs are 1-based, as opposed to the
+ // 0-based indices used in just about other Symbian API...!
+ const int band = i + 1;
+
+ const qint32 hz = effect->CenterFrequency(band);
+
+ // We pass a floating-point parameter range of -1.0 to +1.0 for
+ // each band in order to work around a limitation in
+ // Phonon::EffectWidget. See documentation of EffectParameter
+ // for more details.
+ EffectParameter param(
+ /* parameterId */ ParameterBase + i,
+ /* name */ tr("%1 Hz").arg(hz),
+ /* hints */ EffectParameter::LogarithmicHint,
+ /* defaultValue */ QVariant(qreal(0.0)),
+ /* minimumValue */ QVariant(qreal(-1.0)),
+ /* maximumValue */ QVariant(qreal(+1.0)));
+
+ param.setInternalRange(dbMin, dbMax);
+ parameters.append(param);
+ }
+ }
+
+ return supported;
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/audioequalizer.h b/src/3rdparty/phonon/mmf/audioequalizer.h
new file mode 100644
index 0000000..9c3770a
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/audioequalizer.h
@@ -0,0 +1,67 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_AUDIOEQUALIZER_H
+#define PHONON_MMF_AUDIOEQUALIZER_H
+
+#include "abstractaudioeffect.h"
+
+class CAudioEqualizer;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A classic equalizer.
+ *
+ * The equalizer has a number of bands, and each band has a frequency, and a
+ * volume. With Phonon's API, this is modeled such that each band is one
+ * Phonon::EffectParameter, where Phonon::EffectParameter::id() is the band
+ * number, and the setting is the volume level.
+ */
+class AudioEqualizer : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ AudioEqualizer(QObject *parent, const QList<EffectParameter> &parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+ virtual int effectParameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+private:
+ CAudioEqualizer *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp
new file mode 100644
index 0000000..3588683
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/audiooutput.cpp
@@ -0,0 +1,114 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <e32debug.h>
+
+#include <QCoreApplication>
+
+#include "audiooutput.h"
+#include "defs.h"
+#include "mediaobject.h"
+#include "utils.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AudioOutput
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::AudioOutput::AudioOutput(Backend *, QObject *parent) : MediaNode(parent)
+ , m_volume(InitialVolume)
+{
+
+}
+
+
+//-----------------------------------------------------------------------------
+// Public API
+//-----------------------------------------------------------------------------
+
+qreal MMF::AudioOutput::volume() const
+{
+ return m_volume;
+}
+
+void MMF::AudioOutput::setVolume(qreal volume)
+{
+ TRACE_CONTEXT(AudioOutput::setVolume, EAudioApi);
+ TRACE_ENTRY("volume %f", volume);
+
+ if (volume != m_volume) {
+
+ m_volume = volume;
+ TRACE("emit volumeChanged(%f)", volume)
+ emit volumeChanged(volume);
+ }
+
+ TRACE_EXIT_0();
+}
+
+int MMF::AudioOutput::outputDevice() const
+{
+ return AudioOutputDeviceID;
+}
+
+bool MMF::AudioOutput::setOutputDevice(int index)
+{
+ Q_ASSERT_X(index == AudioOutputDeviceID, Q_FUNC_INFO,
+ "We only support one output device, with id 0");
+#ifdef QT_NO_DEBUG
+ Q_UNUSED(index)
+#endif
+ return true;
+}
+
+void MMF::AudioOutput::connectMediaObject(MediaObject *mediaObject)
+{
+ // Ensure that the MediaObject has the correct initial volume
+ mediaObject->volumeChanged(m_volume);
+ // Connect MediaObject to receive future volume changes
+ connect(this, SIGNAL(volumeChanged(qreal)), mediaObject, SLOT(volumeChanged(qreal)));
+}
+
+void MMF::AudioOutput::disconnectMediaObject(MediaObject *mediaObject)
+{
+ // Disconnect all signal-slot connections
+ disconnect(this, 0, mediaObject, 0);
+}
+
+QHash<QByteArray, QVariant> MMF::AudioOutput::audioOutputDescription(int index)
+{
+ QHash<QByteArray, QVariant> retval;
+
+ if (index == AudioOutputDeviceID) {
+ retval.insert("name", QCoreApplication::translate("Phonon::MMF", "Audio Output"));
+ retval.insert("description", QCoreApplication::translate("Phonon::MMF", "The audio output device"));
+ retval.insert("available", true);
+ }
+
+ return retval;
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/audiooutput.h b/src/3rdparty/phonon/mmf/audiooutput.h
new file mode 100644
index 0000000..67aaa38
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/audiooutput.h
@@ -0,0 +1,94 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_AUDIOOUTPUT_H
+#define PHONON_MMF_AUDIOOUTPUT_H
+
+#include <QHash>
+
+#include "mmf_medianode.h"
+#include <phonon/audiooutputinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+class Backend;
+
+/**
+ * @short AudioOutputInterface implementation for MMF.
+ *
+ * Forwards volume commands to the MediaObject instance,
+ * which is provided by the backend when MediaNode objects are
+ * connected.
+ *
+ * \section volume Volume
+ *
+ * Phonon's concept on volume is from 0.0 to 1.0, and from 1< it does
+ * voltage multiplication. CDrmPlayerUtility goes from 1 to
+ * CDrmPlayerUtility::MaxVolume(). We apply some basic math to convert
+ * between the two.
+ *
+ * @author Frans Englich<frans.englich@nokia.com>
+ */
+class AudioOutput : public MediaNode
+ , public AudioOutputInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioOutputInterface)
+
+public:
+ AudioOutput(Backend *backend, QObject *parent);
+ virtual qreal volume() const;
+ virtual void setVolume(qreal volume);
+
+ virtual int outputDevice() const;
+
+ /**
+ * Has no effect.
+ */
+ virtual bool setOutputDevice(int);
+
+ static QHash<QByteArray, QVariant> audioOutputDescription(int index);
+
+ enum Constants
+ {
+ AudioOutputDeviceID = 0
+ };
+
+protected:
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
+
+Q_SIGNALS:
+ void volumeChanged(qreal volume);
+ void audioDeviceFailed();
+
+private:
+ qreal m_volume;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/audioplayer.cpp b/src/3rdparty/phonon/mmf/audioplayer.cpp
new file mode 100644
index 0000000..2ae6a3d
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/audioplayer.cpp
@@ -0,0 +1,293 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QDir>
+#include <QUrl>
+
+#include "audioplayer.h"
+#include "utils.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::AudioPlayer
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::AudioPlayer::AudioPlayer(MediaObject *parent, const AbstractPlayer *player)
+ : AbstractMediaPlayer(parent, player)
+ , m_totalTime(0)
+{
+ construct();
+}
+
+void MMF::AudioPlayer::construct()
+{
+ TRACE_CONTEXT(AudioPlayer::AudioPlayer, EAudioApi);
+ TRACE_ENTRY_0();
+
+ NativePlayer *player = 0;
+ QT_TRAP_THROWING(player = NativePlayer::NewL(*this, 0, EMdaPriorityPreferenceNone));
+ m_player.reset(player);
+ m_player->RegisterForAudioLoadingNotification(*this);
+
+ TRACE_EXIT_0();
+}
+
+MMF::AudioPlayer::~AudioPlayer()
+{
+ TRACE_CONTEXT(AudioPlayer::~AudioPlayer, EAudioApi);
+ TRACE_ENTRY_0();
+
+ TRACE_EXIT_0();
+}
+
+MMF::AudioPlayer::NativePlayer *MMF::AudioPlayer::nativePlayer() const
+{
+ return m_player.data();
+}
+
+//-----------------------------------------------------------------------------
+// Public API
+//-----------------------------------------------------------------------------
+
+void MMF::AudioPlayer::doPlay()
+{
+ m_player->Play();
+}
+
+void MMF::AudioPlayer::doPause()
+{
+ m_player->Pause();
+}
+
+void MMF::AudioPlayer::doStop()
+{
+ m_player->Stop();
+}
+
+void MMF::AudioPlayer::doSeek(qint64 ms)
+{
+ m_player->SetPosition(TTimeIntervalMicroSeconds(ms * 1000));
+}
+
+int MMF::AudioPlayer::setDeviceVolume(int mmfVolume)
+{
+ /* In SDK 3.1, SetVolume() returns void. If we're compiling against
+ * 3.1, we handle it with ifdefs. However, if we compile against a later
+ * SDK but are _running_ against 3.1, we avoid returning from an undefined
+ * stack by doing a runtime check of the SDK version. */
+#if !defined(__SERIES60_31__)
+ const int err = m_player->SetVolume(mmfVolume);
+ if (QSysInfo::s60Version() >= QSysInfo::SV_S60_3_2)
+ return err;
+ else
+ return KErrNone;
+ #else
+ m_player->SetVolume(mmfVolume);
+ return KErrNone;
+#endif
+}
+
+int MMF::AudioPlayer::openFile(const QString &fileName)
+{
+ const QHBufC nativeFileName(QDir::toNativeSeparators(fileName));
+ TRAPD(err, m_player->OpenFileL(*nativeFileName));
+ return err;
+}
+
+int MMF::AudioPlayer::openFile(RFile& file)
+{
+ TRAPD(err, m_player->OpenFileL(file));
+
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+ if (KErrNone == err) {
+ // There appears to be a bug in the CDrmPlayerUtility implementation (at least
+ // in S60 5.x) whereby the player does not check whether the loading observer
+ // pointer is null before dereferencing it. Therefore we must register for
+ // loading notification, even though we do nothing in the callback functions.
+ m_player->RegisterForAudioLoadingNotification(*this);
+ }
+#endif
+
+ return err;
+}
+
+int MMF::AudioPlayer::openUrl(const QString& /*url*/, int /*iap*/)
+{
+ // Streaming playback is generally not supported by the implementation
+ // of the audio player API, so we use CVideoPlayerUtility for both
+ // audio and video streaming.
+ Utils::panic(AudioUtilityUrlNotSupported);
+
+ // Silence warning
+ return 0;
+}
+
+int MMF::AudioPlayer::openDescriptor(const TDesC8 &des)
+{
+ TRAPD(err, m_player->OpenDesL(des));
+ return err;
+}
+
+int MMF::AudioPlayer::bufferStatus() const
+{
+ int result = 0;
+ TRAP_IGNORE(m_player->GetAudioLoadingProgressL(result));
+ return result;
+}
+
+void MMF::AudioPlayer::doClose()
+{
+ m_player->Close();
+}
+
+bool MMF::AudioPlayer::hasVideo() const
+{
+ return false;
+}
+
+qint64 MMF::AudioPlayer::getCurrentTime() const
+{
+ TRACE_CONTEXT(AudioPlayer::getCurrentTime, EAudioApi);
+
+ TTimeIntervalMicroSeconds us;
+ const TInt err = m_player->GetPosition(us);
+
+ qint64 result = 0;
+
+ if (KErrNone == err) {
+ result = toMilliSeconds(us);
+ } else {
+ TRACE("GetPosition err %d", err);
+
+ // If we don't cast away constness here, we simply have to ignore
+ // the error.
+ const_cast<AudioPlayer*>(this)->setError(tr("Getting position failed"), err);
+ }
+
+ return result;
+}
+
+qint64 MMF::AudioPlayer::totalTime() const
+{
+ return m_totalTime;
+}
+
+
+//-----------------------------------------------------------------------------
+// Symbian multimedia client observer callbacks
+//-----------------------------------------------------------------------------
+
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+void MMF::AudioPlayer::MdapcInitComplete(TInt aError,
+ const TTimeIntervalMicroSeconds &)
+#else
+void MMF::AudioPlayer::MapcInitComplete(TInt aError,
+ const TTimeIntervalMicroSeconds &)
+#endif
+{
+ TRACE_CONTEXT(AudioPlayer::MapcInitComplete, EAudioInternal);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ __ASSERT_ALWAYS(LoadingState == state() ||
+ progressiveDownloadStalled() && BufferingState == state(),
+ Utils::panic(InvalidStatePanic));
+
+ if (KErrNone == aError) {
+ maxVolumeChanged(m_player->MaxVolume());
+ m_totalTime = toMilliSeconds(m_player->Duration());
+ emit totalTimeChanged(m_totalTime);
+ }
+
+ loadingComplete(aError);
+
+ TRACE_EXIT_0();
+}
+
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+void MMF::AudioPlayer::MdapcPlayComplete(TInt aError)
+#else
+void MMF::AudioPlayer::MapcPlayComplete(TInt aError)
+#endif
+{
+ TRACE_CONTEXT(AudioPlayer::MapcPlayComplete, EAudioInternal);
+ TRACE_ENTRY("state %d error %d", state(), aError);
+
+ // Call base class function which handles end of playback for both
+ // audio and video clips.
+ playbackComplete(aError);
+
+ TRACE_EXIT_0();
+}
+
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+void MMF::AudioPlayer::MaloLoadingStarted()
+{
+
+}
+
+void MMF::AudioPlayer::MaloLoadingComplete()
+{
+
+}
+#endif // QT_PHONON_MMF_AUDIO_DRM
+
+
+//-----------------------------------------------------------------------------
+// MAudioLoadingObserver callbacks
+//-----------------------------------------------------------------------------
+
+void MMF::AudioPlayer::MaloLoadingStarted()
+{
+ bufferingStarted();
+}
+
+void MMF::AudioPlayer::MaloLoadingComplete()
+{
+ bufferingComplete();
+}
+
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+int MMF::AudioPlayer::numberOfMetaDataEntries() const
+{
+ int numberOfEntries = 0;
+ m_player->GetNumberOfMetaDataEntries(numberOfEntries); // ignoring return code
+ return numberOfEntries;
+}
+
+QPair<QString, QString> MMF::AudioPlayer::metaDataEntry(int index) const
+{
+ CMMFMetaDataEntry *entry = 0;
+ QT_TRAP_THROWING(entry = m_player->GetMetaDataEntryL(index));
+ return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value()));
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/audioplayer.h b/src/3rdparty/phonon/mmf/audioplayer.h
new file mode 100644
index 0000000..e963c26
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/audioplayer.h
@@ -0,0 +1,124 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_AUDIOPLAYER_H
+#define PHONON_MMF_AUDIOPLAYER_H
+
+#include "abstractmediaplayer.h"
+
+class CDrmPlayerUtility;
+class TTimeIntervalMicroSeconds;
+
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+#include <drmaudiosampleplayer.h>
+typedef MDrmAudioPlayerCallback NativePlayerObserver;
+#else
+#include <mdaaudiosampleplayer.h>
+typedef MMdaAudioPlayerCallback NativePlayerObserver;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short Wrapper over MMF audio client utility
+ */
+class AudioPlayer : public AbstractMediaPlayer
+ , public NativePlayerObserver
+ , public MAudioLoadingObserver
+{
+ Q_OBJECT
+
+public:
+ AudioPlayer(MediaObject *parent = 0, const AbstractPlayer *player = 0);
+ virtual ~AudioPlayer();
+
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+typedef CDrmPlayerUtility NativePlayer;
+#else
+typedef CMdaAudioPlayerUtility NativePlayer;
+#endif
+
+ NativePlayer *nativePlayer() const;
+
+ // AbstractMediaPlayer
+ virtual void doPlay();
+ virtual void doPause();
+ virtual void doStop();
+ virtual void doSeek(qint64 milliseconds);
+ virtual int setDeviceVolume(int mmfVolume);
+ virtual int openFile(const QString &fileName);
+ virtual int openFile(RFile& file);
+ virtual int openUrl(const QString& url, int iap);
+ virtual int openDescriptor(const TDesC8 &des);
+ virtual int bufferStatus() const;
+ virtual void doClose();
+
+ // MediaObjectInterface
+ virtual bool hasVideo() const;
+ virtual qint64 totalTime() const;
+
+ // AbstractMediaPlayer
+ virtual qint64 getCurrentTime() const;
+ virtual int numberOfMetaDataEntries() const;
+ virtual QPair<QString, QString> metaDataEntry(int index) const;
+
+ /**
+ * This class owns the pointer.
+ */
+ NativePlayer *player() const;
+
+private:
+ void construct();
+
+private:
+#ifdef QT_PHONON_MMF_AUDIO_DRM
+ // MDrmAudioPlayerCallback
+ virtual void MdapcInitComplete(TInt aError,
+ const TTimeIntervalMicroSeconds &aDuration);
+ virtual void MdapcPlayComplete(TInt aError);
+#else
+ // MMdaAudioPlayerCallback
+ virtual void MapcInitComplete(TInt aError,
+ const TTimeIntervalMicroSeconds &aDuration);
+ virtual void MapcPlayComplete(TInt aError);
+#endif
+
+ // MAudioLoadingObserver
+ virtual void MaloLoadingStarted();
+ virtual void MaloLoadingComplete();
+
+private:
+ /**
+ * Using CPlayerType typedef in order to be able to easily switch between
+ * CMdaAudioPlayerUtility and CDrmPlayerUtility
+ */
+ QScopedPointer<NativePlayer> m_player;
+
+ qint64 m_totalTime;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp
new file mode 100644
index 0000000..2cec43b
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/backend.cpp
@@ -0,0 +1,223 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QStringList>
+#include <QtPlugin>
+
+#include <apgcli.h> // for RApaLsSession
+#include <apmrec.h> // for CDataTypeArray
+#include <apmstd.h> // for TDataType
+
+#include "abstractaudioeffect.h"
+#include "audiooutput.h"
+#include "audioplayer.h"
+#include "backend.h"
+#include "effectfactory.h"
+#include "mediaobject.h"
+#include "utils.h"
+#include "videowidget.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::Backend
+ \internal
+*/
+
+Backend::Backend(QObject *parent)
+ : QObject(parent)
+#ifndef PHONON_MMF_VIDEO_SURFACES
+ , m_ancestorMoveMonitor(new AncestorMoveMonitor(this))
+#endif
+ , m_effectFactory(new EffectFactory(this))
+{
+ TRACE_CONTEXT(Backend::Backend, EBackend);
+ TRACE_ENTRY_0();
+
+ setProperty("identifier", QLatin1String("phonon_mmf"));
+ setProperty("backendName", QLatin1String("MMF"));
+ setProperty("backendComment", QLatin1String("Backend using Symbian Multimedia Framework (MMF)"));
+ setProperty("backendVersion", QLatin1String("0.1"));
+ setProperty("backendWebsite", QLatin1String("http://qt.nokia.com/"));
+
+ TRACE_EXIT_0();
+}
+
+QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+{
+ TRACE_CONTEXT(Backend::createObject, EBackend);
+ TRACE_ENTRY("class %d", c);
+
+ QObject* result = 0;
+
+ switch (c) {
+ case AudioOutputClass:
+ result = new AudioOutput(this, parent);
+ break;
+
+ case MediaObjectClass:
+ result = new MediaObject(parent);
+ break;
+
+ case VolumeFaderEffectClass:
+ case VisualizationClass:
+ case VideoDataOutputClass:
+ case EffectClass:
+ {
+ Q_ASSERT(args.count() == 1);
+ Q_ASSERT(args.first().type() == QVariant::Int);
+ const EffectFactory::Type type =
+ static_cast<EffectFactory::Type>(args.first().toInt());
+ return m_effectFactory->createAudioEffect(type, parent);
+ }
+
+ case VideoWidgetClass:
+ {
+ VideoWidget *widget = new VideoWidget(qobject_cast<QWidget *>(parent));
+#ifndef PHONON_MMF_VIDEO_SURFACES
+ widget->setAncestorMoveMonitor(m_ancestorMoveMonitor.data());
+#endif
+ result = widget;
+ }
+ break;
+
+ default:
+ TRACE_PANIC(InvalidBackendInterfaceClass);
+ }
+
+ TRACE_RETURN("0x%08x", result);
+}
+
+QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+ TRACE_CONTEXT(Backend::objectDescriptionIndexes, EAudioApi);
+ TRACE_ENTRY_0();
+ QList<int> retval;
+
+ switch(type)
+ {
+ case EffectType:
+ retval.append(m_effectFactory->effectIndexes());
+ break;
+ case AudioOutputDeviceType:
+ // We only have one possible output device, but we need at least
+ // one.
+ retval.append(AudioOutput::AudioOutputDeviceID);
+ break;
+ default:
+ ;
+ }
+
+ TRACE_EXIT_0();
+ return retval;
+}
+
+QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+ TRACE_CONTEXT(Backend::connectNodes, EBackend);
+
+ switch (type) {
+ case EffectType:
+ return m_effectFactory->audioEffectDescriptions(EffectFactory::Type(index));
+ case AudioOutputDeviceType:
+ return AudioOutput::audioOutputDescription(index);
+ default:
+ return QHash<QByteArray, QVariant>();
+ }
+}
+
+bool Backend::startConnectionChange(QSet<QObject *>)
+{
+ return true;
+}
+
+bool Backend::connectNodes(QObject *sourceObject, QObject *targetObject)
+{
+ TRACE_CONTEXT(Backend::connectNodes, EBackend);
+ TRACE_ENTRY("source 0x%08x target 0x%08x", sourceObject, targetObject);
+
+ MediaNode *const source = qobject_cast<MediaNode *>(sourceObject);
+ MediaNode *const target = qobject_cast<MediaNode *>(targetObject);
+
+ Q_ASSERT_X(source, Q_FUNC_INFO, "source is not a MediaNode");
+ Q_ASSERT_X(target, Q_FUNC_INFO, "target is not a MediaNode");
+
+ return source->connectOutput(target);
+}
+
+bool Backend::disconnectNodes(QObject *sourceObject, QObject *targetObject)
+{
+ TRACE_CONTEXT(Backend::disconnectNodes, EBackend);
+ TRACE_ENTRY("source 0x%08x target 0x%08x", sourceObject, targetObject);
+
+ MediaNode *const source = qobject_cast<MediaNode *>(sourceObject);
+ MediaNode *const target = qobject_cast<MediaNode *>(targetObject);
+
+ Q_ASSERT_X(source, Q_FUNC_INFO, "source is not a MediaNode");
+ Q_ASSERT_X(target, Q_FUNC_INFO, "target is not a MediaNode");
+
+ return source->disconnectOutput(target);
+}
+
+bool Backend::endConnectionChange(QSet<QObject *>)
+{
+ return true;
+}
+
+void getAvailableMimeTypesL(QStringList& result)
+{
+ RApaLsSession apaSession;
+ User::LeaveIfError(apaSession.Connect());
+ CleanupClosePushL(apaSession);
+
+ static const TInt DataTypeArrayGranularity = 8;
+ CDataTypeArray* array = new(ELeave) CDataTypeArray(DataTypeArrayGranularity);
+ CleanupStack::PushL(array);
+
+ apaSession.GetSupportedDataTypesL(*array);
+
+ for (TInt i = 0; i < array->Count(); ++i) {
+ const TPtrC mimeType = array->At(i).Des();
+ const MediaType mediaType = Utils::mimeTypeToMediaType(mimeType);
+ if (MediaTypeAudio == mediaType or MediaTypeVideo == mediaType) {
+ result.append(qt_TDesC2QString(mimeType));
+ }
+ }
+
+ CleanupStack::PopAndDestroy(2); // apaSession, array
+}
+
+QStringList Backend::availableMimeTypes() const
+{
+ QStringList result;
+
+ // There is no way to return an error from this function, so we just
+ // have to trap and ignore exceptions...
+ TRAP_IGNORE(getAvailableMimeTypesL(result));
+
+ result.sort();
+
+ return result;
+}
+
+Q_EXPORT_PLUGIN2(phonon_mmf, Phonon::MMF::Backend);
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/backend.h b/src/3rdparty/phonon/mmf/backend.h
new file mode 100644
index 0000000..a45c92a
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/backend.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_BACKEND_H
+#define PHONON_MMF_BACKEND_H
+
+#ifndef PHONON_MMF_VIDEO_SURFACES
+#include "ancestormovemonitor.h"
+#endif
+
+#include "effectfactory.h"
+
+#include <phonon/mediasource.h>
+#include <phonon/backendinterface.h>
+#include <QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+class Backend : public QObject
+ , public BackendInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::BackendInterface)
+public:
+ Backend(QObject *parent = 0);
+
+ virtual QObject *createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args);
+ virtual QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+ virtual QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+ virtual bool startConnectionChange(QSet<QObject *>);
+ virtual bool connectNodes(QObject *, QObject *);
+ virtual bool disconnectNodes(QObject *, QObject *);
+ virtual bool endConnectionChange(QSet<QObject *>);
+ virtual QStringList availableMimeTypes() const;
+
+Q_SIGNALS:
+ void objectDescriptionChanged(ObjectDescriptionType);
+
+private:
+#ifndef PHONON_MMF_VIDEO_SURFACES
+ QScopedPointer<AncestorMoveMonitor> m_ancestorMoveMonitor;
+#endif
+ QScopedPointer<EffectFactory> m_effectFactory;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/bassboost.cpp b/src/3rdparty/phonon/mmf/bassboost.cpp
new file mode 100644
index 0000000..67076f6
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/bassboost.cpp
@@ -0,0 +1,59 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <BassBoostBase.h>
+#include "bassboost.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(BassBoost)
+
+/*! \class MMF::BassBoost
+ \internal
+*/
+
+BassBoost::BassBoost(QObject *parent, const QList<EffectParameter> &parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* BassBoost::description()
+{
+ return "Bass boost";
+}
+
+bool BassBoost::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter> &parameters)
+{
+ Q_UNUSED(parameters)
+ QScopedPointer<CBassBoost> effect;
+ TRAPD(err, effect.reset(CBassBoost::NewL(*stream)));
+ return (KErrNone == err);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/bassboost.h b/src/3rdparty/phonon/mmf/bassboost.h
new file mode 100644
index 0000000..fc40e21
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/bassboost.h
@@ -0,0 +1,60 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_BASSBOOST_H
+#define PHONON_MMF_BASSBOOST_H
+
+#include "abstractaudioeffect.h"
+
+class CBassBoost;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A "bass boost" effect.
+ */
+class BassBoost : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ BassBoost(QObject *parent, const QList<EffectParameter> &parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+
+private:
+ CBassBoost *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/defs.h b/src/3rdparty/phonon/mmf/defs.h
new file mode 100644
index 0000000..1ed8250
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/defs.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_DEFS_H
+#define PHONON_MMF_DEFS_H
+
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+static const qint32 DefaultTickInterval = 10;
+static const qreal InitialVolume = 0.5;
+
+enum MediaType {
+ MediaTypeUnknown,
+ MediaTypeAudio,
+ MediaTypeVideo
+};
+
+enum VideoParameter {
+ WindowHandle = 0x1,
+ WindowScreenRect = 0x2,
+ ScaleFactors = 0x4
+};
+Q_DECLARE_FLAGS(VideoParameters, VideoParameter)
+Q_DECLARE_OPERATORS_FOR_FLAGS(VideoParameters)
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_MMF_DEFS_H
diff --git a/src/3rdparty/phonon/mmf/download.cpp b/src/3rdparty/phonon/mmf/download.cpp
new file mode 100644
index 0000000..f074d7f
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/download.cpp
@@ -0,0 +1,199 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "download.h"
+#include "utils.h"
+#include <QtCore/QDir>
+#include <QtCore/private/qcore_symbian_p.h>
+#include <mmf/common/mmfcontrollerframeworkbase.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+static const TBool InheritDownloads = EFalse;
+
+DownloadPrivate::DownloadPrivate(Download *parent)
+ : QObject(parent)
+ , m_parent(parent)
+ , m_download(0)
+ , m_length(0)
+{
+
+}
+
+DownloadPrivate::~DownloadPrivate()
+{
+ if (m_download)
+ m_download->Delete();
+ m_downloadManager.Disconnect();
+ m_downloadManager.Close();
+}
+
+bool DownloadPrivate::start(int iap)
+{
+ TRACE_CONTEXT(DownloadPrivate::start, EVideoApi);
+ Q_ASSERT(!m_download);
+ // Connect to download manager
+ RProcess process;
+ const TUid uid3 = process.SecureId();
+ TRAPD(err, m_downloadManager.ConnectL(uid3, *this, InheritDownloads));
+ TRACE("connect err %d", err);
+ if (KErrNone == err) {
+ // Start download
+ if (KUseDefaultIap != iap)
+ m_downloadManager.SetIntAttribute(EDlMgrIap, iap);
+ QHBufC url(m_parent->sourceUrl().toString());
+ TPtr8 url8 = url->Des().Collapse();
+ TRAP(err, m_download = &m_downloadManager.CreateDownloadL(url8));
+ TRACE("start err %d", err);
+ if (KErrNone == err)
+ m_download->Start();
+ }
+ return (KErrNone == err);
+}
+
+void DownloadPrivate::resume()
+{
+
+}
+
+void DownloadPrivate::HandleDMgrEventL(RHttpDownload &aDownload, THttpDownloadEvent aEvent)
+{
+ TRACE_CONTEXT(DownloadPrivate::HandleDMgrEventL, EVideoApi);
+ Q_ASSERT(&aDownload == m_download);
+ switch (aEvent.iDownloadState) {
+ case EHttpDlPaused:
+ if (EHttpContentTypeReceived == aEvent.iProgressState) {
+ TRACE_0("paused, content type received");
+ m_download->Start();
+ }
+ break;
+ case EHttpDlInprogress:
+ switch (aEvent.iProgressState) {
+ case EHttpProgResponseHeaderReceived:
+ {
+ TFileName fileName;
+ m_download->GetStringAttribute(EDlAttrDestFilename, fileName);
+ TRACE("in progress, response header received, filename %S", &fileName);
+ const QString fileNameQt = QDir::fromNativeSeparators(qt_TDesC2QString(fileName));
+ m_parent->downloadStarted(fileNameQt);
+ }
+ break;
+ case EHttpProgResponseBodyReceived:
+ {
+ TInt32 length = 0;
+ m_download->GetIntAttribute(EDlAttrDownloadedSize, length);
+ if (length != m_length) {
+ TRACE("in progress, length %d", length);
+ m_length = length;
+ emit lengthChanged(m_length);
+ }
+ }
+ break;
+ }
+ break;
+ case EHttpDlCompleted:
+ TRACE_0("complete");
+ m_parent->complete();
+ break;
+ case EHttpDlFailed:
+ TRACE_0("failed");
+ m_parent->error();
+ break;
+ }
+}
+
+Download::Download(const QUrl &url, QObject *parent)
+ : QObject(parent)
+ , m_private(new DownloadPrivate(this))
+ , m_sourceUrl(url)
+ , m_state(Idle)
+{
+ qRegisterMetaType<Download::State>();
+ connect(m_private, SIGNAL(lengthChanged(qint64)), this, SIGNAL(lengthChanged(qint64)));
+}
+
+Download::~Download()
+{
+
+}
+
+const QUrl &Download::sourceUrl() const
+{
+ return m_sourceUrl;
+}
+
+const QString &Download::targetFileName() const
+{
+ return m_targetFileName;
+}
+
+void Download::start(int iap)
+{
+ TRACE_CONTEXT(Download::start, EVideoApi);
+ TRACE_ENTRY_0();
+ Q_ASSERT(Idle == m_state);
+ const bool ok = m_private->start(iap);
+ setState(ok ? Initializing : Error);
+ TRACE_EXIT_0();
+}
+
+void Download::resume()
+{
+ TRACE_CONTEXT(Download::resume, EVideoApi);
+ TRACE_ENTRY_0();
+ m_private->resume();
+ TRACE_EXIT_0();
+}
+
+void Download::setState(State state)
+{
+ TRACE_CONTEXT(Download::setState, EVideoApi);
+ TRACE("oldState %d newState %d", m_state, state);
+ const State oldState = m_state;
+ m_state = state;
+ if (oldState != m_state)
+ emit stateChanged(m_state);
+}
+
+void Download::error()
+{
+ TRACE_CONTEXT(Download::error, EVideoApi);
+ TRACE_0("");
+ setState(Error);
+}
+
+void Download::downloadStarted(const QString &targetFileName)
+{
+ TRACE_CONTEXT(Download::downloadStarted, EVideoApi);
+ TRACE_0("downloadStarted");
+ m_targetFileName = targetFileName;
+ setState(Downloading);
+}
+
+void Download::complete()
+{
+ TRACE_CONTEXT(Download::complete, EVideoApi);
+ TRACE_0("");
+ setState(Complete);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/download.h b/src/3rdparty/phonon/mmf/download.h
new file mode 100644
index 0000000..2ce54a8
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/download.h
@@ -0,0 +1,109 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_DOWNLOAD_H
+#define PHONON_MMF_DOWNLOAD_H
+
+#include <QtCore/QMetaType>
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+#include <downloadmgrclient.h>
+
+QT_FORWARD_DECLARE_CLASS(QByteArray)
+QT_FORWARD_DECLARE_CLASS(QFile)
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+class Download;
+
+class DownloadPrivate : public QObject
+ , public MHttpDownloadMgrObserver
+{
+ Q_OBJECT
+public:
+ DownloadPrivate(Download *parent);
+ ~DownloadPrivate();
+ bool start(int iap);
+ void resume();
+signals:
+ void error();
+ void targetFileNameChanged();
+ void lengthChanged(qint64 length);
+ void complete();
+private:
+ // MHttpDownloadMgrObserver
+ void HandleDMgrEventL(RHttpDownload &aDownload, THttpDownloadEvent aEvent);
+private:
+ Download *m_parent;
+ RHttpDownloadMgr m_downloadManager;
+ RHttpDownload *m_download;
+ qint64 m_length;
+};
+
+class Download : public QObject
+{
+ Q_OBJECT
+ friend class DownloadPrivate;
+public:
+ Download(const QUrl &url, QObject *parent = 0);
+ ~Download();
+ const QUrl &sourceUrl() const;
+ const QString &targetFileName() const;
+ void start(int iap);
+ void resume();
+
+ enum State {
+ Idle,
+ Initializing,
+ Downloading,
+ Complete,
+ Error
+ };
+
+signals:
+ void lengthChanged(qint64 length);
+ void stateChanged(Download::State state);
+
+private:
+ void setState(State state);
+
+ // Called by DownloadPrivate
+ void error();
+ void downloadStarted(const QString &targetFileName);
+ void complete();
+
+private:
+ DownloadPrivate *m_private;
+ QUrl m_sourceUrl;
+ QString m_targetFileName;
+ State m_state;
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Phonon::MMF::Download::State)
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/dummyplayer.cpp b/src/3rdparty/phonon/mmf/dummyplayer.cpp
new file mode 100644
index 0000000..ba75b02
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/dummyplayer.cpp
@@ -0,0 +1,115 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "dummyplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::DummyPlayer
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::DummyPlayer::DummyPlayer(const AbstractPlayer *player)
+ : AbstractPlayer(player)
+{
+
+}
+
+
+//-----------------------------------------------------------------------------
+// MediaObjectInterface
+//-----------------------------------------------------------------------------
+
+void MMF::DummyPlayer::play()
+{
+
+}
+
+void MMF::DummyPlayer::pause()
+{
+
+}
+
+void MMF::DummyPlayer::stop()
+{
+
+}
+
+void MMF::DummyPlayer::seek(qint64)
+{
+
+}
+
+bool MMF::DummyPlayer::hasVideo() const
+{
+ return false;
+}
+
+bool MMF::DummyPlayer::isSeekable() const
+{
+ return false;
+}
+
+Phonon::State MMF::DummyPlayer::state() const
+{
+ return Phonon::LoadingState;
+}
+
+qint64 MMF::DummyPlayer::currentTime() const
+{
+ return 0;
+}
+
+Phonon::ErrorType MMF::DummyPlayer::errorType() const
+{
+ return Phonon::NoError;
+}
+
+qint64 MMF::DummyPlayer::totalTime() const
+{
+ return 0;
+}
+
+void MMF::DummyPlayer::open()
+{
+
+}
+
+void MMF::DummyPlayer::close()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// AbstractPlayer
+//-----------------------------------------------------------------------------
+
+void MMF::DummyPlayer::doSetTickInterval(qint32)
+{
+
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/dummyplayer.h b/src/3rdparty/phonon/mmf/dummyplayer.h
new file mode 100644
index 0000000..5b00411
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/dummyplayer.h
@@ -0,0 +1,69 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_DUMMYPLAYER_H
+#define PHONON_MMF_DUMMYPLAYER_H
+
+#include "abstractplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+class AudioOutput;
+
+/**
+ * @short Stub implementation of AbstractPlayer.
+ *
+ * The functions of this class are:
+ * - Allow MediaObject to call a subset of the MediaObjectInterface
+ * API, before SetSource has been called.
+ * - Cache any parameters which are set in this state (e.g.
+ * prefinish mark), so that they can be copied into the 'real'
+ * AbstractPlayer implementation once a source has been loaded.
+ */
+class DummyPlayer : public AbstractPlayer
+{
+public:
+ DummyPlayer(const AbstractPlayer *player = 0);
+
+ // MediaObjectInterface
+ virtual void play();
+ virtual void pause();
+ virtual void stop();
+ virtual void seek(qint64 milliseconds);
+ virtual bool hasVideo() const;
+ virtual bool isSeekable() const;
+ virtual qint64 currentTime() const;
+ virtual Phonon::State state() const;
+ virtual Phonon::ErrorType errorType() const;
+ virtual qint64 totalTime() const;
+
+ // AbstractPlayer
+ virtual void open();
+ virtual void close();
+ virtual void doSetTickInterval(qint32 interval);
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/effectfactory.cpp b/src/3rdparty/phonon/mmf/effectfactory.cpp
new file mode 100644
index 0000000..4643978
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/effectfactory.cpp
@@ -0,0 +1,215 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QObject>
+#include <QCoreApplication>
+
+#include <mdaaudiooutputstream.h>
+
+#include "audioequalizer.h"
+#include "bassboost.h"
+#include "environmentalreverb.h"
+#include "loudness.h"
+#include "stereowidening.h"
+
+#include "effectfactory.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::EffectFactory
+ \internal
+*/
+
+EffectFactory::EffectFactory(QObject *parent)
+ : QObject(parent)
+ , m_initialized(false)
+{
+
+}
+
+EffectFactory::~EffectFactory()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+AbstractAudioEffect *EffectFactory::createAudioEffect(Type type,
+ QObject *parent)
+{
+ // Lazily initialize
+ if (!m_initialized)
+ initialize();
+
+ Q_ASSERT(parent);
+
+ const QList<EffectParameter>& parameters = data(type).m_parameters;
+
+ AbstractAudioEffect *effect = 0;
+
+ switch (type)
+ {
+ case TypeBassBoost:
+ effect = new BassBoost(parent, parameters);
+ break;
+ case TypeAudioEqualizer:
+ effect = new AudioEqualizer(parent, parameters);
+ break;
+ case TypeEnvironmentalReverb:
+ effect = new EnvironmentalReverb(parent, parameters);
+ break;
+ case TypeLoudness:
+ effect = new Loudness(parent, parameters);
+ break;
+ case TypeStereoWidening:
+ effect = new StereoWidening(parent, parameters);
+ break;
+
+ // Not implemented
+ case TypeDistanceAttenuation:
+ case TypeListenerOrientation:
+ case TypeSourceOrientation:
+ // Fall through
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown effect");
+ }
+
+ return effect;
+}
+
+QHash<QByteArray, QVariant> EffectFactory::audioEffectDescriptions(Type type)
+{
+ // Lazily initialize
+ if (!m_initialized)
+ initialize();
+
+ return data(type).m_descriptions;
+}
+
+QList<int> EffectFactory::effectIndexes()
+{
+ // Lazily initialize
+ if (!m_initialized)
+ initialize();
+
+ QList<int> result;
+
+ QHash<Type, EffectData>::const_iterator i = m_effectData.begin();
+ for ( ; i != m_effectData.end(); ++i)
+ if (i.value().m_supported)
+ result.append(i.key());
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+#define INITIALIZE_EFFECT(Effect) \
+ { \
+ EffectData data = getData<Effect>(); \
+ m_effectData.insert(Type##Effect, data); \
+ }
+
+void EffectFactory::initialize()
+{
+ Q_ASSERT_X(!m_initialized, Q_FUNC_INFO, "Already initialized");
+
+ INITIALIZE_EFFECT(AudioEqualizer)
+ INITIALIZE_EFFECT(BassBoost)
+ INITIALIZE_EFFECT(EnvironmentalReverb)
+ INITIALIZE_EFFECT(Loudness)
+ INITIALIZE_EFFECT(StereoWidening)
+
+ m_initialized = true;
+}
+
+// This class is just a wrapper which allows us to instantiate a
+// CMdaAudioOutputStream object. This is done in order to allow the
+// effects API to query the DevSound implementation, to discover
+// which effects are supported and what parameters they take.
+// Ideally, we would use CMMFDevSound directly, but this class is not
+// available in the public S60 SDK.
+class OutputStreamFactory : public MMdaAudioOutputStreamCallback
+{
+public:
+ CMdaAudioOutputStream* create()
+ {
+ CMdaAudioOutputStream* stream = 0;
+ QT_TRAP_THROWING(stream = CMdaAudioOutputStream::NewL(*this));
+ return stream;
+ }
+private:
+ void MaoscOpenComplete(TInt /*aError*/) { }
+ void MaoscBufferCopied(TInt /*aError*/, const TDesC8& /*aBuffer*/) { }
+ void MaoscPlayComplete(TInt /*aError*/) { }
+};
+
+template<typename BackendNode>
+EffectFactory::EffectData EffectFactory::getData()
+{
+ EffectData data;
+
+ // Create a temporary CMdaAudioOutputStream object, so that the effects
+ // API can query DevSound to discover which effects are supported.
+ OutputStreamFactory streamFactory;
+ QScopedPointer<CMdaAudioOutputStream> stream(streamFactory.create());
+
+ EffectParameter param(
+ /* parameterId */ AbstractAudioEffect::ParameterEnable,
+ /* name */ tr("Enabled"),
+ /* hints */ EffectParameter::ToggledHint,
+ /* defaultValue */ QVariant(bool(true)));
+ data.m_parameters.append(param);
+
+ data.m_supported = BackendNode::getParameters(stream.data(),
+ data.m_parameters);
+ if (data.m_supported) {
+ const QString description = QCoreApplication::translate
+ ("Phonon::MMF::EffectFactory", BackendNode::description());
+ data.m_descriptions.insert("name", description);
+ data.m_descriptions.insert("description", description);
+ data.m_descriptions.insert("available", true);
+ }
+
+ // Sanity check to ensure that all parameter IDs are unique
+ QSet<int> ids;
+ foreach (param, data.m_parameters) {
+ Q_ASSERT_X(ids.find(param.id()) == ids.end(), Q_FUNC_INFO,
+ "Parameter list contains duplicates");
+ ids.insert(param.id());
+ }
+
+ return data;
+}
+
+const EffectFactory::EffectData& EffectFactory::data(Type type) const
+{
+ QHash<Type, EffectData>::const_iterator i = m_effectData.find(type);
+ Q_ASSERT_X(i != m_effectData.end(), Q_FUNC_INFO, "Effect data not found");
+ return i.value();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/effectfactory.h b/src/3rdparty/phonon/mmf/effectfactory.h
new file mode 100644
index 0000000..dd4b58d
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/effectfactory.h
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_EFFECTFACTORY_H
+#define PHONON_MMF_EFFECTFACTORY_H
+
+#include "abstractaudioeffect.h"
+#include "effectparameter.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short Contains utility functions related to effects.
+ */
+class EffectFactory : public QObject
+{
+ Q_OBJECT
+
+public:
+ EffectFactory(QObject *parent);
+ ~EffectFactory();
+
+ enum Type
+ {
+ TypeAudioEqualizer = 0
+ , TypeBassBoost
+ , TypeDistanceAttenuation
+ , TypeEnvironmentalReverb
+ , TypeListenerOrientation
+ , TypeLoudness
+ , TypeSourceOrientation
+ , TypeStereoWidening
+ };
+
+ /**
+ * @short Creates an audio effect of type @p type.
+ */
+ AbstractAudioEffect *createAudioEffect(Type type, QObject *parent);
+
+ /**
+ * @short Return the properties for effect @p type.
+ *
+ * This handles the effects for
+ * BackendInterface::objectDescriptionProperties().
+ */
+ QHash<QByteArray, QVariant> audioEffectDescriptions(Type type);
+
+ /**
+ * @short Returns the indexes for the supported effects.
+ *
+ * This handles the effects for
+ * BackendInterface::objectDescriptionIndexes().
+ */
+ QList<int> effectIndexes();
+
+private:
+ void initialize();
+
+ struct EffectData
+ {
+ bool m_supported;
+ QHash<QByteArray, QVariant> m_descriptions;
+ QList<EffectParameter> m_parameters;
+ };
+
+ template<typename BackendNode> EffectData getData();
+ const EffectData& data(Type type) const;
+
+private:
+ bool m_initialized;
+ QHash<Type, EffectData> m_effectData;
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/effectparameter.cpp b/src/3rdparty/phonon/mmf/effectparameter.cpp
new file mode 100644
index 0000000..17c1315
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/effectparameter.cpp
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "effectparameter.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::EffectParameter
+ \internal
+*/
+
+MMF::EffectParameter::EffectParameter()
+ : m_hasInternalRange(false)
+{
+
+}
+
+MMF::EffectParameter::EffectParameter(
+ int parameterId, const QString &name, Hints hints,
+ const QVariant &defaultValue, const QVariant &min,
+ const QVariant &max, const QVariantList &values,
+ const QString &description)
+ : Phonon::EffectParameter(parameterId, name, hints, defaultValue,
+ min, max, values, description)
+ , m_hasInternalRange(false)
+{
+
+}
+
+void MMF::EffectParameter::setInternalRange(qint32 min, qint32 max)
+{
+ Q_ASSERT_X(max >= min, Q_FUNC_INFO, "Invalid range");
+ m_internalRange = QPair<qint32, qint32>(min, max);
+ m_hasInternalRange = true;
+}
+
+qint32 MMF::EffectParameter::toInternalValue(qreal external) const
+{
+ Q_ASSERT_X(m_hasInternalRange, Q_FUNC_INFO, "Does not have internal range");
+ const qint32 range = m_internalRange.second - m_internalRange.first;
+ return m_internalRange.first + ((1.0 + external) / 2) * range;
+}
+
+qreal MMF::EffectParameter::toExternalValue
+ (qint32 value, qint32 min, qint32 max)
+{
+ Q_ASSERT_X(max >= min, Q_FUNC_INFO, "Invalid range");
+ const qint32 range = max - min;
+ return range == 0 ? 0.0 : ((2.0 * value - min) / range) - 1.0;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/effectparameter.h b/src/3rdparty/phonon/mmf/effectparameter.h
new file mode 100644
index 0000000..892ed4d
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/effectparameter.h
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_EFFECTPARAMETER_H
+#define PHONON_MMF_EFFECTPARAMETER_H
+
+#include <phonon/effectparameter.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short Parameter value for an audio effect
+ *
+ * The base class is extended in order to work around a shortcoming
+ * in Phonon::EffectWidget. This widget only displays sliders for
+ * parameters with numeric values if the variant type of the parameter
+ * is QReal and the range is exactly -1.0 to +1.0; otherwise, a
+ * spinbox is used to set numeric parameters. This is rather
+ * inconvenient for many effects, such as the audio equalizer, for
+ * which a slider is a much more natural UI control.
+ *
+ * For many such parameters, we therefore report the type to be QReal
+ * and the range to be -1.0 to +1.0. This class stores the actual
+ * integer range for the parameter, and provides the toInternalValue
+ * function for converting between the client-side floating point
+ * value and the internal integer value.
+ */
+class EffectParameter : public Phonon::EffectParameter
+{
+public:
+ EffectParameter();
+ EffectParameter(int parameterId, const QString &name, Hints hints,
+ const QVariant &defaultValue, const QVariant &min = QVariant(),
+ const QVariant &max = QVariant(), const QVariantList &values = QVariantList(),
+ const QString &description = QString());
+
+ void setInternalRange(qint32 min, qint32 max);
+ qint32 toInternalValue(qreal external) const;
+
+ static qreal toExternalValue(qint32 value, qint32 min, qint32 max);
+
+private:
+ bool m_hasInternalRange;
+ QPair<qint32, qint32> m_internalRange;
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.cpp b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
new file mode 100644
index 0000000..d4f5223
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
@@ -0,0 +1,212 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <EnvironmentalReverbBase.h>
+#include "environmentalreverb.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::EnvironmentalReverb
+ \internal
+*/
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(EnvironmentalReverb)
+
+enum Parameters
+{
+ DecayHFRatio = AbstractAudioEffect::ParameterBase,
+ DecayTime,
+ Density,
+ Diffusion,
+ ReflectionsDelay,
+ ReflectionsLevel,
+ ReverbDelay,
+ ReverbLevel,
+ RoomHFLevel,
+ RoomLevel
+};
+
+EnvironmentalReverb::EnvironmentalReverb(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+int EnvironmentalReverb::effectParameterChanged(const EffectParameter &param,
+ const QVariant &value)
+{
+ const qreal externalLevel = value.toReal();
+ const int internalLevel = param.toInternalValue(externalLevel);
+
+ TInt err = 0;
+
+ switch(param.id()) {
+ case DecayHFRatio:
+ TRAP(err, concreteEffect()->SetDecayHFRatioL(internalLevel));
+ break;
+ case DecayTime:
+ TRAP(err, concreteEffect()->SetDecayTimeL(internalLevel));
+ break;
+ case Density:
+ TRAP(err, concreteEffect()->SetDensityL(internalLevel));
+ break;
+ case Diffusion:
+ TRAP(err, concreteEffect()->SetDiffusionL(internalLevel));
+ break;
+ case ReflectionsDelay:
+ TRAP(err, concreteEffect()->SetReflectionsDelayL(internalLevel));
+ break;
+ case ReflectionsLevel:
+ TRAP(err, concreteEffect()->SetReflectionsLevelL(internalLevel));
+ break;
+ case ReverbDelay:
+ TRAP(err, concreteEffect()->SetReverbDelayL(internalLevel));
+ break;
+ case ReverbLevel:
+ TRAP(err, concreteEffect()->SetReverbLevelL(internalLevel));
+ break;
+ case RoomHFLevel:
+ TRAP(err, concreteEffect()->SetRoomHFLevelL(internalLevel));
+ break;
+ case RoomLevel:
+ TRAP(err, concreteEffect()->SetRoomLevelL(internalLevel));
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown parameter");
+ }
+
+ return err;
+}
+
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* EnvironmentalReverb::description()
+{
+ return "Reverb";
+}
+
+// Internal helper function
+Phonon::MMF::EffectParameter createParameter(int id, const QString &name,
+ int defaultValue, int minValue, int maxValue,
+ Phonon::EffectParameter::Hint hint = Phonon::EffectParameter::IntegerHint)
+{
+ const qreal externalDefaultValue =
+ Phonon::MMF::EffectParameter::toExternalValue
+ (defaultValue, minValue, maxValue);
+
+ Phonon::MMF::EffectParameter param(id, name, hint,
+ /* defaultValue */ QVariant(externalDefaultValue),
+ /* minimumValue */ QVariant(qreal(-1.0)),
+ /* maximumValue */ QVariant(qreal(+1.0)));
+
+ param.setInternalRange(minValue, maxValue);
+ return param;
+}
+
+bool EnvironmentalReverb::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters)
+{
+ bool supported = false;
+
+ QScopedPointer<CEnvironmentalReverb> effect;
+ TRAPD(err, effect.reset(CEnvironmentalReverb::NewL(*stream)));
+
+ if (KErrNone == err) {
+ supported = true;
+
+ TInt32 min, max;
+ TUint32 umin, umax;
+
+ effect->DecayHFRatioRange(umin, umax);
+ //: DecayHFRatio: Ratio of high-frequency decay time to the value specified by
+ //: DecayTime.
+ parameters.append(createParameter(
+ DecayHFRatio, tr("Decay HF ratio (%)"), effect->DecayHFRatio(),
+ umin, umax));
+
+ effect->DecayTimeRange(umin, umax);
+ //: DecayTime: Time over which reverberation is diminished.
+ parameters.append(createParameter(
+ DecayTime, tr("Decay time (ms)"), effect->DecayTime(),
+ umin, umax));
+
+ //: Density Delay between first and subsequent reflections.
+ //: Note that the S60 platform documentation does not make clear
+ //: the distinction between this value and the Diffusion value.
+ parameters.append(createParameter(
+ Density, tr("Density (%)"), effect->Density(), 0, 100));
+
+ //: Diffusion: Delay between first and subsequent reflections.
+ //: Note that the S60 platform documentation does not make clear
+ //: the distinction between this value and the Density value.
+ parameters.append(createParameter(
+ Diffusion, tr("Diffusion (%)"), effect->Diffusion(), 0, 100));
+
+ //: ReflectionsDelay: Amount of delay between the arrival the direct
+ //: path from the source and the arrival of the first reflection.
+ parameters.append(createParameter(
+ ReflectionsDelay, tr("Reflections delay (ms)"),
+ effect->ReflectionsDelay(), 0, effect->ReflectionsDelayMax()));
+
+ effect->ReflectionLevelRange(min, max);
+ //: ReflectionsLevel: Amplitude of reflections. This value is
+ //: corrected by the RoomLevel to give the final reflection amplitude.
+ parameters.append(createParameter(
+ ReflectionsLevel, tr("Reflections level (mB)"),
+ effect->ReflectionsLevel(),
+ min, max, EffectParameter::LogarithmicHint));
+
+ //: ReverbDelay: Amount of time between arrival of the first
+ //: reflection and start of the late reverberation.
+ parameters.append(createParameter(
+ ReverbDelay, tr("Reverb delay (ms)"), effect->ReverbDelay(),
+ 0, effect->ReverbDelayMax()));
+
+ effect->ReverbLevelRange(min, max);
+ //: ReverbLevel Amplitude of reverberations. This value is
+ //: corrected by the RoomLevel to give the final reverberation
+ //: amplitude.
+ parameters.append(createParameter(
+ ReverbLevel, tr("Reverb level (mB)"), effect->ReverbLevel(),
+ min, max, EffectParameter::LogarithmicHint));
+
+ effect->RoomHFLevelRange(min, max);
+ //: RoomHFLevel: Amplitude of low-pass filter used to attenuate the
+ //: high frequency component of reflected sound.
+ parameters.append(createParameter(
+ RoomHFLevel, tr("Room HF level"), effect->RoomHFLevel(),
+ min, max));
+
+ effect->RoomLevelRange(min, max);
+ //: RoomLevel: Master volume control for all reflected sound.
+ parameters.append(createParameter(
+ RoomLevel, tr("Room level (mB)"), effect->RoomLevel(),
+ min, max, EffectParameter::LogarithmicHint));
+ }
+
+ return supported;
+}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.h b/src/3rdparty/phonon/mmf/environmentalreverb.h
new file mode 100644
index 0000000..eab68c6
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/environmentalreverb.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_ENVIRONMENTALREVERB_H
+#define PHONON_MMF_ENVIRONMENTALREVERB_H
+
+#include "abstractaudioeffect.h"
+
+class CEnvironmentalReverb;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A reverb effect.
+ */
+class EnvironmentalReverb : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ EnvironmentalReverb(QObject *parent, const QList<EffectParameter>& parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+ virtual int effectParameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+private:
+ CEnvironmentalReverb *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/loudness.cpp b/src/3rdparty/phonon/mmf/loudness.cpp
new file mode 100644
index 0000000..ca05ab0
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/loudness.cpp
@@ -0,0 +1,59 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <LoudnessBase.h>
+#include "loudness.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(Loudness)
+
+/*! \class MMF::Loudness
+ \internal
+*/
+
+Loudness::Loudness(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* Loudness::description()
+{
+ return "Loudness";
+}
+
+bool Loudness::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter> &parameters)
+{
+ Q_UNUSED(parameters)
+ QScopedPointer<CLoudness> effect;
+ TRAPD(err, effect.reset(CLoudness::NewL(*stream)));
+ return (KErrNone == err);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/loudness.h b/src/3rdparty/phonon/mmf/loudness.h
new file mode 100644
index 0000000..a688a67
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/loudness.h
@@ -0,0 +1,60 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_LOUDNESS_H
+#define PHONON_MMF_LOUDNESS_H
+
+#include "abstractaudioeffect.h"
+
+class CLoudness;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A "loudness" effect.
+ */
+class Loudness : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ Loudness(QObject *parent, const QList<EffectParameter>& parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+
+private:
+ CLoudness *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp
new file mode 100644
index 0000000..9da94ee
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/mediaobject.cpp
@@ -0,0 +1,561 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "audiooutput.h"
+#include "audioplayer.h"
+#include "defs.h"
+#include "dummyplayer.h"
+#include "utils.h"
+#include "utils.h"
+
+#ifdef PHONON_MMF_VIDEO_SURFACES
+#include "videoplayer_surface.h"
+#else
+#include "videoplayer_dsa.h"
+#endif
+
+#include "videowidget.h"
+
+#include "mediaobject.h"
+
+#include <QDir>
+#include <QResource>
+#include <QUrl>
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
+#include <mmf/common/mmfcontrollerframeworkbase.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::MediaObject
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::MediaObject::MediaObject(QObject *parent) : MMF::MediaNode::MediaNode(parent)
+ , m_recognizerOpened(false)
+ , m_nextSourceSet(false)
+ , m_file(0)
+ , m_resource(0)
+{
+ m_player.reset(new DummyPlayer());
+
+ TRACE_CONTEXT(MediaObject::MediaObject, EAudioApi);
+ TRACE_ENTRY_0();
+
+ const int err = m_fileServer.Connect();
+ QT_TRAP_THROWING(User::LeaveIfError(err));
+
+ parent->installEventFilter(this);
+ m_iap = KUseDefaultIap;
+
+ TRACE_EXIT_0();
+}
+
+MMF::MediaObject::~MediaObject()
+{
+ TRACE_CONTEXT(MediaObject::~MediaObject, EAudioApi);
+ TRACE_ENTRY_0();
+
+ parent()->removeEventFilter(this);
+ delete m_resource;
+
+ if (m_file)
+ m_file->Close();
+ delete m_file;
+
+ m_fileServer.Close();
+ m_recognizer.Close();
+
+ TRACE_EXIT_0();
+}
+
+
+//-----------------------------------------------------------------------------
+// Recognizer
+//-----------------------------------------------------------------------------
+
+bool MMF::MediaObject::openRecognizer()
+{
+ TRACE_CONTEXT(MediaObject::openRecognizer, EAudioInternal);
+
+ if (!m_recognizerOpened) {
+ TInt err = m_recognizer.Connect();
+ if (KErrNone != err) {
+ TRACE("RApaLsSession::Connect error %d", err);
+ return false;
+ }
+
+ // This must be called in order to be able to share file handles with
+ // the recognizer server (see fileMediaType function).
+ err = m_fileServer.ShareProtected();
+ if (KErrNone != err) {
+ TRACE("RFs::ShareProtected error %d", err);
+ return false;
+ }
+
+ m_recognizerOpened = true;
+ }
+
+ return true;
+}
+
+MMF::MediaType MMF::MediaObject::fileMediaType
+(const QString& fileName)
+{
+ TRACE_CONTEXT(MediaObject::fileMediaType, EAudioInternal);
+
+ MediaType result = MediaTypeUnknown;
+
+ if (openRecognizer()) {
+ TInt err = openFileHandle(fileName);
+ const QHBufC nativeFileName(QDir::toNativeSeparators(fileName));
+ if (KErrNone == err) {
+ TDataRecognitionResult recognizerResult;
+ err = m_recognizer.RecognizeData(*m_file, recognizerResult);
+ if (KErrNone == err) {
+ const TPtrC mimeType = recognizerResult.iDataType.Des();
+ result = Utils::mimeTypeToMediaType(mimeType);
+ } else {
+ TRACE("RApaLsSession::RecognizeData filename %S error %d", nativeFileName.data(), err);
+ }
+ } else {
+ TRACE("RFile::Open filename %S error %d", nativeFileName.data(), err);
+ }
+ }
+
+ return result;
+}
+
+int MMF::MediaObject::openFileHandle(const QString &fileName)
+{
+ TRACE_CONTEXT(MediaObject::openFileHandle, EAudioInternal);
+ const QHBufC nativeFileName(QDir::toNativeSeparators(fileName));
+ TRACE_ENTRY("filename %S", nativeFileName.data());
+ if (m_file)
+ m_file->Close();
+ delete m_file;
+ m_file = 0;
+ m_file = new RFile;
+ TInt err = m_file->Open(m_fileServer, *nativeFileName, EFileRead | EFileShareReadersOrWriters);
+ return err;
+}
+
+MMF::MediaType MMF::MediaObject::bufferMediaType(const uchar *data, qint64 size)
+{
+ TRACE_CONTEXT(MediaObject::bufferMediaType, EAudioInternal);
+ MediaType result = MediaTypeUnknown;
+ if (openRecognizer()) {
+ TDataRecognitionResult recognizerResult;
+ const TPtrC8 des(data, size);
+ const TInt err = m_recognizer.RecognizeData(KNullDesC, des, recognizerResult);
+ if (KErrNone == err) {
+ const TPtrC mimeType = recognizerResult.iDataType.Des();
+ result = Utils::mimeTypeToMediaType(mimeType);
+ } else {
+ TRACE("RApaLsSession::RecognizeData error %d", err);
+ }
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// MediaObjectInterface
+//-----------------------------------------------------------------------------
+
+void MMF::MediaObject::play()
+{
+ m_player->play();
+}
+
+void MMF::MediaObject::pause()
+{
+ m_player->pause();
+}
+
+void MMF::MediaObject::stop()
+{
+ m_player->stop();
+}
+
+void MMF::MediaObject::seek(qint64 ms)
+{
+ m_player->seek(ms);
+
+ if (state() == PausedState or state() == PlayingState) {
+ emit tick(currentTime());
+ }
+}
+
+qint32 MMF::MediaObject::tickInterval() const
+{
+ return m_player->tickInterval();
+}
+
+void MMF::MediaObject::setTickInterval(qint32 interval)
+{
+ m_player->setTickInterval(interval);
+}
+
+bool MMF::MediaObject::hasVideo() const
+{
+ return m_player->hasVideo();
+}
+
+bool MMF::MediaObject::isSeekable() const
+{
+ return m_player->isSeekable();
+}
+
+Phonon::State MMF::MediaObject::state() const
+{
+ return m_player->state();
+}
+
+qint64 MMF::MediaObject::currentTime() const
+{
+ return m_player->currentTime();
+}
+
+QString MMF::MediaObject::errorString() const
+{
+ return m_player->errorString();
+}
+
+Phonon::ErrorType MMF::MediaObject::errorType() const
+{
+ return m_player->errorType();
+}
+
+qint64 MMF::MediaObject::totalTime() const
+{
+ return m_player->totalTime();
+}
+
+MediaSource MMF::MediaObject::source() const
+{
+ return m_source;
+}
+
+void MMF::MediaObject::setSource(const MediaSource &source)
+{
+ switchToSource(source);
+}
+
+void MMF::MediaObject::switchToSource(const MediaSource &source)
+{
+ if (m_file)
+ m_file->Close();
+ delete m_file;
+ m_file = 0;
+
+ delete m_resource;
+ m_resource = 0;
+
+ createPlayer(source);
+ m_source = source;
+ m_player->open();
+ emit currentSourceChanged(m_source);
+}
+
+void MMF::MediaObject::createPlayer(const MediaSource &source)
+{
+ TRACE_CONTEXT(MediaObject::createPlayer, EAudioApi);
+ TRACE_ENTRY("state %d source.type %d", state(), source.type());
+ TRACE_ENTRY("source.type %d", source.type());
+
+ MediaType mediaType = MediaTypeUnknown;
+
+ AbstractPlayer* oldPlayer = m_player.data();
+
+ const bool oldPlayerHasVideo = oldPlayer->hasVideo();
+ const bool oldPlayerSeekable = oldPlayer->isSeekable();
+
+ QString errorMessage;
+
+ // Determine media type
+ switch (source.type()) {
+ case MediaSource::LocalFile:
+ mediaType = fileMediaType(source.fileName());
+ break;
+
+ case MediaSource::Url:
+ {
+ const QUrl url(source.url());
+ if (url.scheme() == QLatin1String("file")) {
+ mediaType = fileMediaType(url.toLocalFile());
+ }
+ else {
+ // Streaming playback is generally not supported by the implementation
+ // of the audio player API, so we use CVideoPlayerUtility for both
+ // audio and video streaming.
+ mediaType = MediaTypeVideo;
+ }
+ }
+ break;
+
+ case MediaSource::Invalid:
+ case MediaSource::Disc:
+ errorMessage = tr("Error opening source: type not supported");
+ break;
+
+ case MediaSource::Stream:
+ {
+ const QString fileName = source.url().toLocalFile();
+ if (fileName.startsWith(QLatin1String(":/")) || fileName.startsWith(QLatin1String("qrc://"))) {
+ Q_ASSERT(!m_resource);
+ m_resource = new QResource(fileName);
+ if (m_resource->isValid()) {
+ if (m_resource->isCompressed())
+ errorMessage = tr("Error opening source: resource is compressed");
+ else
+ mediaType = bufferMediaType(m_resource->data(), m_resource->size());
+ } else {
+ errorMessage = tr("Error opening source: resource not valid");
+ }
+ } else {
+ errorMessage = tr("Error opening source: type not supported");
+ }
+ }
+ break;
+
+ case MediaSource::Empty:
+ TRACE_0("Empty media source");
+ break;
+ }
+
+ if (oldPlayer)
+ oldPlayer->close();
+
+ AbstractPlayer* newPlayer = 0;
+
+ // Construct newPlayer using oldPlayer (if not 0) in order to copy
+ // parameters (volume, prefinishMark, transitionTime) which may have
+ // been set on oldPlayer.
+
+ switch (mediaType) {
+ case MediaTypeUnknown:
+ TRACE_0("Media type could not be determined");
+ newPlayer = new DummyPlayer(oldPlayer);
+ errorMessage = tr("Error opening source: media type could not be determined");
+ break;
+
+ case MediaTypeAudio:
+ newPlayer = new AudioPlayer(this, oldPlayer);
+ break;
+
+ case MediaTypeVideo:
+#ifdef PHONON_MMF_VIDEO_SURFACES
+ newPlayer = SurfaceVideoPlayer::create(this, oldPlayer);
+#else
+ newPlayer = DsaVideoPlayer::create(this, oldPlayer);
+#endif
+ break;
+ }
+
+ if (oldPlayer)
+ emit abstractPlayerChanged(0);
+ m_player.reset(newPlayer);
+ emit abstractPlayerChanged(newPlayer);
+
+ if (oldPlayerHasVideo != hasVideo()) {
+ emit hasVideoChanged(hasVideo());
+ }
+
+ if (oldPlayerSeekable != isSeekable()) {
+ emit seekableChanged(isSeekable());
+ }
+
+ connect(m_player.data(), SIGNAL(totalTimeChanged(qint64)), SIGNAL(totalTimeChanged(qint64)));
+ connect(m_player.data(), SIGNAL(stateChanged(Phonon::State,Phonon::State)), SIGNAL(stateChanged(Phonon::State,Phonon::State)));
+ connect(m_player.data(), SIGNAL(finished()), SIGNAL(finished()));
+ connect(m_player.data(), SIGNAL(bufferStatus(int)), SIGNAL(bufferStatus(int)));
+ connect(m_player.data(), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)));
+ connect(m_player.data(), SIGNAL(aboutToFinish()), SIGNAL(aboutToFinish()));
+ connect(m_player.data(), SIGNAL(prefinishMarkReached(qint32)), SIGNAL(prefinishMarkReached(qint32)));
+ connect(m_player.data(), SIGNAL(prefinishMarkReached(qint32)), SLOT(handlePrefinishMarkReached(qint32)));
+ connect(m_player.data(), SIGNAL(tick(qint64)), SIGNAL(tick(qint64)));
+
+ // We need to call setError() after doing the connects, otherwise the
+ // error won't be received.
+ if (!errorMessage.isEmpty()) {
+ Q_ASSERT(m_player);
+ m_player->setError(errorMessage);
+ }
+
+ TRACE_EXIT_0();
+}
+
+void MMF::MediaObject::setNextSource(const MediaSource &source)
+{
+ m_nextSource = source;
+ m_nextSourceSet = true;
+}
+
+qint32 MMF::MediaObject::prefinishMark() const
+{
+ return m_player->prefinishMark();
+}
+
+void MMF::MediaObject::setPrefinishMark(qint32 mark)
+{
+ m_player->setPrefinishMark(mark);
+}
+
+qint32 MMF::MediaObject::transitionTime() const
+{
+ return m_player->transitionTime();
+}
+
+void MMF::MediaObject::setTransitionTime(qint32 time)
+{
+ m_player->setTransitionTime(time);
+}
+
+void MMF::MediaObject::volumeChanged(qreal volume)
+{
+ m_player->volumeChanged(volume);
+}
+
+RFile* MMF::MediaObject::file() const
+{
+ return m_file;
+}
+
+QResource* MMF::MediaObject::resource() const
+{
+ return m_resource;
+}
+
+//-----------------------------------------------------------------------------
+// MediaNode
+//-----------------------------------------------------------------------------
+
+void MMF::MediaObject::connectMediaObject(MediaObject * /*mediaObject*/)
+{
+ // This function should never be called - see MediaNode::setMediaObject()
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "Connection of MediaObject to MediaObject");
+}
+
+void MMF::MediaObject::disconnectMediaObject(MediaObject * /*mediaObject*/)
+{
+ // This function should never be called - see MediaNode::setMediaObject()
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "Disconnection of MediaObject from MediaObject");
+}
+
+
+//-----------------------------------------------------------------------------
+// Video output
+//-----------------------------------------------------------------------------
+
+void MMF::MediaObject::setVideoOutput(AbstractVideoOutput* videoOutput)
+{
+ m_player->setVideoOutput(videoOutput);
+}
+
+
+AbstractPlayer *MMF::MediaObject::abstractPlayer() const
+{
+ return m_player.data();
+}
+
+//-----------------------------------------------------------------------------
+// Playlist support
+//-----------------------------------------------------------------------------
+
+void MMF::MediaObject::switchToNextSource()
+{
+ if (m_nextSourceSet) {
+ m_nextSourceSet = false;
+ switchToSource(m_nextSource);
+ play();
+ } else {
+ emit finished();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// IAP support
+//-----------------------------------------------------------------------------
+
+int MMF::MediaObject::currentIAP() const
+{
+ return m_iap;
+}
+
+bool MMF::MediaObject::eventFilter(QObject *watched, QEvent *event)
+{
+ if (event->type() == QEvent::DynamicPropertyChange ) {
+ QDynamicPropertyChangeEvent* dynamicEvent = static_cast<QDynamicPropertyChangeEvent*>(event);
+ if (dynamicEvent->propertyName() == "InternetAccessPointName") {
+ QVariant value = watched->property("InternetAccessPointName");
+ if (value.isValid()) {
+ QString iapName = value.toString();
+ TRAPD(err, setIAPIdFromNameL(iapName));
+ if (err)
+ m_player->setError(tr("Failed to set requested IAP"), err);
+ }
+ }
+ }
+ return false;
+}
+
+void MMF::MediaObject::setIAPIdFromNameL(const QString& iapString)
+{
+ TRACE_CONTEXT(MediaObject::getIapIdFromName, EVideoInternal);
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapDes = qt_QString2TPtrC(iapString);
+ CCommsDatabase *commsDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(commsDb);
+ commsDb->ShowHiddenRecords();
+ CCommsDbTableView *view = commsDb->OpenTableLC(TPtrC(IAP));
+ for (TInt l = view->GotoFirstRecord(); l != KErrNotFound; l = view->GotoNextRecord()) {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
+ TRACE("found IAP %S", &iapName);
+ if (iapName.CompareF(iapDes) == 0) {
+ TUint32 uiap;
+ view->ReadUintL(TPtrC(COMMDB_ID), uiap);
+ TRACE("matched IAP %S, setting m_iap %d", &iapName, uiap);
+ m_iap = uiap;
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy(2); // commsDb, view
+}
+
+//-----------------------------------------------------------------------------
+// Other private functions
+//-----------------------------------------------------------------------------
+
+void MMF::MediaObject::handlePrefinishMarkReached(qint32 time)
+{
+ emit tick(time);
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h
new file mode 100644
index 0000000..0ed70ff
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/mediaobject.h
@@ -0,0 +1,160 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_MEDIAOBJECT_H
+#define PHONON_MMF_MEDIAOBJECT_H
+
+#include <phonon/mediasource.h>
+#include <phonon/mediaobjectinterface.h>
+#include <QScopedPointer>
+#include <QTimer>
+#include <QString>
+
+// For recognizer
+#include <apgcli.h>
+
+#include "abstractplayer.h"
+#include "mmf_medianode.h"
+#include "defs.h"
+
+QT_BEGIN_NAMESPACE
+
+class QResource;
+
+namespace Phonon
+{
+namespace MMF
+{
+class AbstractPlayer;
+class AbstractVideoOutput;
+
+/**
+ * @short Facade class which wraps MMF client utility instance
+ */
+class MediaObject : public MediaNode
+ , public MediaObjectInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::MediaObjectInterface)
+
+public:
+ MediaObject(QObject *parent);
+ virtual ~MediaObject();
+
+ // MediaObjectInterface
+ virtual void play();
+ virtual void pause();
+ virtual void stop();
+ virtual void seek(qint64 milliseconds);
+ virtual qint32 tickInterval() const;
+ virtual void setTickInterval(qint32 interval);
+ virtual bool hasVideo() const;
+ virtual bool isSeekable() const;
+ virtual qint64 currentTime() const;
+ virtual Phonon::State state() const;
+ virtual QString errorString() const;
+ virtual Phonon::ErrorType errorType() const;
+ virtual qint64 totalTime() const;
+ virtual MediaSource source() const;
+ virtual void setSource(const MediaSource &);
+ virtual void setNextSource(const MediaSource &source);
+ virtual qint32 prefinishMark() const;
+ virtual void setPrefinishMark(qint32);
+ virtual qint32 transitionTime() const;
+ virtual void setTransitionTime(qint32);
+
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
+
+ /**
+ * This class owns the AbstractPlayer, and will delete it upon
+ * destruction.
+ */
+ AbstractPlayer *abstractPlayer() const;
+
+ void setVideoOutput(AbstractVideoOutput* videoOutput);
+
+ int openFileHandle(const QString &fileName);
+ RFile* file() const;
+ QResource* resource() const;
+ int currentIAP() const;
+
+public Q_SLOTS:
+ void volumeChanged(qreal volume);
+ void switchToNextSource();
+
+Q_SIGNALS:
+ void abstractPlayerChanged(AbstractPlayer *player);
+ void totalTimeChanged(qint64 length);
+ void hasVideoChanged(bool hasVideo);
+ void seekableChanged(bool seekable);
+ void bufferStatus(int);
+ void aboutToFinish();
+ void prefinishMarkReached(qint32 remaining);
+ // TODO: emit metaDataChanged from MediaObject
+ void metaDataChanged(const QMultiMap<QString, QString>& metaData);
+ void currentSourceChanged(const MediaSource& source);
+ void stateChanged(Phonon::State newState,
+ Phonon::State oldState);
+ void finished();
+ void tick(qint64 time);
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event);
+
+private Q_SLOTS:
+ void handlePrefinishMarkReached(qint32);
+
+private:
+ void switchToSource(const MediaSource &source);
+ void createPlayer(const MediaSource &source);
+ bool openRecognizer();
+ void setIAPIdFromNameL(const QString& iapString);
+
+ // Audio / video media type recognition
+ MediaType fileMediaType(const QString& fileName);
+ MediaType bufferMediaType(const uchar *data, qint64 size);
+ // TODO: urlMediaType function
+
+ static qint64 toMilliSeconds(const TTimeIntervalMicroSeconds &);
+
+private:
+
+ // Audio / video media type recognition
+ bool m_recognizerOpened;
+ RApaLsSession m_recognizer;
+ RFs m_fileServer;
+
+ MediaSource m_source;
+ MediaSource m_nextSource;
+ bool m_nextSourceSet;
+
+ RFile* m_file;
+ QResource* m_resource;
+
+ QScopedPointer<AbstractPlayer> m_player;
+ int m_iap;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.cpp b/src/3rdparty/phonon/mmf/mmf_medianode.cpp
new file mode 100644
index 0000000..ca413d9
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/mmf_medianode.cpp
@@ -0,0 +1,152 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "mediaobject.h"
+
+#include "mmf_medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::MediaNode
+ \internal
+*/
+
+MMF::MediaNode::MediaNode(QObject *parent)
+ : QObject(parent)
+ , m_mediaObject(qobject_cast<MediaObject *>(this))
+ , m_input(0)
+{
+
+}
+
+MMF::MediaNode::~MediaNode()
+{
+ // Phonon framework ensures nodes are disconnected before being destroyed.
+ Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO,
+ "Media node not disconnected before destruction");
+}
+
+bool MMF::MediaNode::connectOutput(MediaNode *output)
+{
+ Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
+
+ bool connected = false;
+
+ // Check that this connection will not result in a graph which
+ // containing more than one MediaObject
+ const bool mediaObjectMisMatch =
+ m_mediaObject
+ && output->m_mediaObject
+ && m_mediaObject != output->m_mediaObject;
+
+ const bool canConnect =
+ !output->isMediaObject()
+ && !output->m_input
+ && !m_outputs.contains(output);
+
+ if (canConnect && !mediaObjectMisMatch) {
+ output->m_input = this;
+ m_outputs += output;
+ updateMediaObject();
+ connected = true;
+ }
+
+ return connected;
+}
+
+bool MMF::MediaNode::disconnectOutput(MediaNode *output)
+{
+ Q_ASSERT_X(output, Q_FUNC_INFO, "Null output pointer");
+
+ bool disconnected = false;
+
+ if (m_outputs.contains(output) && this == output->m_input) {
+ output->m_input = 0;
+ const bool removed = m_outputs.removeOne(output);
+ Q_ASSERT_X(removed, Q_FUNC_INFO, "Output removal failed");
+
+ Q_ASSERT_X(!m_outputs.contains(output), Q_FUNC_INFO,
+ "Output list contains duplicate entries");
+
+ // Perform traversal across each of the two graphs separately
+ updateMediaObject();
+ output->updateMediaObject();
+
+ disconnected = true;
+ }
+
+ return disconnected;
+}
+
+bool MMF::MediaNode::isMediaObject() const
+{
+ return (qobject_cast<const MediaObject *>(this) != 0);
+}
+
+void MMF::MediaNode::updateMediaObject()
+{
+ QList<MediaNode *> nodes;
+ MediaObject *mediaObject = 0;
+
+ // Traverse the graph, collecting a list of nodes, and locating
+ // the MediaObject node, if present
+ visit(nodes, mediaObject);
+
+ MediaNode *node = 0;
+ foreach(node, nodes)
+ node->setMediaObject(mediaObject);
+}
+
+void MMF::MediaNode::setMediaObject(MediaObject *mediaObject)
+{
+ if(!isMediaObject() && m_mediaObject != mediaObject) {
+ if (!mediaObject)
+ disconnectMediaObject(m_mediaObject);
+ else {
+ Q_ASSERT_X(!m_mediaObject, Q_FUNC_INFO, "MediaObject already set");
+ connectMediaObject(mediaObject);
+ }
+ m_mediaObject = mediaObject;
+ }
+}
+
+void MMF::MediaNode::visit(QList<MediaNode *>& visited, MediaObject*& mediaObject)
+{
+ if (isMediaObject()) {
+ // There can never be more than one MediaObject per graph, due to the
+ // mediaObjectMisMatch test in connectOutput().
+ Q_ASSERT_X(!mediaObject, Q_FUNC_INFO, "MediaObject already found");
+ mediaObject = static_cast<MediaObject *>(this);
+ }
+
+ visited += this;
+
+ if (m_input && !visited.contains(m_input))
+ m_input->visit(visited, mediaObject);
+
+ MediaNode *output = 0;
+ foreach (output, m_outputs)
+ if (!visited.contains(output))
+ output->visit(visited, mediaObject);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/mmf_medianode.h b/src/3rdparty/phonon/mmf/mmf_medianode.h
new file mode 100644
index 0000000..f2f64e0
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/mmf_medianode.h
@@ -0,0 +1,108 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_MEDIANODE_H
+#define PHONON_MMF_MEDIANODE_H
+
+#include <QObject>
+#include <phonon/effectinterface.h>
+#include "audioplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+/**
+ * @file mmf_medianode.h mmf_medianode.cpp
+ *
+ * This file starts with mmf_ in order to avoid clash with Phonon's
+ * medianode.h. The GStreamer backend has a file named medianode.h, but it
+ * isn't compiled with ABLD build system, which have problems with separating
+ * user and system include paths.
+ */
+
+namespace Phonon
+{
+namespace MMF
+{
+class MediaObject;
+
+/**
+ * @short Base class for all nodes in the MMF backend.
+ *
+ * MediaNode is the base class for all nodes created by the MMF
+ * backend.
+ *
+ * These nodes may be one of the following types:
+ *
+ * - MediaObject
+ * This represents the source of media data. It encapsulates the
+ * appropriate MMF client API for playing audio or video.
+ * - AudioOutput
+ * This represents the audio output device. Since the MMF client API
+ * does not expose the output device directly, this backend node
+ * simply forwards volume control commands to the MediaObject.
+ * - VideoWidget
+ * A native widget on which video will be rendered.
+ * - An audio effect, derived form AbstractAudioEffect
+ *
+ * Because the MMF API does not support the concept of a media filter graph,
+ * this class must ensure the following:
+ *
+ * - Each media graph contains at most one MediaObject instance.
+ * - Every non-MediaObject node holds a reference to the MediaObject. This
+ * allows commands to be sent through the graph to the encapsulated MMF client
+ * API.
+ */
+class MediaNode : public QObject
+{
+ Q_OBJECT
+public:
+ MediaNode(QObject *parent);
+ ~MediaNode();
+
+ bool connectOutput(MediaNode *output);
+ bool disconnectOutput(MediaNode *output);
+
+ virtual void connectMediaObject(MediaObject *mediaObject) = 0;
+ virtual void disconnectMediaObject(MediaObject *mediaObject) = 0;
+
+private:
+ bool isMediaObject() const;
+
+ void updateMediaObject();
+ void setMediaObject(MediaObject *mediaObject);
+
+ typedef QList<const MediaNode *> NodeList;
+ void visit(QList<MediaNode *>& visited, MediaObject*& mediaObject);
+
+private:
+ MediaObject * m_mediaObject;
+
+ // All nodes except MediaObject may have an input
+ MediaNode * m_input;
+
+ // Only MediaObject can have more than one output
+ QList<MediaNode *> m_outputs;
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/objectdump.cpp b/src/3rdparty/phonon/mmf/objectdump.cpp
new file mode 100644
index 0000000..778cde9
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/objectdump.cpp
@@ -0,0 +1,525 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QByteArray>
+#include <QDebug>
+#include <QHash>
+#include <QTextStream>
+#include <QWidget>
+
+#include "objectdump.h"
+#include "objecttree.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace ObjectDump
+{
+
+//-----------------------------------------------------------------------------
+// QObjectAnnotator
+//-----------------------------------------------------------------------------
+
+QAnnotator::~QAnnotator()
+{
+
+}
+
+
+//-----------------------------------------------------------------------------
+// Annotators
+//-----------------------------------------------------------------------------
+
+QList<QByteArray> QAnnotatorBasic::annotation(const QObject& object)
+{
+ QList<QByteArray> result;
+
+ QByteArray array;
+ QTextStream stream(&array);
+
+ stream << '[' << &object << ']';
+ stream << ' ';
+ stream << object.metaObject()->className();
+
+ if (object.objectName() != "")
+ stream << " \"" << object.objectName() << '"';
+
+ if (object.isWidgetType())
+ stream << " isWidget";
+
+ stream.flush();
+ result.append(array);
+ return result;
+}
+
+QList<QByteArray> QAnnotatorWidget::annotation(const QObject& object)
+{
+ QList<QByteArray> result;
+
+ const QWidget* widget = qobject_cast<const QWidget*>(&object);
+ if (widget) {
+
+ QByteArray array;
+ QTextStream stream(&array);
+
+ stream << "widget: ";
+
+ if (widget->isVisible())
+ stream << "visible ";
+ else
+ stream << "invisible ";
+
+ stream << widget->x() << ',' << widget->y() << ' ';
+ stream << widget->size().width() << 'x'<< widget->size().height() << ' ';
+
+ stream << "hint " << widget->sizeHint().width() << 'x' << widget->sizeHint().height();
+
+ stream.flush();
+ result.append(array);
+ }
+
+ return result;
+}
+
+
+//-----------------------------------------------------------------------------
+// Base class for QDumperPrivate, QVisitorPrivate
+//-----------------------------------------------------------------------------
+
+class QDumperBase
+{
+public:
+ QDumperBase();
+ ~QDumperBase();
+
+ void setPrefix(const QString& prefix);
+ void addAnnotator(QAnnotator* annotator);
+
+protected:
+ QByteArray m_prefix;
+ QList<QAnnotator*> m_annotators;
+
+};
+
+QDumperBase::QDumperBase()
+{
+
+}
+
+QDumperBase::~QDumperBase()
+{
+ QAnnotator* annotator;
+ foreach(annotator, m_annotators)
+ delete annotator;
+}
+
+void QDumperBase::setPrefix(const QString& prefix)
+{
+ m_prefix = prefix.count()
+ ? (prefix + " ").toAscii()
+ : prefix.toAscii();
+}
+
+void QDumperBase::addAnnotator(QAnnotator* annotator)
+{
+ // Protect against an exception occurring during QList::append
+ QScopedPointer<QAnnotator> holder(annotator);
+ m_annotators.append(annotator);
+ holder.take();
+}
+
+
+//-----------------------------------------------------------------------------
+// QDumper
+//-----------------------------------------------------------------------------
+
+class QDumperPrivate : public QDumperBase
+{
+public:
+ QDumperPrivate();
+ ~QDumperPrivate();
+
+ void dumpObject(const QObject& object);
+
+};
+
+
+QDumperPrivate::QDumperPrivate()
+{
+
+}
+
+QDumperPrivate::~QDumperPrivate()
+{
+
+}
+
+void QDumperPrivate::dumpObject(const QObject& object)
+{
+ QAnnotator* annotator;
+ foreach(annotator, m_annotators) {
+
+ const QList<QByteArray> annotations = annotator->annotation(object);
+ QByteArray annotation;
+ foreach(annotation, annotations) {
+ QByteArray buffer(m_prefix);
+ buffer.append(annotation);
+ qDebug() << buffer.constData();
+ }
+ }
+}
+
+
+QDumper::QDumper()
+ : d_ptr(new QDumperPrivate)
+{
+
+}
+
+QDumper::~QDumper()
+{
+
+}
+
+void QDumper::setPrefix(const QString& prefix)
+{
+ d_func()->setPrefix(prefix);
+}
+
+void QDumper::addAnnotator(QAnnotator* annotator)
+{
+ d_func()->addAnnotator(annotator);
+}
+
+void QDumper::dumpObject(const QObject& object)
+{
+ d_func()->dumpObject(object);
+}
+
+
+//-----------------------------------------------------------------------------
+// QVisitor
+//-----------------------------------------------------------------------------
+
+class QVisitorPrivate : public QDumperBase
+{
+public:
+ QVisitorPrivate();
+ ~QVisitorPrivate();
+
+ void setIndent(unsigned indent);
+
+ void visitNode(const QObject& object);
+ void visitComplete();
+
+private:
+ class Node
+ {
+ public:
+ Node();
+ ~Node();
+
+ QList<QByteArray> m_annotation;
+ QList<Node*> m_children;
+
+ typedef QList<Node*>::const_iterator child_iterator;
+ };
+
+private:
+ Node* findNode(const QObject* object) const;
+ QByteArray branchBuffer(const QList<bool>& branches, bool isNodeLine, bool isLastChild) const;
+ void dumpRecursive(const Node& node, QList<bool> branches, bool isLastChild);
+ void dumpNode(const Node& node, const QList<bool>& branches, bool isLastChild);
+
+private:
+ unsigned m_indent;
+
+ QScopedPointer<Node> m_root;
+
+ // Hash table used to associate internal nodes with QObjects
+ typedef QHash<const QObject*, Node*> Hash;
+ Hash m_hash;
+};
+
+static const unsigned DefaultIndent = 2;
+
+QVisitorPrivate::QVisitorPrivate()
+ : m_indent(DefaultIndent)
+{
+
+}
+
+QVisitorPrivate::~QVisitorPrivate()
+{
+
+}
+
+void QVisitorPrivate::setIndent(unsigned indent)
+{
+ m_indent = indent;
+}
+
+// Builds up a mirror of the object tree, rooted in m_root, with each node
+// storing annotations generated by
+void QVisitorPrivate::visitNode(const QObject& object)
+{
+ QObject* const objectParent = object.parent();
+ Node* const nodeParent = objectParent ? findNode(objectParent) : 0;
+
+ // Create a new node and store in scoped pointer for exception safety
+ Node* node = new Node;
+ QScopedPointer<Node> nodePtr(node);
+
+ // Associate node with QObject
+ m_hash.insert(&object, node);
+
+ // Insert node into internal tree
+ if (nodeParent)
+ {
+ nodeParent->m_children.append(nodePtr.take());
+ }
+ else
+ {
+ Q_ASSERT(m_root.isNull());
+ m_root.reset(nodePtr.take());
+ }
+
+ // Generate and store annotations
+ QAnnotator* annotator;
+ foreach(annotator, m_annotators)
+ node->m_annotation.append( annotator->annotation(object) );
+}
+
+void QVisitorPrivate::visitComplete()
+{
+ QList<bool> branches;
+ static const bool isLastChild = true;
+ dumpRecursive(*m_root, branches, isLastChild);
+ m_root.reset(0);
+}
+
+QVisitorPrivate::Node* QVisitorPrivate::findNode(const QObject* object) const
+{
+ Hash::const_iterator i = m_hash.find(object);
+ return (m_hash.end() == i) ? 0 : *i;
+}
+
+QByteArray QVisitorPrivate::branchBuffer
+ (const QList<bool>& branches, bool isNodeLine, bool isLastChild) const
+{
+ const int depth = branches.count();
+
+ const QByteArray indent(m_indent, ' ');
+ const QByteArray horiz(m_indent, '-');
+
+ QByteArray buffer;
+ QTextStream stream(&buffer);
+
+ for (int i=0; i<depth-1; ++i) {
+ if (branches[i])
+ stream << '|';
+ else
+ stream << ' ';
+ stream << indent;
+ }
+
+ if (depth) {
+ if (isNodeLine)
+ stream << '+' << horiz;
+ else {
+ if (!isLastChild)
+ stream << '|';
+ else
+ stream << ' ';
+ stream << indent;
+ }
+ }
+
+ stream.flush();
+ buffer.push_front(m_prefix);
+
+ return buffer;
+}
+
+void QVisitorPrivate::dumpRecursive
+ (const Node& node, QList<bool> branches, bool isLastChild)
+{
+ dumpNode(node, branches, isLastChild);
+
+ // Recurse down tree
+ const Node::child_iterator begin = node.m_children.begin();
+ const Node::child_iterator end = node.m_children.end();
+ for (Node::child_iterator i = begin; end != i; ++i) {
+
+ isLastChild = (end == i + 1);
+
+ if (begin == i)
+ branches.push_back(!isLastChild);
+ else
+ branches.back() = !isLastChild;
+
+ static const bool isNodeLine = false;
+ const QByteArray buffer = branchBuffer(branches, isNodeLine, false);
+ qDebug() << buffer.constData();
+
+ dumpRecursive(**i, branches, isLastChild);
+ }
+}
+
+void QVisitorPrivate::dumpNode
+ (const Node& node, const QList<bool>& branches, bool isLastChild)
+{
+ const QList<QByteArray>::const_iterator
+ begin = node.m_annotation.begin(), end = node.m_annotation.end();
+
+ if (begin == end) {
+ // No annotations - just dump the object pointer
+ const bool isNodeLine = true;
+ QByteArray buffer = branchBuffer(branches, isNodeLine, isLastChild);
+ qDebug() << 0;
+ }
+ else {
+ // Dump annotations
+ for (QList<QByteArray>::const_iterator i = begin; end != i; ++i) {
+ const bool isNodeLine = (begin == i);
+ QByteArray buffer = branchBuffer(branches, isNodeLine, isLastChild);
+ buffer.append(*i);
+ qDebug() << buffer.constData();
+ }
+ }
+}
+
+
+// QVisitorPrivate::Node
+
+QVisitorPrivate::Node::Node()
+{
+
+}
+
+QVisitorPrivate::Node::~Node()
+{
+ Node* child;
+ foreach(child, m_children)
+ delete child;
+}
+
+
+// QVisitor
+
+QVisitor::QVisitor()
+ : d_ptr(new QVisitorPrivate)
+{
+
+}
+
+QVisitor::~QVisitor()
+{
+
+}
+
+void QVisitor::setPrefix(const QString& prefix)
+{
+ d_func()->setPrefix(prefix);
+}
+
+void QVisitor::setIndent(unsigned indent)
+{
+ d_func()->setIndent(indent);
+}
+
+void QVisitor::addAnnotator(QAnnotator* annotator)
+{
+ d_func()->addAnnotator(annotator);
+}
+
+void QVisitor::visitPrepare()
+{
+ // Do nothing
+}
+
+void QVisitor::visitNode(const QObject& object)
+{
+ d_func()->visitNode(object);
+}
+
+void QVisitor::visitComplete()
+{
+ d_func()->visitComplete();
+}
+
+
+//-----------------------------------------------------------------------------
+// Utility functions
+//-----------------------------------------------------------------------------
+
+void addDefaultAnnotators_sys(QDumper& visitor);
+void addDefaultAnnotators_sys(QVisitor& visitor);
+
+void addDefaultAnnotators(QDumper& dumper)
+{
+ dumper.addAnnotator(new QAnnotatorBasic);
+ dumper.addAnnotator(new QAnnotatorWidget);
+
+ // Add platform-specific annotators
+ addDefaultAnnotators_sys(dumper);
+}
+
+void addDefaultAnnotators(QVisitor& visitor)
+{
+ visitor.addAnnotator(new QAnnotatorBasic);
+ visitor.addAnnotator(new QAnnotatorWidget);
+
+ // Add platform-specific annotators
+ addDefaultAnnotators_sys(visitor);
+}
+
+void dumpTreeFromRoot(const QObject& root, QVisitor& visitor)
+{
+ // Set up iteration range
+ ObjectTree::DepthFirstConstIterator begin(root), end;
+
+ // Invoke generic visitor algorithm
+ ObjectTree::visit(begin, end, visitor);
+}
+
+void dumpTreeFromLeaf(const QObject& leaf, QVisitor& visitor)
+{
+ // Walk up to root
+ const QObject* root = &leaf;
+ while(root->parent())
+ {
+ root = root->parent();
+ }
+
+ dumpTreeFromRoot(*root, visitor);
+}
+
+void dumpAncestors(const QObject& leaf, QVisitor& visitor)
+{
+ // Set up iteration range
+ ObjectTree::AncestorConstIterator begin(leaf), end;
+
+ // Invoke generic visitor algorithm
+ ObjectTree::visit(begin, end, visitor);
+}
+
+
+} // namespace ObjectDump
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/objectdump.h b/src/3rdparty/phonon/mmf/objectdump.h
new file mode 100644
index 0000000..86aeaba
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/objectdump.h
@@ -0,0 +1,164 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef OBJECTDUMP_H
+#define OBJECTDUMP_H
+
+#include <QObject>
+#include <QList>
+#include <QByteArray>
+#include <QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+namespace ObjectDump
+{
+
+/**
+ * Abstract base for annotator classes invoked by QVisitor.
+ */
+class QAnnotator : public QObject
+{
+ Q_OBJECT
+public:
+ virtual ~QAnnotator();
+ virtual QList<QByteArray> annotation(const QObject& object) = 0;
+};
+
+/**
+ * Annotator which replicates QObject::dumpObjectTree functionality.
+ */
+class QAnnotatorBasic : public QAnnotator
+{
+ Q_OBJECT
+public:
+ QList<QByteArray> annotation(const QObject& object);
+};
+
+/**
+ * Annotator which returns widget information.
+ */
+class QAnnotatorWidget : public QAnnotator
+{
+ Q_OBJECT
+public:
+ QList<QByteArray> annotation(const QObject& object);
+};
+
+
+class QDumperPrivate;
+
+/**
+ * Class used to dump information about individual QObjects.
+ */
+class QDumper : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDumper)
+
+public:
+ QDumper();
+ ~QDumper();
+
+ /**
+ * Specify a prefix, to be printed on each line of output.
+ */
+ void setPrefix(const QString& prefix);
+
+ /**
+ * Takes ownership of annotator.
+ */
+ void addAnnotator(QAnnotator* annotator);
+
+ /**
+ * Invoke each annotator on the object and write to debug output.
+ */
+ void dumpObject(const QObject& object);
+
+private:
+ QScopedPointer<QDumperPrivate> d_ptr;
+
+};
+
+
+class QVisitorPrivate;
+
+/**
+ * Visitor class which dumps information about nodes in the object tree.
+ */
+class QVisitor : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QVisitor)
+
+public:
+ QVisitor();
+ ~QVisitor();
+
+ /**
+ * Specify a prefix, to be printed on each line of output.
+ */
+ void setPrefix(const QString& prefix);
+
+ /**
+ * Set number of spaces by which each level of the tree is indented.
+ */
+ void setIndent(unsigned indent);
+
+ /**
+ * Called by the visitor algorithm before starting the visit.
+ */
+ void visitPrepare();
+
+ /**
+ * Called by the visitor algorithm as each node is visited.
+ */
+ void visitNode(const QObject& object);
+
+ /**
+ * Called by the visitor algorithm when the visit is complete.
+ */
+ void visitComplete();
+
+ /**
+ * Takes ownership of annotator.
+ */
+ void addAnnotator(QAnnotator* annotator);
+
+private:
+ QScopedPointer<QVisitorPrivate> d_ptr;
+
+};
+
+
+//-----------------------------------------------------------------------------
+// Utility functions
+//-----------------------------------------------------------------------------
+
+void addDefaultAnnotators(QDumper& dumper);
+void addDefaultAnnotators(QVisitor& visitor);
+
+void dumpTreeFromRoot(const QObject& root, QVisitor& visitor);
+void dumpTreeFromLeaf(const QObject& leaf, QVisitor& visitor);
+void dumpAncestors(const QObject& leaf, QVisitor& visitor);
+
+} // namespace ObjectDump
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/objectdump_symbian.cpp b/src/3rdparty/phonon/mmf/objectdump_symbian.cpp
new file mode 100644
index 0000000..edad537
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/objectdump_symbian.cpp
@@ -0,0 +1,160 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QTextStream>
+#include <QWidget>
+#include <coecntrl.h>
+#include "objectdump_symbian.h"
+
+#include <QtGui/private/qwidget_p.h> // to access QWExtra
+
+QT_BEGIN_NAMESPACE
+
+namespace ObjectDump
+{
+namespace Symbian
+{
+
+QList<QByteArray> QAnnotatorWidget::annotation(const QObject& object)
+{
+ QList<QByteArray> result;
+
+ const QWidget* widget = qobject_cast<const QWidget*>(&object);
+ if (widget) {
+
+ const QWExtra* extra = qt_widget_private(const_cast<QWidget *>(widget))->extraData();
+
+ if (extra) {
+
+ QByteArray array;
+ QTextStream stream(&array);
+
+ stream << "widget (Symbian): ";
+ stream << "activated " << extra->activated << ' ';
+ stream << "nativePaintMode " << extra->nativePaintMode << ' ';
+
+ stream.flush();
+ result.append(array);
+ }
+ }
+
+ return result;
+}
+
+QList<QByteArray> QAnnotatorControl::annotation(const QObject& object)
+{
+ QList<QByteArray> result;
+
+ const QWidget* widget = qobject_cast<const QWidget*>(&object);
+ if (widget) {
+
+ const CCoeControl* control = widget->effectiveWinId();
+ if (control) {
+
+ QByteArray array;
+ QTextStream stream(&array);
+
+ stream << "control: " << control << ' ';
+ stream << "parent " << control->Parent() << ' ';
+
+ if (control->IsVisible())
+ stream << "visible ";
+ else
+ stream << "invisible ";
+
+ stream << control->Position().iX << ',' << control->Position().iY << ' ';
+ stream << control->Size().iWidth << 'x' << control->Size().iHeight;
+
+ if (control->OwnsWindow())
+ stream << " ownsWindow ";
+
+ stream.flush();
+ result.append(array);
+ }
+ }
+
+ return result;
+}
+
+QList<QByteArray> QAnnotatorWindow::annotation(const QObject& object)
+{
+ QList<QByteArray> result;
+
+ const QWidget* widget = qobject_cast<const QWidget*>(&object);
+ if (widget) {
+
+ const CCoeControl* control = widget->effectiveWinId();
+
+ if (control) {
+ RDrawableWindow *const window = control->DrawableWindow();
+ if(window) {
+ QByteArray array;
+ QTextStream stream(&array);
+
+ stream << "window: ";
+
+ // Server-side address of CWsWindow object
+ // This is useful for correlation with the window tree dumped by the window
+ // server (see RWsSession::LogCommand).
+ // Cast to a void pointer so that log output is in hexadecimal format.
+ stream << "srv " << reinterpret_cast<const void*>(window->WsHandle()) << ' ';
+
+ stream << "group " << window->WindowGroupId() << ' ';
+
+ // Client-side handle to the parent window.
+ // Cast to a void pointer so that log output is in hexadecimal format.
+ stream << "parent " << reinterpret_cast<const void*>(window->Parent()) << ' ';
+
+ stream << window->Position().iX << ',' << window->Position().iY << ' ';
+ stream << '(' << window->AbsPosition().iX << ',' << window->AbsPosition().iY << ") ";
+ stream << window->Size().iWidth << 'x' << window->Size().iHeight << ' ';
+
+ const TDisplayMode displayMode = window->DisplayMode();
+ stream << "mode " << displayMode << ' ';
+
+ stream << "ord " << window->OrdinalPosition();
+
+ stream.flush();
+ result.append(array);
+ }
+ }
+ }
+
+ return result;
+}
+
+} // namespace Symbian
+
+void addDefaultAnnotators_sys(QDumper& dumper)
+{
+ dumper.addAnnotator(new Symbian::QAnnotatorWidget);
+ dumper.addAnnotator(new Symbian::QAnnotatorControl);
+ dumper.addAnnotator(new Symbian::QAnnotatorWindow);
+}
+
+void addDefaultAnnotators_sys(QVisitor& visitor)
+{
+ visitor.addAnnotator(new Symbian::QAnnotatorWidget);
+ visitor.addAnnotator(new Symbian::QAnnotatorControl);
+ visitor.addAnnotator(new Symbian::QAnnotatorWindow);
+}
+
+} // namespace ObjectDump
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/objectdump_symbian.h b/src/3rdparty/phonon/mmf/objectdump_symbian.h
new file mode 100644
index 0000000..563c862
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/objectdump_symbian.h
@@ -0,0 +1,66 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef OBJECTDUMP_SYMBIAN_H
+#define OBJECTDUMP_SYMBIAN_H
+
+#include "objectdump.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace ObjectDump
+{
+namespace Symbian
+{
+
+/**
+ * Annotator which returns Symbian-specific widget information
+ */
+class QAnnotatorWidget : public QAnnotator
+{
+ Q_OBJECT
+public:
+ QList<QByteArray> annotation(const QObject& object);
+};
+
+/**
+ * Annotator which returns control information
+ */
+class QAnnotatorControl : public QAnnotator
+{
+ Q_OBJECT
+public:
+ QList<QByteArray> annotation(const QObject& object);
+};
+
+/**
+ * Annotator which returns window information
+ */
+class QAnnotatorWindow : public QAnnotator
+{
+ Q_OBJECT
+public:
+ QList<QByteArray> annotation(const QObject& object);
+};
+
+} // namespace Symbian
+} // namespace ObjectDump
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/objecttree.cpp b/src/3rdparty/phonon/mmf/objecttree.cpp
new file mode 100644
index 0000000..06b0ced
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/objecttree.cpp
@@ -0,0 +1,100 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QTextStream>
+#include <QWidget>
+#include "objecttree.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace ObjectTree
+{
+
+DepthFirstConstIterator::DepthFirstConstIterator()
+ : m_pointee(0)
+{
+
+}
+
+DepthFirstConstIterator::DepthFirstConstIterator
+ (const QObject& root)
+ : m_pointee(&root)
+{
+
+}
+
+DepthFirstConstIterator&
+ DepthFirstConstIterator::operator++()
+{
+ const QObjectList& children = m_pointee->children();
+
+ if (children.count() == 0) {
+ backtrack();
+ }
+ else {
+ m_history.push(0);
+ m_pointee = children.first();
+ }
+
+ return *this;
+}
+
+void DepthFirstConstIterator::backtrack()
+{
+ if (m_history.count()) {
+ const int index = m_history.top();
+ m_history.pop();
+
+ const QObjectList& siblings = m_pointee->parent()->children();
+ if (siblings.count() > index + 1) {
+ m_history.push(index + 1);
+ m_pointee = siblings[index + 1];
+ }
+ else {
+ m_pointee = m_pointee->parent();
+ backtrack();
+ }
+ }
+ else {
+ // Reached end of search
+ m_pointee = 0;
+ }
+}
+
+
+
+AncestorConstIterator::AncestorConstIterator()
+{
+
+}
+
+AncestorConstIterator::AncestorConstIterator(const QObject& leaf)
+{
+ m_ancestors.push(&leaf);
+ QObject* ancestor = leaf.parent();
+ while(ancestor)
+ {
+ m_ancestors.push(ancestor);
+ ancestor = ancestor->parent();
+ }
+}
+
+} // namespace ObjectTree
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/objecttree.h b/src/3rdparty/phonon/mmf/objecttree.h
new file mode 100644
index 0000000..96adb6f
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/objecttree.h
@@ -0,0 +1,115 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef OBJECTTREE_H
+#define OBJECTTREE_H
+
+#include <QObject>
+#include <QStack>
+
+QT_BEGIN_NAMESPACE
+
+namespace ObjectTree
+{
+
+/**
+ * Depth-first iterator for QObject tree
+ */
+class DepthFirstConstIterator
+{
+public:
+ DepthFirstConstIterator();
+ DepthFirstConstIterator(const QObject& root);
+
+ DepthFirstConstIterator& operator++();
+
+ inline bool operator==(const DepthFirstConstIterator& other) const
+ { return other.m_pointee == m_pointee; }
+
+ inline bool operator!=(const DepthFirstConstIterator& other) const
+ { return other.m_pointee != m_pointee; }
+
+ inline const QObject* operator->() const { return m_pointee; }
+ inline const QObject& operator*() const { return *m_pointee; }
+
+private:
+ void backtrack();
+
+private:
+ const QObject* m_pointee;
+ QStack<int> m_history;
+};
+
+/**
+ * Ancestor iterator for QObject tree
+ */
+class AncestorConstIterator
+{
+public:
+ AncestorConstIterator();
+ AncestorConstIterator(const QObject& root);
+
+ inline AncestorConstIterator& operator++()
+ { m_ancestors.pop(); return *this; }
+
+ inline bool operator==(const AncestorConstIterator& other) const
+ { return other.m_ancestors == m_ancestors; }
+
+ inline bool operator!=(const AncestorConstIterator& other) const
+ { return other.m_ancestors != m_ancestors; }
+
+ inline const QObject* operator->() const { return m_ancestors.top(); }
+ inline const QObject& operator*() const { return *m_ancestors.top(); }
+
+private:
+ QStack<const QObject*> m_ancestors;
+
+};
+
+/**
+ * Generic algorithm for visiting nodes in an object tree. Nodes in the
+ * tree are visited in a const context, therefore they are not modified
+ * by this algorithm.
+ *
+ * Visitor must provide functions with the following signatures:
+ *
+ * Called before visit begins
+ * void visitPrepare()
+ *
+ * Called on each node visited
+ * void visitNode(const QObject& object)
+ *
+ * Called when visit is complete
+ * void visitComplete()
+ */
+template <class Iterator, class Visitor>
+void visit(Iterator begin, Iterator end, Visitor& visitor)
+{
+ visitor.visitPrepare();
+
+ for ( ; begin != end; ++begin)
+ visitor.visitNode(*begin);
+
+ visitor.visitComplete();
+}
+
+} // namespace ObjectTree
+
+QT_END_NAMESPACE
+
+#endif // OBJECTTREE_H
diff --git a/src/3rdparty/phonon/mmf/stereowidening.cpp b/src/3rdparty/phonon/mmf/stereowidening.cpp
new file mode 100644
index 0000000..f90651b
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/stereowidening.cpp
@@ -0,0 +1,93 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <StereoWideningBase.h>
+#include "stereowidening.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+// Define functions which depend on concrete native effect class name
+PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(StereoWidening)
+
+/*! \class MMF::StereoWidening
+ \internal
+*/
+
+StereoWidening::StereoWidening(QObject *parent, const QList<EffectParameter>& parameters)
+ : AbstractAudioEffect::AbstractAudioEffect(parent, parameters)
+{
+
+}
+
+int StereoWidening::parameterChanged(const EffectParameter &param,
+ const QVariant &value)
+{
+ Q_ASSERT_X(param.id() == ParameterBase, Q_FUNC_INFO, "Invalid parameter ID");
+
+ const qreal externalLevel = value.toReal();
+ const int internalLevel = param.toInternalValue(externalLevel);
+
+ TRAPD(err, concreteEffect()->SetStereoWideningLevelL(internalLevel));
+
+ return err;
+}
+
+//-----------------------------------------------------------------------------
+// Static functions
+//-----------------------------------------------------------------------------
+
+const char* StereoWidening::description()
+{
+ return "Stereo widening";
+}
+
+bool StereoWidening::getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter> &parameters)
+{
+ bool supported = false;
+
+ QScopedPointer<CStereoWidening> effect;
+ TRAPD(err, effect.reset(CStereoWidening::NewL(*stream)));
+
+ if (KErrNone == err) {
+ supported = true;
+
+ const qreal defaultValue =
+ Phonon::MMF::EffectParameter::toExternalValue
+ (effect->StereoWideningLevel(), 0, 100);
+
+ EffectParameter param(
+ /* parameterId */ ParameterBase,
+ /* name */ tr("Level (%)"),
+ /* hints */ EffectParameter::IntegerHint,
+ /* defaultValue */ QVariant(defaultValue),
+ /* minimumValue */ QVariant(qreal(-1.0)),
+ /* maximumValue */ QVariant(qreal(+1.0)));
+
+ param.setInternalRange(0, 100);
+ parameters.append(param);
+ }
+
+ return supported;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/stereowidening.h b/src/3rdparty/phonon/mmf/stereowidening.h
new file mode 100644
index 0000000..c967e37
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/stereowidening.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_STEREOWIDENING_H
+#define PHONON_MMF_STEREOWIDENING_H
+
+#include "abstractaudioeffect.h"
+
+class CStereoWidening;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * @short A "bass boost" effect.
+ */
+class StereoWidening : public AbstractAudioEffect
+{
+ Q_OBJECT
+public:
+ StereoWidening(QObject *parent, const QList<EffectParameter>& parameters);
+
+ // Static interface required by EffectFactory
+ static const char* description();
+ static bool getParameters(CMdaAudioOutputStream *stream,
+ QList<EffectParameter>& parameters);
+
+protected:
+ // AbstractAudioEffect
+ virtual void createEffect(AudioPlayer::NativePlayer *player);
+ virtual int parameterChanged(const EffectParameter &param,
+ const QVariant &value);
+
+private:
+ CStereoWidening *concreteEffect();
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/3rdparty/phonon/mmf/utils.cpp b/src/3rdparty/phonon/mmf/utils.cpp
new file mode 100644
index 0000000..c556afc
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/utils.cpp
@@ -0,0 +1,260 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "utils.h"
+#include <e32std.h>
+#include <mmf/common/mmferrors.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \namespace Phonon::MMF::Utils
+ \internal
+*/
+
+/*! \class Phonon::MMF::TTraceContext
+ \internal
+*/
+
+/*! \enum Phonon::MMF::PanicCode
+ \internal
+*/
+
+/*! \enum Phonon::MMF::TTraceCategory
+ \internal
+*/
+
+/*! \enum Phonon::MMF::MediaType
+ \internal
+*/
+
+_LIT(PanicCategory, "Phonon::MMF");
+
+void MMF::Utils::panic(PanicCode code)
+{
+ User::Panic(PanicCategory, code);
+}
+
+_LIT(KMimePrefixAudio, "audio/");
+_LIT(KMimePrefixVideo, "video/");
+_LIT(KMimeSDP, "application/sdp");
+
+enum ConstantStringLengths {
+ KMimePrefixLength = 6, // either "audio/" or "video/",
+ KMimeSDPLength = 15 // "application/sdp"
+};
+
+MMF::MediaType MMF::Utils::mimeTypeToMediaType(const TDesC& mimeType)
+{
+ if (mimeType.Left(KMimePrefixLength).Compare(KMimePrefixAudio) == 0) {
+ return MediaTypeAudio;
+ } else if (mimeType.Left(KMimePrefixLength).Compare(KMimePrefixVideo) == 0 ||
+ mimeType.Left(KMimeSDPLength).Compare(KMimeSDP) == 0) {
+ return MediaTypeVideo;
+ } else
+ return MediaTypeUnknown;
+}
+
+QString MMF::Utils::symbianErrorToString(int errorCode)
+{
+ /**
+ * Here we translate only the error codes which are likely to be
+ * meaningful to the user. For example, when an error occurs
+ * during opening of a media file, displaying "not found" or
+ * "permission denied" is informative. On the other hand,
+ * differentiating between KErrGeneral and KErrArgument at the UI
+ * level does not make sense.
+ */
+ switch (errorCode)
+ {
+ // System-wide errors
+ case KErrNone:
+ return tr("No error");
+ case KErrNotFound:
+ return tr("Not found");
+ case KErrNoMemory:
+ return tr("Out of memory");
+ case KErrNotSupported:
+ return tr("Not supported");
+ case KErrOverflow:
+ return tr("Overflow");
+ case KErrUnderflow:
+ return tr("Underflow");
+ case KErrAlreadyExists:
+ return tr("Already exists");
+ case KErrPathNotFound:
+ return tr("Path not found");
+ case KErrInUse:
+ return tr("In use");
+ case KErrNotReady:
+ return tr("Not ready");
+ case KErrAccessDenied:
+ return tr("Access denied");
+ case KErrCouldNotConnect:
+ return tr("Could not connect");
+ case KErrDisconnected:
+ return tr("Disconnected");
+ case KErrPermissionDenied:
+ return tr("Permission denied");
+
+ // Multimedia framework errors
+ case KErrMMNotEnoughBandwidth:
+ return tr("Insufficient bandwidth");
+ case KErrMMSocketServiceNotFound:
+ case KErrMMServerSocket:
+ return tr("Network unavailable");
+ case KErrMMNetworkRead:
+ case KErrMMNetworkWrite:
+ case KErrMMUDPReceive:
+ return tr("Network communication error");
+ case KErrMMServerNotSupported:
+ return tr("Streaming not supported");
+ case KErrMMServerAlert:
+ return tr("Server alert");
+ case KErrMMInvalidProtocol:
+ return tr("Invalid protocol");
+ case KErrMMInvalidURL:
+ return tr("Invalid URL");
+ case KErrMMMulticast:
+ return tr("Multicast error");
+ case KErrMMProxyServer:
+ case KErrMMProxyServerConnect:
+ return tr("Proxy server error");
+ case KErrMMProxyServerNotSupported:
+ return tr("Proxy server not supported");
+ case KErrMMAudioDevice:
+ return tr("Audio output error");
+ case KErrMMVideoDevice:
+ return tr("Video output error");
+ case KErrMMDecoder:
+ return tr("Decoder error");
+ case KErrMMPartialPlayback:
+ return tr("Audio or video components could not be played");
+ case KErrMMDRMNotAuthorized:
+ return tr("DRM error");
+
+ /*
+ // We don't use QoS settings
+ case KErrMMQosLowBandwidth:
+ case KErrMMQosUnsupportedTrafficClass:
+ case KErrMMQosPoorTrafficClass:
+ case KErrMMQosUnsupportedParameters:
+ case KErrMMQosPoorParameters:
+ case KErrMMQosNotSupported:
+ */
+
+ // Catch-all for errors other than those above
+ default:
+ {
+ return tr("Unknown error (%1)").arg(errorCode);
+ }
+ }
+}
+
+#ifndef QT_NO_DEBUG
+
+#include <hal.h>
+#include <hal_data.h>
+#include <gdi.h>
+#include <eikenv.h>
+
+struct TScreenInfo
+{
+ int width;
+ int height;
+ int bpp;
+ const char* address;
+ int initialOffset;
+ int lineOffset;
+ TDisplayMode displayMode;
+};
+
+static void getScreenInfoL(TScreenInfo& info)
+{
+ info.displayMode = CEikonEnv::Static()->ScreenDevice()->DisplayMode();
+
+ // Then we must set these as the input parameter
+ info.width = info.displayMode;
+ info.height = info.displayMode;
+ info.initialOffset = info.displayMode;
+ info.lineOffset = info.displayMode;
+ info.bpp = info.displayMode;
+
+ User::LeaveIfError( HAL::Get(HALData::EDisplayXPixels, info.width) );
+ User::LeaveIfError( HAL::Get(HALData::EDisplayYPixels, info.width) );
+
+ int address;
+ User::LeaveIfError( HAL::Get(HALData::EDisplayMemoryAddress, address) );
+ info.address = reinterpret_cast<const char*>(address);
+
+ User::LeaveIfError( HAL::Get(HALData::EDisplayOffsetToFirstPixel, info.initialOffset) );
+
+ User::LeaveIfError( HAL::Get(HALData::EDisplayOffsetBetweenLines, info.lineOffset) );
+
+ User::LeaveIfError( HAL::Get(HALData::EDisplayBitsPerPixel, info.bpp) );
+}
+
+
+QColor MMF::Utils::getScreenPixel(const QPoint& pos)
+{
+ TScreenInfo info;
+ TRAPD(err, getScreenInfoL(info));
+ QColor pixel;
+ if (err == KErrNone and pos.x() < info.width and pos.y() < info.height)
+ {
+ const int bytesPerPixel = info.bpp / 8;
+ Q_ASSERT(bytesPerPixel >= 3);
+
+ const int stride = (info.width * bytesPerPixel) + info.lineOffset;
+
+ const char* ptr =
+ info.address
+ + info.initialOffset
+ + pos.y() * stride
+ + pos.x() * bytesPerPixel;
+
+ // BGRA
+ pixel.setBlue(*ptr++);
+ pixel.setGreen(*ptr++);
+ pixel.setRed(*ptr++);
+
+ if (bytesPerPixel == 4)
+ pixel.setAlpha(*ptr++);
+ }
+ return pixel;
+}
+
+// Debugging: for debugging video visibility
+void MMF::Utils::dumpScreenPixelSample()
+{
+ for (int i=0; i<20; ++i) {
+ const QPoint pos(i*10, i*10);
+ const QColor pixel = Utils::getScreenPixel(pos);
+ RDebug::Printf(
+ "Phonon::MMF::Utils::dumpScreenPixelSample %d %d = %d %d %d %d",
+ pos.x(), pos.y(), pixel.red(), pixel.green(), pixel.blue(), pixel.alpha()
+ );
+ }
+}
+
+#endif // _DEBUG
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/utils.h b/src/3rdparty/phonon/mmf/utils.h
new file mode 100644
index 0000000..acad55a
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/utils.h
@@ -0,0 +1,176 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_UTILS_H
+#define PHONON_MMF_UTILS_H
+
+#include <private/qcore_symbian_p.h>
+#include <e32debug.h> // for RDebug
+#include <QtCore/QCoreApplication> // for Q_DECLARE_TR_FUNCTIONS
+#include <QColor>
+
+#include "defs.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+/**
+ * Panic codes for fatal errors
+ */
+enum PanicCode {
+ InvalidStatePanic = 1,
+ InvalidMediaTypePanic = 2,
+ InvalidBackendInterfaceClass = 3,
+ AudioUtilityUrlNotSupported = 4
+};
+
+class Utils
+{
+ Q_DECLARE_TR_FUNCTIONS(Phonon::MMF)
+
+public:
+/**
+ * Raise a fatal exception
+ */
+static void panic(PanicCode code);
+
+/**
+ * Determines whether the provided MIME type is an audio or video
+ * type. If it is neither, the function returns MediaTypeUnknown.
+ */
+static MediaType mimeTypeToMediaType(const TDesC& mimeType);
+
+/**
+ * Translates a Symbian error code into a user-readable string.
+ */
+static QString symbianErrorToString(int errorCode);
+
+#ifndef QT_NO_DEBUG
+/**
+ * Retrieve color of specified pixel from the screen.
+ */
+static QColor getScreenPixel(const QPoint& pos);
+
+/**
+ * Samples a small number of pixels from the screen, and dumps their
+ * colors to the debug log.
+ */
+static void dumpScreenPixelSample();
+#endif
+};
+
+/**
+ * Available trace categories;
+ */
+enum TTraceCategory {
+ /**
+ * Backend
+ */
+ EBackend = 0x00000001,
+
+ /**
+ * Functions which map directly to the public Phonon audio API
+ */
+ EAudioApi = 0x00000010,
+
+ /**
+ * Internal functions in the audio implementation
+ */
+ EAudioInternal = 0x00000020,
+
+ /**
+ * Functions which map directly to the public Phonon video API
+ */
+ EVideoApi = 0x00010000,
+
+ /**
+ * Internal functions in the video implementation
+ */
+ EVideoInternal = 0x00020000
+};
+
+/**
+ * Mask indicating which trace categories are enabled
+ *
+ * Note that, at the moment, this is a compiled static constant. For
+ * runtime control over enabled trace categories, this could be replaced
+ * by a per-thread singleton object which owns the trace mask, and which
+ * exposes an API allowing it to be modified.
+ */
+static const TUint KTraceMask = 0xffffffff;
+
+/**
+ * Data structure used by tracing macros
+ */
+class TTraceContext
+{
+public:
+ TTraceContext(const TText* aFunction, const TUint aAddr,
+ const TUint aCategory = 0)
+ : iFunction(aFunction),
+ iAddr(aAddr),
+ iCategory(aCategory) { }
+
+ /**
+ * Check whether iCategory appears in the trace mask
+ */
+ TBool Enabled() const {
+ return (iCategory == 0) or(iCategory & KTraceMask);
+ }
+
+ const TText* iFunction; // Name of function
+ const TUint iAddr; // 'this' pointer
+ const TUint iCategory;
+};
+
+// Macros used internally by the trace system
+#define _TRACE_PRINT RDebug::Print
+#define _TRACE_TEXT(x) (TPtrC((const TText *)(x)))
+#define _TRACE_MODULE Phonon::MMF
+
+// Macros available for use by implementation code
+#ifndef QT_NO_DEBUG
+#define TRACE_CONTEXT(_fn, _cat) const ::Phonon::MMF::TTraceContext _tc((TText*)L ## #_fn, (TUint)this, _cat);
+#define TRACE_ENTRY_0() { if (_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "+ Phonon::MMF::%s [0x%08x]"), _tc.iFunction, _tc.iAddr); }
+#define TRACE_ENTRY(string, args...) { if (_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "+ Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, args); }
+#define TRACE_EXIT_0() { if (_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "- Phonon::MMF::%s [0x%08x]"), _tc.iFunction, _tc.iAddr); }
+#define TRACE_EXIT(string, args...) { if (_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "- Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, args); }
+#define TRACE_RETURN(string, result) { if (_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## "r Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, result); } return result;
+#define TRACE_PANIC(code) { _TRACE_PRINT(_TRACE_TEXT(L ## "! Phonon::MMF::%s [0x%08x] panic %d"), _tc.iFunction, _tc.iAddr, code); } Utils::panic(code);
+#define TRACE_0(string) { if (_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## " Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr); }
+#define TRACE(string, args...) { if (_tc.Enabled()) _TRACE_PRINT(_TRACE_TEXT(L ## " Phonon::MMF::%s [0x%08x] " L ## string), _tc.iFunction, _tc.iAddr, args); }
+#else
+#define TRACE_CONTEXT(_fn, _cat)
+#define TRACE_ENTRY_0()
+#define TRACE_ENTRY(string, args...)
+#define TRACE_EXIT_0()
+#define TRACE_EXIT(string, args...)
+#define TRACE_RETURN(string, result) return result;
+#define TRACE_PANIC(code) Utils::panic(code);
+#define TRACE_0(string)
+#define TRACE(string, args...)
+#endif
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/mmf/videooutput_dsa.cpp b/src/3rdparty/phonon/mmf/videooutput_dsa.cpp
new file mode 100644
index 0000000..4f9ad7f
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videooutput_dsa.cpp
@@ -0,0 +1,183 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QtCore/private/qcore_symbian_p.h> // for qt_TRect2QRect
+#include <QtGui/private/qwidget_p.h> // to access QWExtra
+#include <QResizeEvent>
+#include <QMoveEvent>
+
+#include <coemain.h> // for CCoeEnv
+
+#include "ancestormovemonitor.h"
+#include "utils.h"
+#include "videooutput_dsa.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+DsaVideoOutput::DsaVideoOutput(QWidget *parent)
+ : AbstractVideoOutput(parent)
+ , m_ancestorMoveMonitor(0)
+{
+ TRACE_CONTEXT(DsaVideoOutput::DsaVideoOutput, EVideoInternal);
+ TRACE_ENTRY("parent 0x%08x", parent);
+
+ setPalette(QPalette(Qt::black));
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+ setAttribute(Qt::WA_NoSystemBackground, true);
+ setAutoFillBackground(false);
+
+ qt_widget_private(this)->extraData()->nativePaintMode = QWExtra::ZeroFill;
+ qt_widget_private(this)->extraData()->receiveNativePaintEvents = true;
+
+ getVideoWindowScreenRect();
+
+ dump();
+
+ TRACE_EXIT_0();
+}
+
+DsaVideoOutput::~DsaVideoOutput()
+{
+ TRACE_CONTEXT(DsaVideoOutput::~DsaVideoOutput, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ m_ancestorMoveMonitor->unRegisterTarget(this);
+
+ TRACE_EXIT_0();
+}
+
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+void MMF::DsaVideoOutput::setAncestorMoveMonitor(AncestorMoveMonitor *monitor)
+{
+ m_ancestorMoveMonitor = monitor;
+ registerForAncestorMoved();
+}
+
+const QRect& MMF::DsaVideoOutput::videoWindowScreenRect() const
+{
+ return m_videoWindowScreenRect;
+}
+
+void MMF::DsaVideoOutput::ancestorMoved()
+{
+ TRACE_CONTEXT(DsaVideoOutput::ancestorMoved, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ RWindowBase *const window = videoWindow();
+
+ if (window) {
+ const TPoint newWindowPosSymbian = window->AbsPosition();
+ const QPoint newWindowPos(newWindowPosSymbian.iX, newWindowPosSymbian.iY);
+
+ if (newWindowPos != m_videoWindowScreenRect.topLeft()) {
+ m_videoWindowScreenRect.moveTo(newWindowPos);
+ emit videoWindowScreenRectChanged();
+ }
+ }
+
+ TRACE_EXIT_0();
+}
+
+void MMF::DsaVideoOutput::beginNativePaintEvent(const QRect & /*controlRect*/)
+{
+ TRACE_CONTEXT(DsaVideoOutput::beginNativePaintEvent, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ emit beginVideoWindowNativePaint();
+}
+
+void MMF::DsaVideoOutput::endNativePaintEvent(const QRect & /*controlRect*/)
+{
+ TRACE_CONTEXT(DsaVideoOutput::endNativePaintEvent, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ // Ensure that draw ops are executed into the WSERV output framebuffer
+ CCoeEnv::Static()->WsSession().Flush();
+
+ emit endVideoWindowNativePaint();
+}
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+void MMF::DsaVideoOutput::getVideoWindowScreenRect()
+{
+ RWindowBase *const window = videoWindow();
+ if (window)
+ m_videoWindowScreenRect =
+ qt_TRect2QRect(TRect(window->AbsPosition(), window->Size()));
+}
+
+void MMF::DsaVideoOutput::registerForAncestorMoved()
+{
+ m_ancestorMoveMonitor->registerTarget(this);
+}
+
+void MMF::DsaVideoOutput::resizeEvent(QResizeEvent *event)
+{
+ TRACE_CONTEXT(DsaVideoOutput::resizeEvent, EVideoInternal);
+ TRACE("%d %d -> %d %d",
+ event->oldSize().width(), event->oldSize().height(),
+ event->size().width(), event->size().height());
+
+ if (event->size() != event->oldSize()) {
+ m_videoWindowScreenRect.setSize(event->size());
+ emit videoWindowScreenRectChanged();
+ }
+}
+
+void MMF::DsaVideoOutput::moveEvent(QMoveEvent *event)
+{
+ TRACE_CONTEXT(DsaVideoOutput::moveEvent, EVideoInternal);
+ TRACE("%d %d -> %d %d",
+ event->oldPos().x(), event->oldPos().y(),
+ event->pos().x(), event->pos().y());
+
+ if (event->pos() != event->oldPos()) {
+ m_videoWindowScreenRect.moveTo(event->pos());
+ emit videoWindowScreenRectChanged();
+ }
+}
+
+bool MMF::DsaVideoOutput::event(QEvent *event)
+{
+ TRACE_CONTEXT(DsaVideoOutput::event, EVideoInternal);
+
+ if (event->type() == QEvent::WinIdChange) {
+ TRACE_0("WinIdChange");
+ getVideoWindowScreenRect();
+ emit videoWindowChanged();
+ return true;
+ } else if (event->type() == QEvent::ParentChange) {
+ // Tell ancestor move monitor to update ancestor list for this widget
+ registerForAncestorMoved();
+ return true;
+ } else {
+ return QWidget::event(event);
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/videooutput_dsa.h b/src/3rdparty/phonon/mmf/videooutput_dsa.h
new file mode 100644
index 0000000..c37dad8
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videooutput_dsa.h
@@ -0,0 +1,109 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_VIDEOOUTPUT_DSA_H
+#define PHONON_MMF_VIDEOOUTPUT_DSA_H
+
+#include <QRect>
+
+#include "phonon/mmf/abstractvideooutput.h"
+
+QT_BEGIN_NAMESPACE
+
+class QResizeEvent;
+class QMoveEvent;
+
+namespace Phonon
+{
+namespace MMF
+{
+class AncestorMoveMonitor;
+
+/**
+ * @short Widget on which video is displayed by DSA rendering
+ *
+ * This implementation is used on devices with the legacy graphics
+ * subsystem, which does not support surfaces. On such devices,
+ * video rendering is done via Direct Screen Access (DSA), whereby
+ * the video decoder writes directly to the framebuffer. To ensure
+ * that the window server and video decoder do not try to draw to
+ * the same screen region at the same time, the video subsystem
+ * first requests permission to perform DSA. If the window server
+ * needs to draw to this screen region (for example to display a
+ * message dialog), it first notifies the video subsystem that it
+ * must stop rendering to this region.
+ *
+ * @see SurfaceVideoOutput
+ */
+class DsaVideoOutput
+ : public AbstractVideoOutput
+{
+ Q_OBJECT
+
+public:
+ DsaVideoOutput(QWidget *parent);
+ ~DsaVideoOutput();
+
+ void setAncestorMoveMonitor(AncestorMoveMonitor *monitor);
+
+ // Get absolute screen rectangle for video window
+ const QRect& videoWindowScreenRect() const;
+
+ // Called by AncestorMoveMonitor
+ void ancestorMoved();
+
+public Q_SLOTS:
+ // Callbacks received from Symbian QtGui implementation, when it
+ // begins / ends blitting the video widget's backing store to the
+ // window server.
+ void beginNativePaintEvent(const QRect & /*controlRect*/);
+ void endNativePaintEvent(const QRect & /*controlRect*/);
+
+Q_SIGNALS:
+ void videoWindowScreenRectChanged();
+
+ // Emitted when the Symbian QtGui implementation begins / ends
+ // blitting the video widget's backing store to the window server.
+ void beginVideoWindowNativePaint();
+ void endVideoWindowNativePaint();
+
+private:
+ void getVideoWindowScreenRect();
+ void registerForAncestorMoved();
+
+ // QWidget
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ bool event(QEvent *event);
+
+private:
+ // Not owned
+ AncestorMoveMonitor* m_ancestorMoveMonitor;
+
+ // Absolute screen rectangle on which video is displayed
+ QRect m_videoWindowScreenRect;
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif // !PHONON_MMF_VIDEOOUTPUT_DSA_H
+
diff --git a/src/3rdparty/phonon/mmf/videooutput_surface.cpp b/src/3rdparty/phonon/mmf/videooutput_surface.cpp
new file mode 100644
index 0000000..e9b2d3f
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videooutput_surface.cpp
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QResizeEvent>
+
+#include <QtCore/private/qcore_symbian_p.h> // for qt_TRect2QRect
+#include <QtGui/private/qwidget_p.h> // to access QWExtra
+
+#include "utils.h"
+#include "videooutput_surface.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+SurfaceVideoOutput::SurfaceVideoOutput(QWidget *parent)
+ : AbstractVideoOutput(parent)
+{
+ TRACE_CONTEXT(SurfaceVideoOutput::SurfaceVideoOutput, EVideoInternal);
+ TRACE_ENTRY("parent 0x%08x", parent);
+
+ qt_widget_private(this)->createExtra();
+ qt_widget_private(this)->extraData()->nativePaintMode = QWExtra::Disable;
+
+ TRACE_EXIT_0();
+}
+
+SurfaceVideoOutput::~SurfaceVideoOutput()
+{
+ TRACE_CONTEXT(SurfaceVideoOutput::~SurfaceVideoOutput, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ TRACE_EXIT_0();
+}
+
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+void MMF::SurfaceVideoOutput::resizeEvent(QResizeEvent *event)
+{
+ TRACE_CONTEXT(SurfaceVideoOutput::resizeEvent, EVideoInternal);
+ TRACE("%d %d -> %d %d",
+ event->oldSize().width(), event->oldSize().height(),
+ event->size().width(), event->size().height());
+
+ if (event->size() != event->oldSize())
+ emit videoWindowSizeChanged();
+}
+
+bool MMF::SurfaceVideoOutput::event(QEvent *event)
+{
+ TRACE_CONTEXT(SurfaceVideoOutput::event, EVideoInternal);
+
+ if (event->type() == QEvent::WinIdChange) {
+ TRACE_0("WinIdChange");
+ emit videoWindowChanged();
+ return true;
+ } else {
+ return QWidget::event(event);
+ }
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/videooutput_surface.h b/src/3rdparty/phonon/mmf/videooutput_surface.h
new file mode 100644
index 0000000..0b22a71
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videooutput_surface.h
@@ -0,0 +1,66 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_VIDEOOUTPUT_SURFACE_H
+#define PHONON_MMF_VIDEOOUTPUT_SURFACE_H
+
+#include "phonon/mmf/abstractvideooutput.h"
+
+QT_BEGIN_NAMESPACE
+
+class QResizeEvent;
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short Widget on which video is displayed by rendering to a surface
+ *
+ * This implementation is used on devices with a graphics subsystem which
+ * supports surfaces.
+ *
+ * @see DsaVideoOutput
+ */
+class SurfaceVideoOutput
+ : public AbstractVideoOutput
+{
+ Q_OBJECT
+
+public:
+ SurfaceVideoOutput(QWidget *parent);
+ ~SurfaceVideoOutput();
+
+Q_SIGNALS:
+ void videoWindowSizeChanged();
+
+private:
+ // QWidget
+ void resizeEvent(QResizeEvent *event);
+ bool event(QEvent *event);
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif // !PHONON_MMF_VIDEOOUTPUT_SURFACE_H
+
diff --git a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp
new file mode 100644
index 0000000..deb9774
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp
@@ -0,0 +1,317 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <coecntrl.h> // for CCoeControl
+
+#include <QApplication> // for QApplication::activeWindow
+#include <QtCore/private/qcore_symbian_p.h> // for qt_TRect2QRect
+
+#include "utils.h"
+#include "videooutput_dsa.h"
+#include "videoplayer_dsa.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+// Two-phase constructor idiom is used because construct() calls virtual
+// functions and therefore cannot be called from the AbstractVideoPlayer
+// C++ constructor.
+DsaVideoPlayer* DsaVideoPlayer::create(MediaObject *parent,
+ const AbstractPlayer *player)
+{
+ QScopedPointer<DsaVideoPlayer> self(new DsaVideoPlayer(parent, player));
+ self->construct();
+ return self.take();
+}
+
+DsaVideoPlayer::DsaVideoPlayer(MediaObject *parent, const AbstractPlayer *player)
+ : AbstractVideoPlayer(parent, player)
+ , m_dsaActive(false)
+ , m_dsaWasActive(false)
+{
+
+}
+
+DsaVideoPlayer::~DsaVideoPlayer()
+{
+
+}
+
+
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+void MMF::DsaVideoPlayer::videoWindowScreenRectChanged()
+{
+ Q_ASSERT(m_videoOutput);
+
+ QRect windowRect = static_cast<DsaVideoOutput *>(m_videoOutput)->videoWindowScreenRect();
+
+ // Clip to physical window size
+ // This is due to a defect in the layout when running on S60 3.2, which
+ // results in the rectangle of the video widget extending outside the
+ // screen in certain circumstances. These include the initial startup
+ // of the mediaplayer demo in portrait mode. When this rectangle is
+ // passed to the CVideoPlayerUtility, no video is rendered.
+ const TSize screenSize = m_screenDevice.SizeInPixels();
+ const QRect screenRect(0, 0, screenSize.iWidth, screenSize.iHeight);
+ windowRect = windowRect.intersected(screenRect);
+
+ // Recalculate scale factors. Pass 'false' as second parameter in order to
+ // suppress application of the change to the player - this is done at the end
+ // of the function.
+ updateScaleFactors(windowRect.size(), false);
+
+ m_videoScreenRect = qt_QRect2TRect(windowRect);
+
+ parametersChanged(WindowScreenRect | ScaleFactors);
+}
+
+void MMF::DsaVideoPlayer::suspendDirectScreenAccess()
+{
+ m_dsaWasActive = stopDirectScreenAccess();
+}
+
+void MMF::DsaVideoPlayer::resumeDirectScreenAccess()
+{
+ if (m_dsaWasActive) {
+ startDirectScreenAccess();
+ m_dsaWasActive = false;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+void MMF::DsaVideoPlayer::createPlayer()
+{
+ // A window handle must be provided in order to construct
+ // CVideoPlayerUtility. If no VideoOutput has yet been connected to this
+ // player, we temporarily use the top-level application window handle.
+ // No video ever gets rendered into this window; SetDisplayWindowL is
+ // always called before rendering actually begins.
+ if (!m_window)
+ m_window = QApplication::activeWindow()->effectiveWinId()->DrawableWindow();
+
+ const TInt priority = 0;
+ const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone;
+
+ CVideoPlayerUtility *player = 0;
+ QT_TRAP_THROWING(player = CVideoPlayerUtility::NewL(*this,
+ priority, preference,
+ m_wsSession, m_screenDevice,
+ *m_window,
+ m_videoScreenRect, m_videoScreenRect));
+ m_player.reset(player);
+
+ // CVideoPlayerUtility::NewL starts DSA
+ m_dsaActive = true;
+}
+
+void MMF::DsaVideoPlayer::initVideoOutput()
+{
+ Q_ASSERT(m_videoOutput);
+
+ bool connected = connect(
+ m_videoOutput, SIGNAL(videoWindowScreenRectChanged()),
+ this, SLOT(videoWindowScreenRectChanged())
+ );
+ Q_ASSERT(connected);
+
+ connected = connect(
+ m_videoOutput, SIGNAL(beginVideoWindowNativePaint()),
+ this, SLOT(suspendDirectScreenAccess())
+ );
+ Q_ASSERT(connected);
+
+ connected = connect(
+ m_videoOutput, SIGNAL(endVideoWindowNativePaint()),
+ this, SLOT(resumeDirectScreenAccess())
+ );
+ Q_ASSERT(connected);
+
+ // Suppress warnings in release builds
+ Q_UNUSED(connected);
+
+ AbstractVideoPlayer::initVideoOutput();
+}
+
+void MMF::DsaVideoPlayer::prepareCompleted()
+{
+ if (m_videoOutput)
+ videoWindowScreenRectChanged();
+}
+
+void MMF::DsaVideoPlayer::handleVideoWindowChanged()
+{
+ if (!m_window) {
+ if (QWidget *window = QApplication::activeWindow())
+ m_window = window->effectiveWinId()->DrawableWindow();
+ else
+ m_window = 0;
+ m_videoScreenRect = TRect();
+ }
+
+ parametersChanged(WindowHandle | WindowScreenRect);
+}
+
+#ifndef QT_NO_DEBUG
+
+// The following code is for debugging problems related to video visibility. It allows
+// the VideoPlayer instance to query the window server in order to determine the
+// DSA drawing region for the video window.
+
+class CDummyAO : public CActive
+{
+public:
+ CDummyAO() : CActive(CActive::EPriorityStandard) { CActiveScheduler::Add(this); }
+ void RunL() { }
+ void DoCancel() { }
+ TRequestStatus& Status() { return iStatus; }
+ void SetActive() { CActive::SetActive(); }
+};
+
+void getDsaRegion(RWsSession &session, const RWindowBase &window)
+{
+ // Dump complete window tree
+ session.LogCommand(RWsSession::ELoggingStatusDump);
+
+ RDirectScreenAccess dsa(session);
+ TInt err = dsa.Construct();
+ CDummyAO ao;
+ RRegion* region;
+ err = dsa.Request(region, ao.Status(), window);
+ ao.SetActive();
+ dsa.Close();
+ ao.Cancel();
+ if (region) {
+ qDebug() << "Phonon::MMF::getDsaRegion count" << region->Count();
+ for (int i=0; i<region->Count(); ++i) {
+ const TRect& rect = region->RectangleList()[i];
+ qDebug() << "Phonon::MMF::getDsaRegion rect"
+ << rect.iTl.iX << rect.iTl.iY << rect.iBr.iX << rect.iBr.iY;
+ }
+ region->Close();
+ }
+}
+
+#endif // QT_NO_DEBUG
+
+void MMF::DsaVideoPlayer::handleParametersChanged(VideoParameters parameters)
+{
+ TRACE_CONTEXT(DsaVideoPlayer::handleParametersChanged, EVideoInternal);
+ TRACE_ENTRY("parameters 0x%x", parameters.operator int());
+
+ if (!m_window)
+ return;
+
+#ifndef QT_NO_DEBUG
+ getDsaRegion(m_wsSession, *m_window);
+#endif
+
+ if (m_player) {
+ static const TBool antialias = ETrue;
+ int err = KErrNone;
+
+ if (parameters & ScaleFactors) {
+ TRAP(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight,
+ antialias));
+ if(KErrNone != err) {
+ TRACE("SetScaleFactorL (1) err %d", err);
+ setError(tr("Video display error"), err);
+ }
+ }
+
+ if (KErrNone == err) {
+ if (parameters & WindowHandle || parameters & WindowScreenRect) {
+ TRAP(err,
+ m_player->SetDisplayWindowL(m_wsSession, m_screenDevice,
+ *m_window,
+ m_videoScreenRect,
+ m_videoScreenRect));
+ }
+
+ if (KErrNone != err) {
+ TRACE("SetDisplayWindowL err %d", err);
+ setError(tr("Video display error"), err);
+ } else {
+ m_dsaActive = true;
+ if (parameters & ScaleFactors) {
+ TRAP(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight,
+ antialias));
+ if (KErrNone != err) {
+ TRACE("SetScaleFactorL (2) err %d", err);
+ setError(tr("Video display error"), err);
+ }
+ }
+ }
+ }
+ }
+
+ TRACE_EXIT_0();
+}
+
+void MMF::DsaVideoPlayer::startDirectScreenAccess()
+{
+ TRACE_CONTEXT(DsaVideoPlayer::startDirectScreenAccess, EVideoInternal);
+ TRACE_ENTRY("dsaActive %d", m_dsaActive);
+
+ int err = KErrNone;
+
+ if (!m_dsaActive) {
+ TRAP(err, m_player->StartDirectScreenAccessL());
+ if (KErrNone == err)
+ m_dsaActive = true;
+ else
+ setError(tr("Video display error"), err);
+ }
+
+ if (m_videoOutput)
+ m_videoOutput->dump();
+
+ TRACE_EXIT("error %d", err);
+}
+
+bool MMF::DsaVideoPlayer::stopDirectScreenAccess()
+{
+ TRACE_CONTEXT(DsaVideoPlayer::stopDirectScreenAccess, EVideoInternal);
+ TRACE_ENTRY("dsaActive %d", m_dsaActive);
+
+ int err = KErrNone;
+
+ const bool dsaWasActive = m_dsaActive;
+ if (m_dsaActive) {
+ TRAP(err, m_player->StopDirectScreenAccessL());
+ if (KErrNone == err)
+ m_dsaActive = false;
+ else
+ setError(tr("Video display error"), err);
+ }
+
+ TRACE_EXIT("error %d", err);
+
+ return dsaWasActive;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/videoplayer_dsa.h b/src/3rdparty/phonon/mmf/videoplayer_dsa.h
new file mode 100644
index 0000000..45cc47d
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videoplayer_dsa.h
@@ -0,0 +1,92 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_VIDEOPLAYER_DSA_H
+#define PHONON_MMF_VIDEOPLAYER_DSA_H
+
+#include "abstractvideoplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short Wrapper over the MMF video player utility (DSA version)
+ *
+ * This implementation is used on devices with the legacy graphics
+ * subsystem, which does not support surfaces. On such devices,
+ * video rendering is done via Direct Screen Access (DSA), whereby
+ * the video decoder writes directly to the framebuffer. To ensure
+ * that the window server and video decoder do not try to draw to
+ * the same screen region at the same time, the video subsystem
+ * first requests permission to perform DSA. If the window server
+ * needs to draw to this screen region (for example to display a
+ * message dialog), it first notifies the video subsystem that it
+ * must stop rendering to this region.
+ *
+ * @see SurfaceVideoPlayer
+ */
+class DsaVideoPlayer
+ : public AbstractVideoPlayer
+{
+ Q_OBJECT
+
+public:
+ // Factory function
+ static DsaVideoPlayer* create(MediaObject *parent = 0,
+ const AbstractPlayer *player = 0);
+ ~DsaVideoPlayer();
+
+public Q_SLOTS:
+ void videoWindowScreenRectChanged();
+ void suspendDirectScreenAccess();
+ void resumeDirectScreenAccess();
+
+private:
+ DsaVideoPlayer(MediaObject *parent, const AbstractPlayer *player);
+
+ // AbstractVideoPlayer
+ void createPlayer();
+ void initVideoOutput();
+ void prepareCompleted();
+ void handleVideoWindowChanged();
+ void handleParametersChanged(VideoParameters parameters);
+
+ void startDirectScreenAccess();
+ bool stopDirectScreenAccess();
+
+private:
+ bool m_dsaActive;
+ bool m_dsaWasActive;
+
+ // Absolute screen rectangle on which video is displayed
+ TRect m_videoScreenRect;
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif // !PHONON_MMF_VIDEOPLAYER_DSA_H
+
+
diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp
new file mode 100644
index 0000000..f380e69
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp
@@ -0,0 +1,185 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <videoplayer2.h>
+
+#include <QtCore/private/qcore_symbian_p.h> // for qt_QRect2TRect
+
+#include "utils.h"
+#include "videooutput_surface.h"
+#include "videoplayer_surface.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+// Two-phase constructor idiom is used because construct() calls virtual
+// functions and therefore cannot be called from the AbstractVideoPlayer
+// C++ constructor.
+SurfaceVideoPlayer* SurfaceVideoPlayer::create(MediaObject *parent,
+ const AbstractPlayer *player)
+{
+ QScopedPointer<SurfaceVideoPlayer> self(new SurfaceVideoPlayer(parent, player));
+ self->construct();
+ return self.take();
+}
+
+SurfaceVideoPlayer::SurfaceVideoPlayer(MediaObject *parent, const AbstractPlayer *player)
+ : AbstractVideoPlayer(parent, player)
+ , m_displayWindow(0)
+{
+
+}
+
+SurfaceVideoPlayer::~SurfaceVideoPlayer()
+{
+
+}
+
+
+//-----------------------------------------------------------------------------
+// Public functions
+//-----------------------------------------------------------------------------
+
+void MMF::SurfaceVideoPlayer::videoWindowSizeChanged()
+{
+ if (m_videoOutput)
+ updateScaleFactors(m_videoOutput->videoWindowSize());
+}
+
+
+//-----------------------------------------------------------------------------
+// Private functions
+//-----------------------------------------------------------------------------
+
+void MMF::SurfaceVideoPlayer::createPlayer()
+{
+ const TInt priority = 0;
+ const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone;
+
+ CVideoPlayerUtility2 *player = 0;
+ QT_TRAP_THROWING(player = CVideoPlayerUtility2::NewL(*this,
+ priority, preference));
+ m_player.reset(player);
+}
+
+void MMF::SurfaceVideoPlayer::initVideoOutput()
+{
+ Q_ASSERT(m_videoOutput);
+
+ bool connected = connect(
+ m_videoOutput, SIGNAL(videoWindowSizeChanged()),
+ this, SLOT(videoWindowSizeChanged())
+ );
+ Q_ASSERT(connected);
+
+ // Suppress warnings in release builds
+ Q_UNUSED(connected);
+
+ AbstractVideoPlayer::initVideoOutput();
+}
+
+void MMF::SurfaceVideoPlayer::prepareCompleted()
+{
+ videoWindowSizeChanged();
+}
+
+void MMF::SurfaceVideoPlayer::handleVideoWindowChanged()
+{
+ parametersChanged(WindowHandle);
+}
+
+void MMF::SurfaceVideoPlayer::handleParametersChanged(VideoParameters parameters)
+{
+ TRACE_CONTEXT(SurfaceVideoPlayer::handleParametersChanged, EVideoApi);
+ TRACE_ENTRY("parameters 0x%x", parameters.operator int());
+
+ TRect rect;
+ if (m_videoOutput) {
+ m_videoOutput->dump();
+ const QSize size = m_videoOutput->videoWindowSize();
+ rect.SetSize(TSize(size.width(), size.height()));
+ }
+
+ CVideoPlayerUtility2 *player = static_cast<CVideoPlayerUtility2 *>(m_player.data());
+ if (player) {
+ int err = KErrNone;
+ if (parameters & WindowHandle) {
+ removeDisplayWindow();
+ addDisplayWindow(rect);
+ }
+
+ if (KErrNone == err) {
+ if (parameters & ScaleFactors) {
+ if (!m_displayWindow)
+ addDisplayWindow(rect);
+ Q_ASSERT(m_displayWindow);
+ TRAP(err, player->SetVideoExtentL(*m_displayWindow, rect));
+ if (KErrNone == err)
+ TRAP(err, player->SetWindowClipRectL(*m_displayWindow, rect));
+ if (KErrNone == err)
+ TRAP(err, player->SetScaleFactorL(*m_displayWindow, m_scaleWidth, m_scaleHeight));
+ if (KErrNone != err)
+ setError(tr("Video display error"), err);
+ }
+ }
+ }
+
+ TRACE_EXIT_0();
+}
+
+void MMF::SurfaceVideoPlayer::addDisplayWindow(const TRect &rect)
+{
+ TRACE_CONTEXT(SurfaceVideoPlayer::addDisplayWindow, EVideoApi);
+ TRACE_ENTRY("rect %d %d - %d %d", rect.iTl.iX, rect.iTl.iY, rect.iBr.iX, rect.iBr.iY);
+
+ Q_ASSERT(!m_displayWindow);
+ RWindow *window = static_cast<RWindow *>(m_window);
+
+ TRACE("window 0x%08x", window);
+
+ if (window) {
+ window->SetBackgroundColor(TRgb(0, 0, 0, 255));
+ CVideoPlayerUtility2 *player = static_cast<CVideoPlayerUtility2 *>(m_player.data());
+ Q_ASSERT(player);
+ TRAPD(err, player->AddDisplayWindowL(m_wsSession, m_screenDevice, *window, rect, rect));
+ if (KErrNone == err)
+ m_displayWindow = window;
+ else
+ setError(tr("Video display error"), err);
+ TRACE("err %d", err);
+ }
+
+ TRACE_EXIT_0();
+}
+
+void MMF::SurfaceVideoPlayer::removeDisplayWindow()
+{
+ TRACE_CONTEXT(SurfaceVideoPlayer::removeDisplayWindow, EVideoApi);
+ TRACE("player 0x%08x window 0x%08x", m_player.data(), m_displayWindow);
+
+ CVideoPlayerUtility2 *player = static_cast<CVideoPlayerUtility2 *>(m_player.data());
+ if (player && m_displayWindow) {
+ player->RemoveDisplayWindow(*m_displayWindow);
+ m_displayWindow = 0;
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.h b/src/3rdparty/phonon/mmf/videoplayer_surface.h
new file mode 100644
index 0000000..8572fdc
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videoplayer_surface.h
@@ -0,0 +1,81 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_VIDEOPLAYER_SURFACE_H
+#define PHONON_MMF_VIDEOPLAYER_SURFACE_H
+
+#include "abstractvideoplayer.h"
+
+class RWindow;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+
+/**
+ * @short Wrapper over the MMF video player utility (surface version)
+ *
+ * This implementation is used on devices with a graphics subsystem which
+ * supports surfaces.
+ *
+ * @see DsaVideoPlayer
+ */
+class SurfaceVideoPlayer
+ : public AbstractVideoPlayer
+{
+ Q_OBJECT
+
+public:
+ // Factory function
+ static SurfaceVideoPlayer* create(MediaObject *parent = 0,
+ const AbstractPlayer *player = 0);
+ ~SurfaceVideoPlayer();
+
+public Q_SLOTS:
+ void videoWindowSizeChanged();
+
+private:
+ SurfaceVideoPlayer(MediaObject *parent, const AbstractPlayer *player);
+
+ // AbstractVideoPlayer
+ void createPlayer();
+ void initVideoOutput();
+ void prepareCompleted();
+ void handleVideoWindowChanged();
+ void handleParametersChanged(VideoParameters parameters);
+
+ void addDisplayWindow(const TRect &rect);
+ void removeDisplayWindow();
+
+private:
+ // Window handle which has been passed to the MMF via
+ // CVideoPlayerUtility2::SetDisplayWindowL
+ RWindow* m_displayWindow;
+
+};
+
+}
+}
+
+QT_END_NAMESPACE
+
+#endif // !PHONON_MMF_VIDEOPLAYER_SURFACE_H
+
diff --git a/src/3rdparty/phonon/mmf/videowidget.cpp b/src/3rdparty/phonon/mmf/videowidget.cpp
new file mode 100644
index 0000000..d59e82a
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videowidget.cpp
@@ -0,0 +1,192 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "mediaobject.h"
+#include "utils.h"
+
+#include "videowidget.h"
+
+#ifdef PHONON_MMF_VIDEO_SURFACES
+#include "videooutput_surface.h"
+#else
+#include "videooutput_dsa.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace Phonon;
+using namespace Phonon::MMF;
+
+/*! \class MMF::VideoWidget
+ \internal
+*/
+
+//-----------------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------------
+
+static const qreal DefaultBrightness = 1.0;
+static const qreal DefaultContrast = 1.0;
+static const qreal DefaultHue = 1.0;
+static const qreal DefaultSaturation = 1.0;
+
+
+//-----------------------------------------------------------------------------
+// Constructor / destructor
+//-----------------------------------------------------------------------------
+
+MMF::VideoWidget::VideoWidget(QWidget *parent)
+ : MediaNode(parent)
+#ifdef PHONON_MMF_VIDEO_SURFACES
+ , m_videoOutput(new SurfaceVideoOutput(parent))
+#else
+ , m_videoOutput(new DsaVideoOutput(parent))
+#endif
+ , m_brightness(DefaultBrightness)
+ , m_contrast(DefaultContrast)
+ , m_hue(DefaultHue)
+ , m_saturation(DefaultSaturation)
+{
+ TRACE_CONTEXT(VideoWidget::VideoWidget, EVideoApi);
+ TRACE_ENTRY_0();
+
+ parent->setProperty("_q_DummyWindowSurface", true);
+
+ TRACE_EXIT_0();
+}
+
+MMF::VideoWidget::~VideoWidget()
+{
+ TRACE_CONTEXT(VideoWidget::~VideoWidget, EVideoApi);
+ TRACE_ENTRY_0();
+
+ TRACE_EXIT_0();
+}
+
+#ifndef PHONON_MMF_VIDEO_SURFACES
+void MMF::VideoWidget::setAncestorMoveMonitor(AncestorMoveMonitor *monitor)
+{
+ static_cast<DsaVideoOutput *>(m_videoOutput.data())->setAncestorMoveMonitor(monitor);
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// VideoWidgetInterface
+//-----------------------------------------------------------------------------
+
+Phonon::VideoWidget::AspectRatio MMF::VideoWidget::aspectRatio() const
+{
+ return m_videoOutput->aspectRatio();
+}
+
+void MMF::VideoWidget::setAspectRatio
+(Phonon::VideoWidget::AspectRatio aspectRatio)
+{
+ TRACE_CONTEXT(VideoWidget::setAspectRatio, EVideoApi);
+ TRACE("aspectRatio %d", aspectRatio);
+
+ m_videoOutput->setAspectRatio(aspectRatio);
+}
+
+qreal MMF::VideoWidget::brightness() const
+{
+ return m_brightness;
+}
+
+void MMF::VideoWidget::setBrightness(qreal brightness)
+{
+ TRACE_CONTEXT(VideoWidget::setBrightness, EVideoApi);
+ TRACE("brightness %f", brightness);
+
+ m_brightness = brightness;
+}
+
+Phonon::VideoWidget::ScaleMode MMF::VideoWidget::scaleMode() const
+{
+ return m_videoOutput->scaleMode();
+}
+
+void MMF::VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+{
+ TRACE_CONTEXT(VideoWidget::setScaleMode, EVideoApi);
+ TRACE("setScaleMode %d", scaleMode);
+
+ m_videoOutput->setScaleMode(scaleMode);
+}
+
+qreal MMF::VideoWidget::contrast() const
+{
+ return m_contrast;
+}
+
+void MMF::VideoWidget::setContrast(qreal contrast)
+{
+ TRACE_CONTEXT(VideoWidget::setContrast, EVideoApi);
+ TRACE("contrast %f", contrast);
+
+ m_contrast = contrast;
+}
+
+qreal MMF::VideoWidget::hue() const
+{
+ return m_hue;
+}
+
+void MMF::VideoWidget::setHue(qreal hue)
+{
+ TRACE_CONTEXT(VideoWidget::setHue, EVideoApi);
+ TRACE("hue %f", hue);
+
+ m_hue = hue;
+}
+
+qreal MMF::VideoWidget::saturation() const
+{
+ return m_saturation;
+}
+
+void MMF::VideoWidget::setSaturation(qreal saturation)
+{
+ TRACE_CONTEXT(VideoWidget::setSaturation, EVideoApi);
+ TRACE("saturation %f", saturation);
+
+ m_saturation = saturation;
+}
+
+QWidget* MMF::VideoWidget::widget()
+{
+ return m_videoOutput.data();
+}
+
+//-----------------------------------------------------------------------------
+// MediaNode
+//-----------------------------------------------------------------------------
+
+void MMF::VideoWidget::connectMediaObject(MediaObject *mediaObject)
+{
+ mediaObject->setVideoOutput(m_videoOutput.data());
+}
+
+void MMF::VideoWidget::disconnectMediaObject(MediaObject *mediaObject)
+{
+ mediaObject->setVideoOutput(0);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/mmf/videowidget.h b/src/3rdparty/phonon/mmf/videowidget.h
new file mode 100644
index 0000000..3b6283e
--- /dev/null
+++ b/src/3rdparty/phonon/mmf/videowidget.h
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MMF_VIDEOWIDGET_H
+#define PHONON_MMF_VIDEOWIDGET_H
+
+#include "abstractvideooutput.h"
+#include "mmf_medianode.h"
+
+#include <QtGui/QWidget>
+#include <phonon/videowidget.h>
+#include <phonon/videowidgetinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace MMF
+{
+#ifndef PHONON_MMF_VIDEO_SURFACES
+class AncestorMoveMonitor;
+#endif
+
+class VideoWidget : public MediaNode
+ , public Phonon::VideoWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VideoWidgetInterface)
+
+public:
+ VideoWidget(QWidget* parent);
+ ~VideoWidget();
+
+#ifndef PHONON_MMF_VIDEO_SURFACES
+ void setAncestorMoveMonitor(AncestorMoveMonitor *ancestorMoveMonitor);
+#endif
+
+ // VideoWidgetInterface
+ virtual Phonon::VideoWidget::AspectRatio aspectRatio() const;
+ virtual void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio);
+ virtual qreal brightness() const;
+ virtual void setBrightness(qreal brightness);
+ virtual Phonon::VideoWidget::ScaleMode scaleMode() const;
+ virtual void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode);
+ virtual qreal contrast() const;
+ virtual void setContrast(qreal constrast);
+ virtual qreal hue() const;
+ virtual void setHue(qreal hue);
+ virtual qreal saturation() const;
+ virtual void setSaturation(qreal saturation);
+ virtual QWidget *widget();
+
+protected:
+ // MediaNode
+ void connectMediaObject(MediaObject *mediaObject);
+ void disconnectMediaObject(MediaObject *mediaObject);
+
+private:
+ QScopedPointer<AbstractVideoOutput> m_videoOutput;
+
+ qreal m_brightness;
+ qreal m_contrast;
+ qreal m_hue;
+ qreal m_saturation;
+
+};
+}
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/3rdparty/phonon/phonon.pc.cmake b/src/3rdparty/phonon/phonon.pc.cmake
new file mode 100644
index 0000000..10c3712
--- /dev/null
+++ b/src/3rdparty/phonon/phonon.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@EXEC_INSTALL_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: Phonon
+Description: Phonon library needed to build applications
+Version: @PHONON_LIB_MAJOR_VERSION@.@PHONON_LIB_MINOR_VERSION@.@PHONON_LIB_PATCH_VERSION@
+Requires: QtCore QtGui QtDBus
+Libs: -L${libdir} -lphonon
+Cflags: -I${includedir}
diff --git a/src/3rdparty/phonon/phonon/.krazy b/src/3rdparty/phonon/phonon/.krazy
new file mode 100644
index 0000000..f0ab4d5
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/.krazy
@@ -0,0 +1,2 @@
+EXCLUDE qclasses
+SKIP /DESIGN/
diff --git a/src/3rdparty/phonon/phonon/BUGS b/src/3rdparty/phonon/phonon/BUGS
new file mode 100644
index 0000000..fb74e44
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/BUGS
@@ -0,0 +1,9 @@
+When the backend changes there's a drop in the playback. When it's in
+PlayingState it could time how long it takes until the playback resumes and add
+that time to the seek.
+
+When the backend changes the paths are not restored correctly and it crashes
+
+When a new AudioOutput is created with the same name and category it'll still cause
+a notification if a device fallback was necessary. One such notification per
+name/category or even ignoring the name sure is enough.
diff --git a/src/3rdparty/phonon/phonon/CMakeLists.txt b/src/3rdparty/phonon/phonon/CMakeLists.txt
new file mode 100644
index 0000000..ace934a
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/CMakeLists.txt
@@ -0,0 +1,139 @@
+if (PHONON_BUILD_TESTS)
+ add_subdirectory(tests)
+endif (PHONON_BUILD_TESTS)
+
+if (PHONON_BUILD_EXAMPLES)
+ add_subdirectory(examples)
+endif (PHONON_BUILD_EXAMPLES)
+
+add_subdirectory(experimental)
+
+set(PULSEAUDIO_MINIMUM_VERSION "0.9.15")
+macro_optional_find_package(PulseAudio)
+if (PULSEAUDIO_FOUND)
+ # PULSEAUDIO_DEVICE_MANAGER feature check could be moved to FindPulseAudio.cmake, hint hint. -- Rex
+ macro_ensure_version("0.9.21" "${PULSEAUDIO_VERSION}" PULSEAUDIO_DEVICE_MANAGER)
+endif (PULSEAUDIO_FOUND)
+macro_log_feature(PULSEAUDIO_FOUND "PulseAudio" "A cross-platform, networked sound server." "http://www.pulseaudio.org" FALSE "" "Allows audio playback via the PulseAudio soundserver when it is running")
+macro_optional_find_package(GLIB2)
+macro_log_feature(GLIB2_FOUND "GLib2" "GLib 2 is required to compile the pulseaudio for Phonon" "http://www.gtk.org/download/" FALSE)
+
+
+if (GLIB2_FOUND AND PULSEAUDIO_FOUND)
+ add_definitions(-DHAVE_PULSEAUDIO)
+ include_directories(${GLIB2_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIR})
+ if (PULSEAUDIO_DEVICE_MANAGER)
+ add_definitions(-DHAVE_PULSEAUDIO_DEVICE_MANAGER)
+ endif(PULSEAUDIO_DEVICE_MANAGER)
+else(GLIB2_FOUND AND PULSEAUDIO_FOUND)
+ set(PULSEAUDIO_INCLUDE_DIR "")
+ set(PULSEAUDIO_LIBRARY "")
+ set(PULSEAUDIO_MAINLOOP_LIBRARY "")
+endif(GLIB2_FOUND AND PULSEAUDIO_FOUND)
+
+
+set(phonon_LIB_SRCS
+ objectdescription.cpp
+ objectdescriptionmodel.cpp
+ phononnamespace.cpp
+ mediasource.cpp
+ abstractmediastream.cpp
+ streaminterface.cpp
+ mediaobject.cpp
+ medianode.cpp
+ path.cpp
+ effectparameter.cpp
+ effect.cpp
+ volumefadereffect.cpp
+ abstractaudiooutput.cpp
+ abstractaudiooutput_p.cpp
+ audiooutput.cpp
+ audiooutputinterface.cpp
+ abstractvideooutput.cpp
+ abstractvideooutput_p.cpp
+ backendcapabilities.cpp
+ globalconfig.cpp
+ factory.cpp
+ platform.cpp
+ mediacontroller.cpp
+ videowidget.cpp
+ videoplayer.cpp
+ seekslider.cpp
+ swiftslider.cpp
+ volumeslider.cpp
+ effectwidget.cpp
+ iodevicestream.cpp
+ audiodataoutput.cpp
+ pulsesupport.cpp
+ )
+
+if (QT_QTDBUS_FOUND)
+ list(APPEND phonon_LIB_SRCS
+ audiooutputadaptor.cpp
+ )
+endif (QT_QTDBUS_FOUND)
+
+
+add_definitions(-DPHONON_LIBRARY_PATH="${PLUGIN_INSTALL_DIR}/plugins")
+automoc4_add_library(phonon SHARED ${phonon_LIB_SRCS})
+target_link_libraries(phonon ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
+if (GLIB2_FOUND AND PULSEAUDIO_FOUND)
+target_link_libraries(phonon ${GLIB2_LIBRARIES} ${GOBJECT_LIBRARIES} ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY})
+endif (GLIB2_FOUND AND PULSEAUDIO_FOUND)
+
+if (QT_QTDBUS_FOUND)
+ target_link_libraries(phonon ${QT_QTDBUS_LIBRARY})
+endif (QT_QTDBUS_FOUND)
+if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
+ # We need to explicitly link libm to phonon in Solaris
+ target_link_libraries(phonon m)
+endif (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
+
+set_target_properties(phonon PROPERTIES
+ VERSION ${PHONON_LIB_VERSION}
+ SOVERSION ${PHONON_LIB_SOVERSION}
+ DEFINE_SYMBOL MAKE_PHONON_LIB
+ )
+install(TARGETS phonon ${INSTALL_TARGETS_DEFAULT_ARGS})
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/phononnamespace.h.in ${CMAKE_CURRENT_BINARY_DIR}/phononnamespace.h)
+
+install(FILES
+ phonon_export.h
+ objectdescription.h
+ objectdescriptionmodel.h
+ ${CMAKE_CURRENT_BINARY_DIR}/phononnamespace.h
+ mediasource.h
+ abstractmediastream.h
+ streaminterface.h
+ mediaobject.h
+ audiooutput.h
+ medianode.h
+ path.h
+ effectparameter.h
+ effect.h
+ effectinterface.h
+ volumefadereffect.h
+ volumefaderinterface.h
+ abstractaudiooutput.h
+ abstractvideooutput.h
+ backendcapabilities.h
+ phonondefs.h
+ backendinterface.h
+ mediaobjectinterface.h
+ audiooutputinterface.h
+ addoninterface.h
+ mediacontroller.h
+ videowidget.h
+ videowidgetinterface.h
+ videoplayer.h
+ seekslider.h
+ volumeslider.h
+ effectwidget.h
+ platformplugin.h
+ audiodataoutput.h
+ audiodataoutputinterface.h
+ globalconfig.h
+ pulsesupport.h
+ DESTINATION ${INCLUDE_INSTALL_DIR}/phonon COMPONENT Devel)
+
+install(FILES org.kde.Phonon.AudioOutput.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR})
diff --git a/src/3rdparty/phonon/phonon/IDEAS b/src/3rdparty/phonon/phonon/IDEAS
new file mode 100644
index 0000000..96fe056
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/IDEAS
@@ -0,0 +1,70 @@
+MediaInfo class
+===============
+
+It might be nice to have a class that gives information about MediaSource
+objects without having to use MediaObject for it. Something like QFileInfo for
+QFile. MediaObject could also return a list of MediaInfo objects for all the
+MediaSource objects in the queue.
+
+Rationale: The app then can get info about length and substreams so that it can
+set up everything correctly for the next "file" in the queue.
+
+
+- on hotplug of a USB audio/video device:
+ 1. If the device is plugged in for the first time
+ Check whether the backend now provides new device selections. If yes, open
+ up central config with the page that allows selection of the default
+ devices. Tell the user what new options are available.
+ Allow the user to set preference of devices: If device USB-Headset is
+ available use that, else use builtin speakers.
+
+ device info persistance
+=========================
+On device selections: should the user be presented with options that are
+currently not available? It might actually be confusing to select a device that
+is not usable at the moment.
+
+Some situations:
+(device A is always available)
+- user plugs device B
+- selects device B as default
+next day: device B unplugged
+- phonon falls back to device A as B is not available and shows a passive popup
+ informing the user about the fallback
+- user opens config dialog
+- device B still shows up as default
+- selects device A, closes dialog
+- opens dialog again
+- device B is gone...
+- user plugs device B
+- device B reappears
+
+The Backend has to provide the information about devices. Those can map directly
+to hardware or a soundserver or some other virtual device. The Backend has to
+have some unique identifier. For example the ALSA devices could be identified
+using the ALSA device names (either hw:0, hw:1 or aliases from asoundrc). OSS
+devices could be identified using /dev/dsp, /dev/dsp1 and so on.
+=> the backend internal uid is a string
+In the Frontend all that is needed is a name and a description of the device
+(both translated to the current locale) and a unique identifier to talk to the
+backend. This identifier could be the same as used internally by the Backend,
+but doesn't have to be.
+
+ "lowlevel" audio I/O
+======================
+ByteStream is a buffered stream, and as therefore completely useless for cases
+where an application wants to write audio data to the soundcard/-system with low
+latency.
+=> PcmInStream and PcmOutStream
+
+
+============================================================================
+= Ideas for "useless but nice" things (until somebody can convince me that =
+= they're useful) =
+============================================================================
+
+ Video Output
+==============
+Add another VideoOutput that can be used directly with QGraphicsView by creating
+a QGraphicsItem subclass.
+
diff --git a/src/3rdparty/phonon/phonon/Messages.sh b/src/3rdparty/phonon/phonon/Messages.sh
new file mode 100644
index 0000000..c628a04
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/Messages.sh
@@ -0,0 +1,6 @@
+#! /usr/bin/env bash
+find ./ -maxdepth 1 -name "*.cpp" -print > files
+find ./ -maxdepth 1 -name "*.h" -print >> files
+#$EXTRACTRC `find $dirs -maxdepth 1 \( -name \*.rc -o -name \*.ui -o -name \*.ui3 -o -name \*.ui4 -o -name \*.kcfg \) ` >> rc.cpp || exit 11
+$XGETTEXT_QT --copyright-holder=This_file_is_part_of_KDE --msgid-bugs-address=http://bugs.kde.org --files-from=files -o $podir/libphonon.pot
+rm files
diff --git a/src/3rdparty/phonon/phonon/TODO b/src/3rdparty/phonon/phonon/TODO
new file mode 100644
index 0000000..479bbd7
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/TODO
@@ -0,0 +1,31 @@
+- add a metadata function that returns a QVariant instead of a QString - useful for QImage or other binary (QByteArray) content
+
+- QImage VideoWidget::screenshot(): ordinary screenshot doesn't work with XV says Christoph. And VideoDataOutput
+ would be major overkill.
+
+- consider whether to add a signal to notify when the information for
+ availableAudioStreams/availableVideoStreams/availableSubtitleStreams
+ is available
+
+- look at collaboration with other projects, e.g. pavucontrol, gsmartmix
+
+- consider Player dbus interface in MediaObject
+
+- add global setting to pause video when it's not visible
+
+- add a way to request a specific version (>=) from the Backend, so that known to be buggy Backends aren't used
+
+- Video Overlays (OSD) like: show a rectangle as a play symbol, show the position in
+ the file as something like [IIIIIIIII------], and so on
+
+- http://bugs.kde.org/show_bug.cgi?id=147494
+
+- frame/sample precise positioning (cue in/out)
+
+- different timecode support like SMPTE
+
+- Codec interface - at least for audio
+
+- Speed factor for playback (useful mostly for audio - but video still needs to stay in sync)
+
+- tell the platform plugin which backend was loaded (if it doesn't do it itself) so that it can load KDE translations for the backend
diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp b/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp
new file mode 100644
index 0000000..bce7c11
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp
@@ -0,0 +1,50 @@
+/* This file is part of the KDE project
+Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "abstractaudiooutput.h"
+#include "abstractaudiooutput_p.h"
+#include "factory_p.h"
+
+#define PHONON_CLASSNAME AbstractAudioOutput
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+ AbstractAudioOutput::AbstractAudioOutput(AbstractAudioOutputPrivate &dd, QObject *parent) : QObject(parent),
+ MediaNode(dd)
+ {
+ }
+
+ AbstractAudioOutput::~AbstractAudioOutput()
+ {
+ }
+
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+#undef PHONON_CLASSNAME
+
+#include "moc_abstractaudiooutput.cpp"
+
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput.h b/src/3rdparty/phonon/phonon/abstractaudiooutput.h
new file mode 100644
index 0000000..1045f18
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractaudiooutput.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef Phonon_ABSTRACTAUDIOOUTPUTBASE_H
+#define Phonon_ABSTRACTAUDIOOUTPUTBASE_H
+
+#include "phonondefs.h"
+#include "phonon_export.h"
+#include "medianode.h"
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class AbstractAudioOutputPrivate;
+
+ /** \class AbstractAudioOutput abstractaudiooutput.h Phonon/AbstractAudioOutput
+ * Common base class for all audio outputs.
+ *
+ * \see AudioOutput
+ */
+ class PHONON_EXPORT AbstractAudioOutput : public QObject, public MediaNode
+ {
+ Q_OBJECT
+ K_DECLARE_PRIVATE(AbstractAudioOutput)
+ protected:
+ AbstractAudioOutput(AbstractAudioOutputPrivate &dd, QObject *parent);
+ public:
+ ~AbstractAudioOutput();
+ };
+} //namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_ABSTRACTAUDIOOUTPUTBASE_H
diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp
new file mode 100644
index 0000000..20e0b3c
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp
@@ -0,0 +1,44 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "abstractaudiooutput_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+bool AbstractAudioOutputPrivate::aboutToDeleteBackendObject()
+{
+ return true;
+}
+
+void AbstractAudioOutputPrivate::setupBackendObject()
+{
+ Q_ASSERT(m_backendObject);
+
+ // set up attributes
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h
new file mode 100644
index 0000000..9b3a57f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h
@@ -0,0 +1,50 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_ABSTRACTAUDIOOUTPUT_P_H
+#define PHONON_ABSTRACTAUDIOOUTPUT_P_H
+
+#include "abstractaudiooutput.h"
+#include "medianode_p.h"
+#include "phonondefs_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+class AbstractAudioOutputPrivate : public MediaNodePrivate
+{
+ Q_DECLARE_PUBLIC(AbstractAudioOutput)
+ PHONON_PRIVATEABSTRACTCLASS
+ public:
+ virtual QObject *qObject() { return q_func(); }
+ protected:
+ AbstractAudioOutputPrivate(CastId castId = AbstractAudioOutputPrivateType)
+ : MediaNodePrivate(castId)
+ {
+ }
+};
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // PHONON_ABSTRACTAUDIOOUTPUT_P_H
diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.cpp b/src/3rdparty/phonon/phonon/abstractmediastream.cpp
new file mode 100644
index 0000000..f4a7db6
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractmediastream.cpp
@@ -0,0 +1,197 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "abstractmediastream.h"
+#include "abstractmediastream_p.h"
+#include "mediaobjectinterface.h"
+#include "mediaobject_p.h"
+#include "streaminterface_p.h"
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+AbstractMediaStream::AbstractMediaStream(QObject *parent)
+ : QObject(parent),
+ d_ptr(new AbstractMediaStreamPrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+AbstractMediaStream::AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject *parent)
+ : QObject(parent),
+ d_ptr(&dd)
+{
+ d_ptr->q_ptr = this;
+}
+
+AbstractMediaStream::~AbstractMediaStream()
+{
+}
+
+qint64 AbstractMediaStream::streamSize() const
+{
+ return d_ptr->streamSize;
+}
+
+void AbstractMediaStream::setStreamSize(qint64 newSize)
+{
+ d_ptr->setStreamSize(newSize);
+}
+
+void AbstractMediaStreamPrivate::setStreamSize(qint64 newSize)
+{
+ streamSize = newSize;
+ if (streamInterface) {
+ streamInterface->setStreamSize(newSize);
+ }
+}
+
+bool AbstractMediaStream::streamSeekable() const
+{
+ return d_ptr->streamSeekable;
+}
+
+void AbstractMediaStream::setStreamSeekable(bool s)
+{
+ d_ptr->setStreamSeekable(s);
+}
+
+void AbstractMediaStreamPrivate::setStreamSeekable(bool s)
+{
+ streamSeekable = s;
+ if (streamInterface) {
+ streamInterface->setStreamSeekable(s);
+ }
+}
+
+void AbstractMediaStream::writeData(const QByteArray &data)
+{
+ d_ptr->writeData(data);
+}
+
+void AbstractMediaStreamPrivate::writeData(const QByteArray &data)
+{
+ if (ignoreWrites) {
+ return;
+ }
+ Q_ASSERT(streamInterface);
+ streamInterface->writeData(data);
+}
+
+void AbstractMediaStream::endOfData()
+{
+ d_ptr->endOfData();
+}
+
+void AbstractMediaStreamPrivate::endOfData()
+{
+ if (streamInterface) {
+ streamInterface->endOfData();
+ }
+}
+
+void AbstractMediaStream::error(Phonon::ErrorType type, const QString &text)
+{
+ Q_D(AbstractMediaStream);
+ d->errorType = type;
+ d->errorText = text;
+ if (d->mediaObjectPrivate) {
+ // TODO: MediaObject might be in a different thread
+ d->mediaObjectPrivate->streamError(type, text);
+ }
+}
+
+void AbstractMediaStream::enoughData()
+{
+}
+
+void AbstractMediaStream::seekStream(qint64)
+{
+ Q_ASSERT(!d_ptr->streamSeekable);
+}
+
+AbstractMediaStreamPrivate::~AbstractMediaStreamPrivate()
+{
+ if (mediaObjectPrivate) {
+ // TODO: MediaObject might be in a different thread
+ mediaObjectPrivate->removeDestructionHandler(this);
+ }
+ if (streamInterface) {
+ // TODO: StreamInterface might be in a different thread
+ streamInterface->d->disconnectMediaStream();
+ }
+}
+
+void AbstractMediaStreamPrivate::setStreamInterface(StreamInterface *iface)
+{
+ Q_Q(AbstractMediaStream);
+ streamInterface = iface;
+ if (!iface) {
+ // our subclass might be just about to call writeData, so tell it we have enoughData and
+ // ignore the next writeData calls
+ q->enoughData();
+ ignoreWrites = true;
+ return;
+ }
+ if (ignoreWrites) {
+ ignoreWrites = false;
+ // we had a StreamInterface before. The new StreamInterface expects us to start reading from
+ // position 0
+ q->reset();
+ } else {
+ iface->setStreamSize(streamSize);
+ iface->setStreamSeekable(streamSeekable);
+ }
+}
+
+void AbstractMediaStreamPrivate::setMediaObjectPrivate(MediaObjectPrivate *mop)
+{
+ // TODO: MediaObject might be in a different thread
+ mediaObjectPrivate = mop;
+ mediaObjectPrivate->addDestructionHandler(this);
+ if (!errorText.isEmpty()) {
+ mediaObjectPrivate->streamError(errorType, errorText);
+ }
+}
+
+void AbstractMediaStreamPrivate::phononObjectDestroyed(MediaNodePrivate *bp)
+{
+ // TODO: MediaObject might be in a different thread
+ Q_ASSERT(bp == mediaObjectPrivate);
+ Q_UNUSED(bp);
+ mediaObjectPrivate = 0;
+}
+
+} // namespace Phonon
+
+
+QT_END_NAMESPACE
+
+#include "moc_abstractmediastream.cpp"
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.h b/src/3rdparty/phonon/phonon/abstractmediastream.h
new file mode 100644
index 0000000..87fa140
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractmediastream.h
@@ -0,0 +1,227 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_ABSTRACTMEDIASTREAM_H
+#define PHONON_ABSTRACTMEDIASTREAM_H
+
+#include "phonon_export.h"
+#include "phononnamespace.h"
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+class MediaObject;
+class AbstractMediaStreamPrivate;
+
+/** \class AbstractMediaStream abstractmediastream.h Phonon/AbstractMediaStream
+ * \brief Base class for custom media data streams.
+ *
+ * Implement this class to provide a custom data stream to the backend. The class supports both, the
+ * push and the pull model.
+ *
+ * Push:
+ * \code
+ * PushStream::PushStream(QObject *parent)
+ * : AbstractMediaStream(parent), m_timer(new QTimer(this))
+ * {
+ * setStreamSize(getMediaStreamSize());
+ *
+ * connect(m_timer, SIGNAL(timeout()), SLOT(moreData()));
+ * m_timer->setInterval(0);
+ * }
+ *
+ * void PushStream::moreData()
+ * {
+ * const QByteArray data = getMediaData();
+ * if (data.isEmpty()) {
+ * endOfData();
+ * } else {
+ * writeData(data);
+ * }
+ * }
+ *
+ * void PushStream::needData()
+ * {
+ * m_timer->start();
+ * moreData();
+ * }
+ *
+ * void PushStream::enoughData()
+ * {
+ * m_timer->stop();
+ * }
+ * \endcode
+ *
+ * Pull:
+ * \code
+ * PullStream::PullStream(QObject *parent)
+ * : AbstractMediaStream(parent)
+ * {
+ * setStreamSize(getMediaStreamSize());
+ * }
+ *
+ * void PullStream::needData()
+ * {
+ * const QByteArray data = getMediaData();
+ * if (data.isEmpty()) {
+ * endOfData();
+ * } else {
+ * writeData(data);
+ * }
+ * }
+ * \endcode
+ *
+ * \ingroup Playback
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class PHONON_EXPORT AbstractMediaStream : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(AbstractMediaStream)
+ friend class MediaObject;
+ friend class MediaObjectPrivate;
+ friend class StreamInterface;
+ public:
+ virtual ~AbstractMediaStream();
+
+ protected:
+ /**
+ * Constructs an AbstractMediaStream object with a \p parent.
+ */
+ explicit AbstractMediaStream(QObject *parent = 0);
+
+ /**
+ * Returns the stream size that was set with \ref setStreamSize.
+ *
+ * A negative value means that the length of the stream cannot be known.
+ *
+ * Defaults to \c 0.
+ */
+ qint64 streamSize() const;
+
+ /**
+ * Sets the size of the stream in number of bytes.
+ *
+ * A negative value means that the length of the stream cannot be known.
+ *
+ * Defaults to 0.
+ *
+ * This function has to be called. A backend will not call \ref needData() until the
+ * stream size is set.
+ */
+ void setStreamSize(qint64);
+
+ /**
+ * Returns whether your data stream is set as seekable.
+ *
+ * Defaults to \c false.
+ */
+ bool streamSeekable() const;
+
+ /**
+ * Sets whether your data stream is seekable.
+ *
+ * Defaults to \c false.
+ *
+ * If you set this to \c true you have to implement the \ref seekStream function.
+ */
+ void setStreamSeekable(bool);
+
+ /**
+ * Sends the media \p data to the backend for decoding.
+ *
+ * \warning Don't call this function before the first needData() is emitted.
+ */
+ void writeData(const QByteArray &data);
+
+ /**
+ * Tells the backend that the media data stream is at its end.
+ *
+ * \warning Don't call this function before the first needData() is emitted.
+ */
+ void endOfData();
+
+ /**
+ * If an I/O error occurs you should call this function to make MediaObject go into
+ * ErrorState.
+ *
+ * \see MediaObject::errorType()
+ * \see MediaObject::errorString()
+ */
+ void error(Phonon::ErrorType errorType, const QString &errorString);
+
+ /**
+ * Reimplement this function to reset the stream. Subsequent calls to writeData should start
+ * from the first position of the data unless a seek is requested.
+ *
+ * The function is necessary for the case where a non-seekable MediaStream is
+ * played more than once. For a seekable stream the implementation can simply call
+ * \code
+ * seekStream(0);
+ * \endcode.
+ */
+ virtual void reset() = 0;
+
+ /**
+ * Reimplement this function to be notified when the backend needs data.
+ *
+ * When this function is called you should try to call writeData or endOfData before
+ * returning.
+ */
+ virtual void needData() = 0;
+
+ /**
+ * Reimplement this function to be notified when the backend has enough data and your stream
+ * object may take a break. This method is important for pushing data to the backend in
+ * order to not fill the backend buffer unnecessarily.
+ */
+ virtual void enoughData();
+
+ /**
+ * Reimplement this function if your stream is seekable.
+ *
+ * When this function is called the next call to writeData has to be at the requested \p
+ * offset.
+ *
+ * \warning Do not call the parent implementation.
+ */
+ virtual void seekStream(qint64 offset);
+
+ AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject *parent);
+ QScopedPointer<AbstractMediaStreamPrivate> d_ptr;
+};
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_ABSTRACTMEDIASTREAM_H
diff --git a/src/3rdparty/phonon/phonon/abstractmediastream_p.h b/src/3rdparty/phonon/phonon/abstractmediastream_p.h
new file mode 100644
index 0000000..a676716
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractmediastream_p.h
@@ -0,0 +1,83 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef ABSTRACTMEDIASTREAM_P_H
+#define ABSTRACTMEDIASTREAM_P_H
+
+#include "phonon_export.h"
+#include "abstractmediastream.h"
+#include "mediaobject_p.h"
+#include "streaminterface.h"
+
+#include "medianodedestructionhandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+class MediaObjectPrivate;
+
+namespace Phonon
+{
+class PHONON_EXPORT AbstractMediaStreamPrivate : private MediaNodeDestructionHandler
+{
+ friend class MediaObject;
+ Q_DECLARE_PUBLIC(AbstractMediaStream)
+ public:
+ void setStreamInterface(StreamInterface *);
+ void setMediaObjectPrivate(MediaObjectPrivate *);
+ ~AbstractMediaStreamPrivate();
+
+ protected:
+ AbstractMediaStreamPrivate()
+ : streamSize(0),
+ streamSeekable(false),
+ ignoreWrites(false),
+ streamInterface(0),
+ mediaObjectPrivate(0),
+ errorType(NoError)
+ {
+ }
+
+ virtual void setStreamSize(qint64 newSize);
+ virtual void setStreamSeekable(bool s);
+ virtual void writeData(const QByteArray &data);
+ virtual void endOfData();
+ void phononObjectDestroyed(MediaNodePrivate *);
+
+ AbstractMediaStream *q_ptr;
+ qint64 streamSize;
+ bool streamSeekable;
+ bool ignoreWrites;
+ StreamInterface *streamInterface;
+ MediaObjectPrivate *mediaObjectPrivate;
+ Phonon::ErrorType errorType;
+ QString errorText;
+};
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+
+#endif // ABSTRACTMEDIASTREAM_P_H
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput.cpp b/src/3rdparty/phonon/phonon/abstractvideooutput.cpp
new file mode 100644
index 0000000..1695b78
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractvideooutput.cpp
@@ -0,0 +1,41 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "abstractvideooutput.h"
+#include "abstractvideooutput_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+
+AbstractVideoOutput::AbstractVideoOutput(AbstractVideoOutputPrivate &d)
+ : MediaNode(d)
+{
+}
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput.h b/src/3rdparty/phonon/phonon/abstractvideooutput.h
new file mode 100644
index 0000000..824f729
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractvideooutput.h
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef Phonon_ABSTRACTVIDEOOUTPUTBASE_H
+#define Phonon_ABSTRACTVIDEOOUTPUTBASE_H
+
+#include "phonondefs.h"
+#include "phonon_export.h"
+#include "medianode.h"
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+class QString;
+
+namespace Phonon
+{
+
+namespace Experimental
+{
+ class Visualization;
+ class VisualizationPrivate;
+} // namespace Experimental
+
+ class AbstractVideoOutputPrivate;
+
+ /** \class AbstractVideoOutput abstractvideooutput.h Phonon/AbstractVideoOutput
+ * \brief Common base class for all video outputs.
+ *
+ * \see VideoWidget
+ */
+ class PHONON_EXPORT AbstractVideoOutput : public MediaNode
+ {
+ friend class Experimental::Visualization;
+ friend class Experimental::VisualizationPrivate;
+ K_DECLARE_PRIVATE(AbstractVideoOutput)
+ protected:
+ /**
+ * \internal
+ * Constructor that is called from derived classes.
+ *
+ * \param d the private object
+ */
+ AbstractVideoOutput(AbstractVideoOutputPrivate &d);
+ };
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // Phonon_ABSTRACTVIDEOOUTPUTBASE_H
diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp b/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp
new file mode 100644
index 0000000..a9cfa4d
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp
@@ -0,0 +1,41 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "abstractvideooutput_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+
+bool AbstractVideoOutputPrivate::aboutToDeleteBackendObject()
+{
+ return true;
+}
+
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput_p.h b/src/3rdparty/phonon/phonon/abstractvideooutput_p.h
new file mode 100644
index 0000000..90230d4
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/abstractvideooutput_p.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef ABSTRACTVIDEOOUTPUT_P_H
+#define ABSTRACTVIDEOOUTPUT_P_H
+
+#include "abstractvideooutput.h"
+#include "medianode_p.h"
+#include "phonondefs_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+class AbstractVideoOutputPrivate : public MediaNodePrivate
+{
+ Q_DECLARE_PUBLIC(AbstractVideoOutput)
+ PHONON_PRIVATEABSTRACTCLASS
+};
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+
+#endif // ABSTRACTVIDEOOUTPUT_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/addoninterface.h b/src/3rdparty/phonon/phonon/addoninterface.h
new file mode 100644
index 0000000..229129b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/addoninterface.h
@@ -0,0 +1,103 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_ADDONINTERFACE_H
+#define PHONON_ADDONINTERFACE_H
+
+#include "phononnamespace.h"
+
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+
+namespace Phonon
+{
+/** \class AddonInterface addoninterface.h Phonon/AddonInterface
+ * \short Interface for Menu, Chapter, Angle and Title/Track control.
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class AddonInterface
+{
+ public:
+ virtual ~AddonInterface() {}
+
+ enum Interface {
+ NavigationInterface = 1,
+ ChapterInterface = 2,
+ AngleInterface = 3,
+ TitleInterface = 4,
+ SubtitleInterface = 5,
+ AudioChannelInterface = 6
+ };
+
+ enum NavigationCommand {
+ Menu1Button
+ };
+ enum ChapterCommand {
+ availableChapters,
+ chapter,
+ setChapter
+ };
+ enum AngleCommand {
+ availableAngles,
+ angle,
+ setAngle
+ };
+ enum TitleCommand {
+ availableTitles,
+ title,
+ setTitle,
+ autoplayTitles,
+ setAutoplayTitles
+ };
+ enum SubtitleCommand {
+ availableSubtitles,
+ currentSubtitle,
+ setCurrentSubtitle
+ };
+ enum AudioChannelCommand {
+ availableAudioChannels,
+ currentAudioChannel,
+ setCurrentAudioChannel
+ };
+
+ virtual bool hasInterface(Interface iface) const = 0;
+
+ virtual QVariant interfaceCall(Interface iface, int command,
+ const QList<QVariant> &arguments = QList<QVariant>()) = 0;
+};
+
+} // namespace Phonon
+
+Q_DECLARE_INTERFACE(Phonon::AddonInterface, "AddonInterface0.2.phonon.kde.org")
+
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_ADDONINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.cpp b/src/3rdparty/phonon/phonon/audiodataoutput.cpp
new file mode 100644
index 0000000..fa8ec0d
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutput.cpp
@@ -0,0 +1,72 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "audiodataoutput.h"
+#include "audiodataoutput_p.h"
+#include "factory_p.h"
+
+#define PHONON_CLASSNAME AudioDataOutput
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+PHONON_HEIR_IMPL(AbstractAudioOutput)
+
+PHONON_GETTER(int, dataSize, d->dataSize)
+PHONON_GETTER(int, sampleRate, -1)
+PHONON_SETTER(setDataSize, dataSize, int)
+
+bool AudioDataOutputPrivate::aboutToDeleteBackendObject()
+{
+ Q_ASSERT(m_backendObject);
+ pBACKEND_GET(int, dataSize, "dataSize");
+
+ return AbstractAudioOutputPrivate::aboutToDeleteBackendObject();
+}
+
+void AudioDataOutputPrivate::setupBackendObject()
+{
+ Q_Q(AudioDataOutput);
+ Q_ASSERT(m_backendObject);
+ AbstractAudioOutputPrivate::setupBackendObject();
+
+ // set up attributes
+ pBACKEND_CALL1("setDataSize", int, dataSize);
+
+ qRegisterMetaType<QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > >("QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> >");
+
+ QObject::connect(m_backendObject,
+ SIGNAL(dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &)),
+ q, SIGNAL(dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &)));
+ QObject::connect(m_backendObject, SIGNAL(endOfMedia(int)), q, SIGNAL(endOfMedia(int)));
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#undef PHONON_CLASSNAME
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.h b/src/3rdparty/phonon/phonon/audiodataoutput.h
new file mode 100644
index 0000000..7a559b3
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutput.h
@@ -0,0 +1,135 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef Phonon_AUDIODATAOUTPUT_H
+#define Phonon_AUDIODATAOUTPUT_H
+
+#include "phonon_export.h"
+#include "abstractaudiooutput.h"
+#include "phonondefs.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template<typename T> class QVector;
+template<typename Key, typename T> class QMap;
+#endif
+
+namespace Phonon
+{
+ class AudioDataOutputPrivate;
+
+ /**
+ * \short This class gives you the audio data (for visualizations).
+ *
+ * This class implements a special AbstractAudioOutput that gives your
+ * application the audio data. Don't expect realtime performance. But
+ * the latencies should be low enough to use the audio data for
+ * visualizations. You can also use the audio data for further processing
+ * (e.g. encoding and saving to a file).
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class PHONON_EXPORT AudioDataOutput : public AbstractAudioOutput
+ {
+ Q_OBJECT
+ K_DECLARE_PRIVATE(AudioDataOutput)
+ Q_ENUMS(Channel)
+ Q_PROPERTY(int dataSize READ dataSize WRITE setDataSize)
+ PHONON_HEIR(AudioDataOutput)
+ public:
+ /**
+ * Specifies the channel the audio data belongs to.
+ */
+ enum Channel
+ {
+ LeftChannel,
+ RightChannel,
+ CenterChannel,
+ LeftSurroundChannel,
+ RightSurroundChannel,
+ SubwooferChannel
+ };
+
+ /**
+ * Returns the currently used number of samples passed through
+ * the signal.
+ *
+ * \see setDataSize
+ */
+ int dataSize() const;
+
+ /**
+ * Returns the sample rate in Hz. Common sample rates are 44100 Hz
+ * and 48000 Hz. AudioDataOutput will not do any sample rate
+ * conversion for you. If you need to convert the sample rate you
+ * might want to take a look at libsamplerate. For visualizations it
+ * is often enough to do simple interpolation or even drop/duplicate
+ * samples.
+ *
+ * \return The sample rate as reported by the backend. If the
+ * backend is unavailable -1 is returned.
+ */
+ int sampleRate() const;
+
+ public Q_SLOTS:
+ /**
+ * Sets the number of samples to be passed in one signal emission.
+ *
+ * Defaults to 512 samples per emitted signal.
+ *
+ * \param size the number of samples
+ */
+ void setDataSize(int size);
+
+ Q_SIGNALS:
+ /**
+ * Emitted whenever another dataSize number of samples are ready.
+ *
+ * \param data A mapping of Channel to a vector holding the audio data.
+ */
+ void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &data);
+
+
+ /**
+ * This signal is emitted before the last dataReady signal of a
+ * media is emitted.
+ *
+ * If, for example, the playback of a media file has finished and the
+ * last audio data of that file is going to be passed with the next
+ * dataReady signal, and only the 28 first samples of the data
+ * vector are from that media file endOfMedia will be emitted right
+ * before dataReady with \p remainingSamples = 28.
+ *
+ * \param remainingSamples The number of samples in the next
+ * dataReady vector that belong to the media that was playing to
+ * this point.
+ */
+ void endOfMedia(int remainingSamples);
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_AUDIODATAOUTPUT_H
diff --git a/src/3rdparty/phonon/phonon/audiodataoutput_p.h b/src/3rdparty/phonon/phonon/audiodataoutput_p.h
new file mode 100644
index 0000000..5fd4f80
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutput_p.h
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef AUDIODATAOUTPUT_P_H
+#define AUDIODATAOUTPUT_P_H
+
+#include "audiodataoutput.h"
+#include "abstractaudiooutput_p.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+class AudioDataOutputPrivate : public AbstractAudioOutputPrivate
+{
+ Q_DECLARE_PUBLIC(AudioDataOutput)
+ PHONON_PRIVATECLASS
+ protected:
+ AudioDataOutputPrivate()
+ : dataSize(512)
+ {
+ }
+
+ int dataSize;
+};
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // AUDIODATAOUTPUT_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/audiodataoutputinterface.h b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h
new file mode 100644
index 0000000..08bc7fc
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h
@@ -0,0 +1,50 @@
+/* This file is part of the KDE project
+ Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_AUDIODATAOUTPUTINTERFACE_H
+#define PHONON_AUDIODATAOUTPUTINTERFACE_H
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+class AudioDataOutput;
+
+class AudioDataOutputInterface
+{
+ public:
+ virtual ~AudioDataOutputInterface() {}
+
+ virtual AudioDataOutput *frontendObject() const = 0;
+ virtual void setFrontendObject(AudioDataOutput *) = 0;
+};
+
+} // namespace Phonon
+
+Q_DECLARE_INTERFACE(Phonon::AudioDataOutputInterface, "0AudioDataOutputInterface.phonon.kde.org")
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_AUDIODATAOUTPUTINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/audiooutput.cpp b/src/3rdparty/phonon/phonon/audiooutput.cpp
new file mode 100644
index 0000000..e94caad
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiooutput.cpp
@@ -0,0 +1,511 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "audiooutput.h"
+#include "audiooutput_p.h"
+#include "factory_p.h"
+#include "objectdescription.h"
+#include "audiooutputadaptor_p.h"
+#include "globalconfig.h"
+#include "audiooutputinterface.h"
+#include "phononnamespace_p.h"
+#include "platform_p.h"
+#include "pulsesupport.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/quuid.h>
+
+#define PHONON_CLASSNAME AudioOutput
+#define IFACES2 AudioOutputInterface42
+#define IFACES1 IFACES2
+#define IFACES0 AudioOutputInterface40, IFACES1
+#define PHONON_INTERFACENAME IFACES0
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+static inline bool callSetOutputDevice(AudioOutputPrivate *const d, int index)
+{
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive())
+ return pulse->setOutputDevice(d->getStreamUuid(), index);
+
+ Iface<IFACES2> iface(d);
+ if (iface) {
+ return iface->setOutputDevice(AudioOutputDevice::fromIndex(index));
+ }
+ return Iface<IFACES0>::cast(d)->setOutputDevice(index);
+}
+
+static inline bool callSetOutputDevice(AudioOutputPrivate *const d, const AudioOutputDevice &dev)
+{
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive())
+ return pulse->setOutputDevice(d->getStreamUuid(), dev.index());
+
+ Iface<IFACES2> iface(d);
+ if (iface) {
+ return iface->setOutputDevice(dev);
+ }
+ return Iface<IFACES0>::cast(d)->setOutputDevice(dev.index());
+}
+
+AudioOutput::AudioOutput(Phonon::Category category, QObject *parent)
+ : AbstractAudioOutput(*new AudioOutputPrivate, parent)
+{
+ K_D(AudioOutput);
+ d->init(category);
+}
+
+AudioOutput::AudioOutput(QObject *parent)
+ : AbstractAudioOutput(*new AudioOutputPrivate, parent)
+{
+ K_D(AudioOutput);
+ d->init(NoCategory);
+}
+
+void AudioOutputPrivate::init(Phonon::Category c)
+{
+ Q_Q(AudioOutput);
+#ifndef QT_NO_DBUS
+ adaptor = new AudioOutputAdaptor(q);
+ static unsigned int number = 0;
+ const QString &path = QLatin1String("/AudioOutputs/") + QString::number(number++);
+ QDBusConnection con = QDBusConnection::sessionBus();
+ con.registerObject(path, q);
+ emit adaptor->newOutputAvailable(con.baseService(), path);
+ q->connect(q, SIGNAL(volumeChanged(qreal)), adaptor, SIGNAL(volumeChanged(qreal)));
+ q->connect(q, SIGNAL(mutedChanged(bool)), adaptor, SIGNAL(mutedChanged(bool)));
+#endif
+
+ category = c;
+ streamUuid = QUuid::createUuid().toString();
+ PulseSupport *pulse = PulseSupport::getInstance();
+ pulse->setStreamPropList(category, streamUuid);
+ q->connect(pulse, SIGNAL(usingDevice(QString,int)), SLOT(_k_deviceChanged(QString,int)));
+
+ createBackendObject();
+
+ q->connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(_k_deviceListChanged()));
+}
+
+QString AudioOutputPrivate::getStreamUuid()
+{
+ return streamUuid;
+}
+
+void AudioOutputPrivate::createBackendObject()
+{
+ if (m_backendObject)
+ return;
+ Q_Q(AudioOutput);
+ m_backendObject = Factory::createAudioOutput(q);
+ device = AudioOutputDevice::fromIndex(GlobalConfig().audioOutputDeviceFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices));
+ if (m_backendObject) {
+ setupBackendObject();
+ }
+}
+
+QString AudioOutput::name() const
+{
+ K_D(const AudioOutput);
+ return d->name;
+}
+
+void AudioOutput::setName(const QString &newName)
+{
+ K_D(AudioOutput);
+ if (d->name == newName) {
+ return;
+ }
+ d->name = newName;
+ setVolume(Platform::loadVolume(newName));
+#ifndef QT_NO_DBUS
+ if (d->adaptor) {
+ emit d->adaptor->nameChanged(newName);
+ }
+#endif
+}
+
+static const qreal LOUDNESS_TO_VOLTAGE_EXPONENT = qreal(0.67);
+static const qreal VOLTAGE_TO_LOUDNESS_EXPONENT = qreal(1.0/LOUDNESS_TO_VOLTAGE_EXPONENT);
+
+void AudioOutput::setVolume(qreal volume)
+{
+ K_D(AudioOutput);
+ d->volume = volume;
+ if (k_ptr->backendObject() && !d->muted) {
+ // using Stevens' power law loudness is proportional to (sound pressure)^0.67
+ // sound pressure is proportional to voltage:
+ // p² \prop P \prop V²
+ // => if a factor for loudness of x is requested
+ INTERFACE_CALL(setVolume(pow(volume, VOLTAGE_TO_LOUDNESS_EXPONENT)));
+ } else {
+ emit volumeChanged(volume);
+ }
+ Platform::saveVolume(d->name, volume);
+}
+
+qreal AudioOutput::volume() const
+{
+ K_D(const AudioOutput);
+ if (d->muted || !d->m_backendObject) {
+ return d->volume;
+ }
+ return pow(INTERFACE_CALL(volume()), LOUDNESS_TO_VOLTAGE_EXPONENT);
+}
+
+#ifndef PHONON_LOG10OVER20
+#define PHONON_LOG10OVER20
+static const qreal log10over20 = qreal(0.1151292546497022842); // ln(10) / 20
+#endif // PHONON_LOG10OVER20
+
+qreal AudioOutput::volumeDecibel() const
+{
+ K_D(const AudioOutput);
+ if (d->muted || !d->m_backendObject) {
+ return log(d->volume) / log10over20;
+ }
+ return 0.67 * log(INTERFACE_CALL(volume())) / log10over20;
+}
+
+void AudioOutput::setVolumeDecibel(qreal newVolumeDecibel)
+{
+ setVolume(exp(newVolumeDecibel * log10over20));
+}
+
+bool AudioOutput::isMuted() const
+{
+ K_D(const AudioOutput);
+ return d->muted;
+}
+
+void AudioOutput::setMuted(bool mute)
+{
+ K_D(AudioOutput);
+ if (d->muted != mute) {
+ if (mute) {
+ d->muted = mute;
+ if (k_ptr->backendObject()) {
+ INTERFACE_CALL(setVolume(0.0));
+ }
+ } else {
+ if (k_ptr->backendObject()) {
+ INTERFACE_CALL(setVolume(pow(d->volume, VOLTAGE_TO_LOUDNESS_EXPONENT)));
+ }
+ d->muted = mute;
+ }
+ emit mutedChanged(mute);
+ }
+}
+
+Category AudioOutput::category() const
+{
+ K_D(const AudioOutput);
+ return d->category;
+}
+
+AudioOutputDevice AudioOutput::outputDevice() const
+{
+ K_D(const AudioOutput);
+ return d->device;
+}
+
+bool AudioOutput::setOutputDevice(const AudioOutputDevice &newAudioOutputDevice)
+{
+ K_D(AudioOutput);
+ if (!newAudioOutputDevice.isValid()) {
+ d->outputDeviceOverridden = d->forceMove = false;
+ const int newIndex = GlobalConfig().audioOutputDeviceFor(d->category);
+ if (newIndex == d->device.index()) {
+ return true;
+ }
+ d->device = AudioOutputDevice::fromIndex(newIndex);
+ } else {
+ d->outputDeviceOverridden = d->forceMove = true;
+ if (d->device == newAudioOutputDevice) {
+ return true;
+ }
+ d->device = newAudioOutputDevice;
+ }
+ if (k_ptr->backendObject()) {
+ return callSetOutputDevice(d, d->device.index());
+ }
+ return true;
+}
+
+bool AudioOutputPrivate::aboutToDeleteBackendObject()
+{
+ if (m_backendObject) {
+ volume = pINTERFACE_CALL(volume());
+ }
+ return AbstractAudioOutputPrivate::aboutToDeleteBackendObject();
+}
+
+void AudioOutputPrivate::setupBackendObject()
+{
+ Q_Q(AudioOutput);
+ Q_ASSERT(m_backendObject);
+ AbstractAudioOutputPrivate::setupBackendObject();
+
+ QObject::connect(m_backendObject, SIGNAL(volumeChanged(qreal)), q, SLOT(_k_volumeChanged(qreal)));
+ QObject::connect(m_backendObject, SIGNAL(audioDeviceFailed()), q, SLOT(_k_audioDeviceFailed()));
+
+ // set up attributes
+ pINTERFACE_CALL(setVolume(pow(volume, VOLTAGE_TO_LOUDNESS_EXPONENT)));
+
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+ // if the output device is not available and the device was not explicitly set
+ // There is no need to set the output device initially if PA is used as
+ // we know it will not work (stream doesn't exist yet) and that this will be
+ // handled by _k_deviceChanged()
+ if (!PulseSupport::getInstance()->isActive() && !callSetOutputDevice(this, device) && !outputDeviceOverridden) {
+ // fall back in the preference list of output devices
+ QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices);
+ if (deviceList.isEmpty()) {
+ return;
+ }
+ for (int i = 0; i < deviceList.count(); ++i) {
+ const AudioOutputDevice &dev = AudioOutputDevice::fromIndex(deviceList.at(i));
+ if (callSetOutputDevice(this, dev)) {
+ handleAutomaticDeviceChange(dev, AudioOutputPrivate::FallbackChange);
+ return; // found one that works
+ }
+ }
+ // if we get here there is no working output device. Tell the backend.
+ const AudioOutputDevice none;
+ callSetOutputDevice(this, none);
+ handleAutomaticDeviceChange(none, FallbackChange);
+ }
+#endif //QT_NO_PHONON_SETTINGSGROUP
+}
+
+void AudioOutputPrivate::_k_volumeChanged(qreal newVolume)
+{
+ if (!muted) {
+ Q_Q(AudioOutput);
+ emit q->volumeChanged(pow(newVolume, qreal(0.67)));
+ }
+}
+
+void AudioOutputPrivate::_k_revertFallback()
+{
+ if (deviceBeforeFallback == -1) {
+ return;
+ }
+ device = AudioOutputDevice::fromIndex(deviceBeforeFallback);
+ callSetOutputDevice(this, device);
+ Q_Q(AudioOutput);
+ emit q->outputDeviceChanged(device);
+#ifndef QT_NO_DBUS
+ emit adaptor->outputDeviceIndexChanged(device.index());
+#endif
+}
+
+void AudioOutputPrivate::_k_audioDeviceFailed()
+{
+ if (PulseSupport::getInstance()->isActive())
+ return;
+
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+
+ pDebug() << Q_FUNC_INFO;
+ // outputDeviceIndex identifies a failing device
+ // fall back in the preference list of output devices
+ const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices);
+ for (int i = 0; i < deviceList.count(); ++i) {
+ const int devIndex = deviceList.at(i);
+ // if it's the same device as the one that failed, ignore it
+ if (device.index() != devIndex) {
+ const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex);
+ if (callSetOutputDevice(this, info)) {
+ handleAutomaticDeviceChange(info, FallbackChange);
+ return; // found one that works
+ }
+ }
+ }
+#endif //QT_NO_PHONON_SETTINGSGROUP
+ // if we get here there is no working output device. Tell the backend.
+ const AudioOutputDevice none;
+ callSetOutputDevice(this, none);
+ handleAutomaticDeviceChange(none, FallbackChange);
+}
+
+void AudioOutputPrivate::_k_deviceListChanged()
+{
+ if (PulseSupport::getInstance()->isActive())
+ return;
+
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+ pDebug() << Q_FUNC_INFO;
+ // Check to see if we have an override and do not change to a higher priority device if the overridden device is still present.
+ if (outputDeviceOverridden && device.property("available").toBool()) {
+ return;
+ }
+ // let's see if there's a usable device higher in the preference list
+ const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings);
+ DeviceChangeType changeType = HigherPreferenceChange;
+ for (int i = 0; i < deviceList.count(); ++i) {
+ const int devIndex = deviceList.at(i);
+ const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex);
+ if (!info.property("available").toBool()) {
+ if (device.index() == devIndex) {
+ // we've reached the currently used device and it's not available anymore, so we
+ // fallback to the next available device
+ changeType = FallbackChange;
+ }
+ pDebug() << devIndex << "is not available";
+ continue;
+ }
+ pDebug() << devIndex << "is available";
+ if (device.index() == devIndex) {
+ // we've reached the currently used device, nothing to change
+ break;
+ }
+ if (callSetOutputDevice(this, info)) {
+ handleAutomaticDeviceChange(info, changeType);
+ break; // found one with higher preference that works
+ }
+ }
+#endif //QT_NO_PHONON_SETTINGSGROUP
+}
+
+void AudioOutputPrivate::_k_deviceChanged(QString inStreamUuid, int deviceIndex)
+{
+ // Note that this method is only used by PulseAudio at present.
+ if (inStreamUuid == streamUuid) {
+ // 1. Check to see if we are overridden. If we are, and devices do not match,
+ // then try and apply our own device as the output device.
+ // We only do this the first time
+ if (outputDeviceOverridden && forceMove) {
+ forceMove = false;
+ const AudioOutputDevice &currentDevice = AudioOutputDevice::fromIndex(deviceIndex);
+ if (currentDevice != device) {
+ if (!callSetOutputDevice(this, device)) {
+ // What to do if we are overridden and cannot change to our preferred device?
+ }
+ }
+ }
+ // 2. If we are not overridden, then we need to update our perception of what
+ // device we are using. If the devices do not match, something lower in the
+ // stack is overriding our preferences (e.g. a per-application stream preference,
+ // specific application move, priority list changed etc. etc.)
+ else if (!outputDeviceOverridden) {
+ const AudioOutputDevice &currentDevice = AudioOutputDevice::fromIndex(deviceIndex);
+ if (currentDevice != device) {
+ // The device is not what we think it is, so lets say what is happening.
+ handleAutomaticDeviceChange(currentDevice, SoundSystemChange);
+ }
+ }
+ }
+}
+
+static struct
+{
+ int first;
+ int second;
+} g_lastFallback = { 0, 0 };
+
+void AudioOutputPrivate::handleAutomaticDeviceChange(const AudioOutputDevice &device2, DeviceChangeType type)
+{
+ Q_Q(AudioOutput);
+ deviceBeforeFallback = device.index();
+ device = device2;
+ emit q->outputDeviceChanged(device2);
+#ifndef QT_NO_DBUS
+ emit adaptor->outputDeviceIndexChanged(device.index());
+#endif
+ const AudioOutputDevice &device1 = AudioOutputDevice::fromIndex(deviceBeforeFallback);
+ switch (type) {
+ case FallbackChange:
+ if (g_lastFallback.first != device1.index() || g_lastFallback.second != device2.index()) {
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ const QString &text = //device2.isValid() ?
+ AudioOutput::tr("<html>The audio playback device <b>%1</b> does not work.<br/>"
+ "Falling back to <b>%2</b>.</html>").arg(device1.name()).arg(device2.name()) /*:
+ AudioOutput::tr("<html>The audio playback device <b>%1</b> does not work.<br/>"
+ "No other device available.</html>").arg(device1.name())*/;
+ Platform::notification("AudioDeviceFallback", text);
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ g_lastFallback.first = device1.index();
+ g_lastFallback.second = device2.index();
+ }
+ break;
+ case HigherPreferenceChange:
+ {
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ const QString text = AudioOutput::tr("<html>Switching to the audio playback device <b>%1</b><br/>"
+ "which just became available and has higher preference.</html>").arg(device2.name());
+ Platform::notification("AudioDeviceFallback", text,
+ QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())),
+ q, SLOT(_k_revertFallback()));
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ g_lastFallback.first = 0;
+ g_lastFallback.second = 0;
+ }
+ break;
+ case SoundSystemChange:
+ {
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ if (device1.property("available").toBool()) {
+ const QString text = AudioOutput::tr("<html>Switching to the audio playback device <b>%1</b><br/>"
+ "which has higher preference or is specifically configured for this stream.</html>").arg(device2.name());
+ Platform::notification("AudioDeviceFallback", text,
+ QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())),
+ q, SLOT(_k_revertFallback()));
+ } else {
+ const QString &text =
+ AudioOutput::tr("<html>The audio playback device <b>%1</b> does not work.<br/>"
+ "Falling back to <b>%2</b>.</html>").arg(device1.name()).arg(device2.name());
+ Platform::notification("AudioDeviceFallback", text);
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ //outputDeviceOverridden = true;
+ g_lastFallback.first = 0;
+ g_lastFallback.second = 0;
+ }
+ break;
+ }
+}
+
+AudioOutputPrivate::~AudioOutputPrivate()
+{
+ PulseSupport::getInstance()->clearStreamCache(streamUuid);
+#ifndef QT_NO_DBUS
+ if (adaptor) {
+ emit adaptor->outputDestroyed();
+ }
+#endif
+}
+
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_audiooutput.cpp"
+
+#undef PHONON_CLASSNAME
+#undef PHONON_INTERFACENAME
+#undef IFACES2
+#undef IFACES1
+#undef IFACES0
diff --git a/src/3rdparty/phonon/phonon/audiooutput.h b/src/3rdparty/phonon/phonon/audiooutput.h
new file mode 100644
index 0000000..513a863
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiooutput.h
@@ -0,0 +1,180 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef Phonon_AUDIOOUTPUT_H
+#define Phonon_AUDIOOUTPUT_H
+
+#include "phonon_export.h"
+#include "abstractaudiooutput.h"
+#include "phonondefs.h"
+#include "phononnamespace.h"
+#include "objectdescription.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+class AudioOutputAdaptor;
+namespace Phonon
+{
+ class AudioOutputPrivate;
+
+ /** \class AudioOutput audiooutput.h Phonon/AudioOutput
+ * \short Class for audio output to the soundcard.
+ *
+ * Use this class to define the audio output.
+ *
+ * \ingroup Frontend
+ * \author Matthias Kretz <kretz@kde.org>
+ * \see Phonon::Ui::VolumeSlider
+ */
+ class PHONON_EXPORT AudioOutput : public AbstractAudioOutput
+ {
+ friend class FactoryPrivate;
+ friend class ::AudioOutputAdaptor;
+ Q_OBJECT
+ K_DECLARE_PRIVATE(AudioOutput)
+ /**
+ * This is the name that appears in Mixer applications that control
+ * the volume of this output.
+ *
+ * \see category
+ */
+ Q_PROPERTY(QString name READ name WRITE setName)
+ /**
+ * This is the current loudness of the output (it is using Stevens' law
+ * to calculate the change in voltage internally).
+ *
+ * \see volumeDecibel
+ */
+ Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
+ /**
+ * This is the current volume of the output in decibel.
+ *
+ * 0 dB means no change in volume, -6dB means an attenuation of the
+ * voltage to 50% and an attenuation of the power to 25%, -inf dB means
+ * silence.
+ *
+ * \see volume
+ */
+ Q_PROPERTY(qreal volumeDecibel READ volumeDecibel WRITE setVolumeDecibel)
+ /**
+ * This property holds the (hardware) destination for the output.
+ *
+ * The default device is determined by the category and the global
+ * configuration for that category of outputs. Normally you don't need
+ * to override this setting - letting the user change the global
+ * configuration is the right choice. You can still override the
+ * device though, if you have good reasons to do so.
+ *
+ * \see outputDeviceChanged
+ */
+ Q_PROPERTY(AudioOutputDevice outputDevice READ outputDevice WRITE setOutputDevice)
+
+ /**
+ * This property tells whether the output is muted.
+ *
+ * Muting the output has the same effect as calling setVolume(0.0).
+ */
+ Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
+ public:
+ /**
+ * Creates a new AudioOutput that defines output to a physical
+ * device.
+ *
+ * \param category The category can be used by mixer applications to group volume
+ * controls of applications into categories. That makes it easier for
+ * the user to identify the programs.
+ * The category is also used for the default output device that is
+ * configured centrally. As an example: often users want to have the
+ * audio signal of a VoIP application go to their USB headset while
+ * all other sounds should go to the internal soundcard.
+ *
+ * \param parent QObject parent
+ *
+ * \see Phonon::categoryToString
+ * \see outputDevice
+ */
+ explicit AudioOutput(Phonon::Category category, QObject *parent = 0);
+ explicit AudioOutput(QObject *parent = 0);
+
+ QString name() const;
+ qreal volume() const;
+ qreal volumeDecibel() const;
+
+ /**
+ * Returns the category of this output.
+ *
+ * \see AudioOutput(Phonon::Category, QObject *)
+ */
+ Phonon::Category category() const;
+ AudioOutputDevice outputDevice() const;
+ bool isMuted() const;
+
+ public Q_SLOTS:
+ void setName(const QString &newName);
+ void setVolume(qreal newVolume);
+ void setVolumeDecibel(qreal newVolumeDecibel);
+ bool setOutputDevice(const Phonon::AudioOutputDevice &newAudioOutputDevice);
+ void setMuted(bool mute);
+
+ Q_SIGNALS:
+ /**
+ * This signal is emitted whenever the volume has changed. As the
+ * volume can change without a call to setVolume (calls over dbus)
+ * this is important
+ * to keep a widget showing the current volume up to date.
+ */
+ void volumeChanged(qreal newVolume);
+
+ /**
+ * This signal is emitted when the muted property has changed. As
+ * this property can change by IPC (DBus) calls a UI element showing
+ * the muted property should listen to this signal.
+ */
+ void mutedChanged(bool);
+
+ /**
+ * This signal is emitted when the (hardware) device for the output
+ * has changed.
+ *
+ * The change can happen either through setOutputDevice or if the
+ * global configuration for the used category has changed.
+ *
+ * \see outputDevice
+ */
+ void outputDeviceChanged(const Phonon::AudioOutputDevice &newAudioOutputDevice);
+
+ private:
+ Q_PRIVATE_SLOT(k_func(), void _k_volumeChanged(qreal))
+ Q_PRIVATE_SLOT(k_func(), void _k_revertFallback())
+ Q_PRIVATE_SLOT(k_func(), void _k_audioDeviceFailed())
+ Q_PRIVATE_SLOT(k_func(), void _k_deviceListChanged())
+ Q_PRIVATE_SLOT(k_func(), void _k_deviceChanged(QString streamUuid, int device))
+ };
+} //namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_AUDIOOUTPUT_H
diff --git a/src/3rdparty/phonon/phonon/audiooutput_p.h b/src/3rdparty/phonon/phonon/audiooutput_p.h
new file mode 100644
index 0000000..01dc48f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiooutput_p.h
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef AUDIOOUTPUT_P_H
+#define AUDIOOUTPUT_P_H
+
+#include "audiooutput.h"
+#include "abstractaudiooutput_p.h"
+#include "platform_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+class AudioOutputAdaptor;
+
+class AudioOutputPrivate : public AbstractAudioOutputPrivate
+{
+ Q_DECLARE_PUBLIC(AudioOutput)
+ PHONON_PRIVATECLASS
+ public:
+ inline static AudioOutputPrivate *cast(MediaNodePrivate *x)
+ {
+ if (x && x->castId == MediaNodePrivate::AudioOutputType) {
+ return static_cast<AudioOutputPrivate *>(x);
+ }
+ return 0;
+ }
+ void init(Phonon::Category c);
+ QString getStreamUuid();
+
+
+ protected:
+ AudioOutputPrivate(CastId castId = MediaNodePrivate::AudioOutputType)
+ : AbstractAudioOutputPrivate(castId),
+ name(Platform::applicationName()),
+ volume(Platform::loadVolume(name)),
+#ifndef QT_NO_DBUS
+ adaptor(0),
+#endif
+ deviceBeforeFallback(-1),
+ outputDeviceOverridden(false),
+ forceMove(false),
+ muted(false)
+ {
+ }
+
+ ~AudioOutputPrivate();
+
+ enum DeviceChangeType {
+ FallbackChange,
+ HigherPreferenceChange,
+ SoundSystemChange
+ };
+ void handleAutomaticDeviceChange(const AudioOutputDevice &newDev, DeviceChangeType type);
+
+ void _k_volumeChanged(qreal);
+ void _k_revertFallback();
+ void _k_audioDeviceFailed();
+ void _k_deviceListChanged();
+ void _k_deviceChanged(QString streamUuid, int deviceIndex);
+
+ private:
+ QString name;
+ Phonon::AudioOutputDevice device;
+ qreal volume;
+ QString streamUuid;
+#ifndef QT_NO_DBUS
+ Phonon::AudioOutputAdaptor *adaptor;
+#endif
+ Category category;
+ int deviceBeforeFallback;
+ bool outputDeviceOverridden;
+ bool forceMove;
+ bool muted;
+};
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // AUDIOOUTPUT_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp
new file mode 100644
index 0000000..2c01773
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp
@@ -0,0 +1,101 @@
+/*
+ * This file was generated by dbusidl2cpp version 0.4
+ * when processing input file org.kde.Phonon.AudioOutput.xml
+ *
+ * dbusidl2cpp is Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file. This file has been hand-edited.
+ */
+
+#include "audiooutputadaptor_p.h"
+#include "audiooutput.h"
+#include <QtCore/QArgument>
+#include <QtCore/QByteRef>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include "phononnamespace_p.h"
+#include "objectdescription.h"
+
+#ifndef QT_NO_DBUS
+
+/*
+ * Implementation of adaptor class AudioOutputAdaptor
+ */
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+AudioOutputAdaptor::AudioOutputAdaptor(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
+{
+ // constructor
+ setAutoRelaySignals(true);
+}
+
+AudioOutputAdaptor::~AudioOutputAdaptor()
+{
+ // destructor
+}
+
+double AudioOutputAdaptor::volume() const
+{
+ // get the value of property volume
+ return qvariant_cast<qreal>(parent()->property("volume"));
+}
+
+void AudioOutputAdaptor::setVolume(double value)
+{
+ // set the value of property volume
+ parent()->setProperty("volume", QVariant::fromValue(static_cast<qreal>(value)));
+}
+
+bool AudioOutputAdaptor::muted() const
+{
+ return parent()->property("muted").toBool();
+}
+
+void AudioOutputAdaptor::setMuted(bool value)
+{
+ parent()->setProperty("muted", value);
+}
+
+QString AudioOutputAdaptor::category()
+{
+ // handle method call org.kde.Phonon.AudioOutput.category
+ return Phonon::categoryToString(static_cast<Phonon::AudioOutput *>(parent())->category());
+}
+
+QString AudioOutputAdaptor::name()
+{
+ // handle method call org.kde.Phonon.AudioOutput.name
+ QString name;
+ //QMetaObject::invokeMethod(parent(), "name", Q_RETURN_ARG(QString, name));
+
+ // Alternative:
+ name = static_cast<Phonon::AudioOutput *>(parent())->name();
+ return name;
+}
+
+int AudioOutputAdaptor::outputDeviceIndex() const
+{
+ return static_cast<Phonon::AudioOutput *>(parent())->outputDevice().index();
+}
+
+void AudioOutputAdaptor::setOutputDeviceIndex(int newAudioOutputDeviceIndex)
+{
+ static_cast<Phonon::AudioOutput *>(parent())
+ ->setOutputDevice(Phonon::AudioOutputDevice::fromIndex(newAudioOutputDeviceIndex));
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_audiooutputadaptor_p.cpp"
+
+#endif
diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h
new file mode 100644
index 0000000..7178e9b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h
@@ -0,0 +1,109 @@
+/*
+ * This file was generated by dbusidl2cpp version 0.4
+ * when processing input file org.kde.Phonon.AudioOutput.xml
+ *
+ * dbusidl2cpp is Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file. This file has been hand-edited.
+ */
+
+#ifndef AUDIOOUTPUTADAPTOR_P_H
+#define AUDIOOUTPUTADAPTOR_P_H
+
+#include <QtCore/QObject>
+
+#ifndef QT_NO_DBUS
+#include <QtDBus/QtDBus>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+template<class T> class QList;
+template<class Key, class Value> class QMap;
+class QString;
+class QStringList;
+class QVariant;
+
+namespace Phonon
+{
+ class AudioOutputPrivate;
+ class AudioOutput;
+
+/*
+ * Adaptor class for interface org.kde.Phonon.AudioOutput
+ */
+class AudioOutputAdaptor: public QDBusAbstractAdaptor
+{
+ friend class Phonon::AudioOutputPrivate;
+ friend class Phonon::AudioOutput;
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.kde.Phonon.AudioOutput")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"org.kde.Phonon.AudioOutput\" >\n"
+" <property access=\"readwrite\" type=\"d\" name=\"volume\" />\n"
+" <property access=\"readwrite\" type=\"b\" name=\"muted\" />\n"
+" <property access=\"readwrite\" type=\"i\" name=\"outputDeviceIndex\" />\n"
+" <signal name=\"volumeChanged\" >\n"
+" <arg direction=\"out\" type=\"d\" />\n"
+" </signal>\n"
+" <signal name=\"mutedChanged\" >\n"
+" <arg direction=\"out\" type=\"b\" />\n"
+" </signal>\n"
+" <signal name=\"outputDeviceIndexChanged\" >\n"
+" <arg direction=\"out\" type=\"i\" />\n"
+" </signal>\n"
+" <signal name=\"nameChanged\" >\n"
+" <arg direction=\"out\" type=\"s\" name=\"newName\" />\n"
+" </signal>\n"
+" <signal name=\"newOutputAvailable\" >\n"
+" <arg direction=\"out\" type=\"s\" name=\"service\" />\n"
+" <arg direction=\"out\" type=\"s\" name=\"path\" />\n"
+" </signal>\n"
+" <signal name=\"outputDestroyed\" >\n"
+" </signal>\n"
+" <method name=\"category\" >\n"
+" <arg direction=\"out\" type=\"s\" />\n"
+" </method>\n"
+" <method name=\"name\" >\n"
+" <arg direction=\"out\" type=\"s\" />\n"
+" </method>\n"
+" </interface>\n"
+ "")
+public:
+ AudioOutputAdaptor(QObject *parent);
+ virtual ~AudioOutputAdaptor();
+
+public: // PROPERTIES
+ Q_PROPERTY(bool muted READ muted WRITE setMuted)
+ bool muted() const;
+ void setMuted(bool value);
+
+ Q_PROPERTY(int outputDeviceIndex READ outputDeviceIndex WRITE setOutputDeviceIndex)
+ int outputDeviceIndex() const;
+ void setOutputDeviceIndex(int value);
+
+ Q_PROPERTY(double volume READ volume WRITE setVolume)
+ double volume() const;
+ void setVolume(double value);
+
+public Q_SLOTS: // METHODS
+ QString category();
+ QString name();
+Q_SIGNALS: // SIGNALS
+ void mutedChanged(bool in0);
+ void nameChanged(const QString &newName);
+ void newOutputAvailable(const QString &service, const QString &path);
+ void outputDestroyed();
+ void outputDeviceIndexChanged(int in0);
+ void volumeChanged(qreal in0);
+};
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QT_NO_DBUS
+
+#endif // AUDIOOUTPUTADAPTOR_P_H
diff --git a/src/3rdparty/phonon/phonon/audiooutputinterface.cpp b/src/3rdparty/phonon/phonon/audiooutputinterface.cpp
new file mode 100644
index 0000000..1770f4c
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiooutputinterface.cpp
@@ -0,0 +1,40 @@
+/* This file is part of the KDE project
+ Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "audiooutputinterface.h"
+#include <QtCore/QList>
+#include <QtCore/QStringList>
+#include <QtCore/QPair>
+#include "platform_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+QList<QPair<QByteArray, QString> > AudioOutputInterface42::deviceAccessListFor(const Phonon::AudioOutputDevice &deviceDesc) const
+{
+ return Platform::deviceAccessListFor(deviceDesc);
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/audiooutputinterface.h b/src/3rdparty/phonon/phonon/audiooutputinterface.h
new file mode 100644
index 0000000..cce12b2
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiooutputinterface.h
@@ -0,0 +1,151 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_AUDIOOUTPUTINTERFACE_H
+#define PHONON_AUDIOOUTPUTINTERFACE_H
+
+#include "phononnamespace.h"
+#include "objectdescription.h"
+#include "phonondefs.h"
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+/** \class AudioOutputInterface audiooutputinterface.h Phonon/AudioOutputInterface
+ * \short Interface for AudioOutput objects
+ *
+ * The implementation can make use of the signals
+ * \code
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+ * \endcode
+ * to notify the frontend whenever the volume has changed or when an audioDeviceFailed (e.g. USB
+ * unplug or sound server failure).
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class AudioOutputInterface40
+{
+ public:
+ virtual ~AudioOutputInterface40() {}
+
+ /**
+ * Returns the current software volume.
+ *
+ * A value of 0.0 means muted, 1.0 means unchanged, 2.0 means double voltage (i.e. all
+ * samples are multiplied by 2).
+ */
+ virtual qreal volume() const = 0;
+ /**
+ * Sets the new current software volume.
+ *
+ * A value of 0.0 means muted, 1.0 means unchanged, 2.0 means double voltage (i.e. all
+ * samples are multiplied by 2).
+ *
+ * Every time the volume in the backend changes it should emit volumeChanged(qreal), also
+ * inside this function.
+ */
+ virtual void setVolume(qreal) = 0;
+
+ /**
+ * Returns the index of the device that is used. The index is the number returned from
+ * BackendInterface::objectDescriptionIndexes(AudioOutputDeviceType).
+ */
+ virtual int outputDevice() const = 0;
+ /**
+ * \deprecated
+ *
+ * Requests to change the current output device to the one identified by the passed index.
+ *
+ * The index is the number returned from
+ * BackendInterface::objectDescriptionIndexes(AudioOutputDeviceType).
+ *
+ * \returns \c true if the requested device works and is used after this call.
+ * \returns \c false if something failed and the device is not used after this call.
+ */
+ virtual bool setOutputDevice(int) = 0;
+};
+
+class AudioOutputInterface42 : public AudioOutputInterface40
+{
+ public:
+ /**
+ * Requests to change the current output device.
+ *
+ * \returns \c true if the requested device works and is used after this call.
+ * \returns \c false if something failed and the device is not used after this call.
+ */
+ virtual bool setOutputDevice(const Phonon::AudioOutputDevice &) = 0;
+
+ using AudioOutputInterface40::setOutputDevice;
+
+ /**
+ * Helper function for backends to get a list of (driver, handle) pairs for
+ * AudioOutputDevice objects that are listed by the platform plugin.
+ *
+ * Example:
+ * \code
+ typedef QPair<QByteArray, QString> PhononDeviceAccess;
+ const QList<PhononDeviceAccess> &deviceAccessList = deviceAccessListFor(deviceDesc);
+ foreach (const PhononDeviceAccess &access, deviceAccessList) {
+ const QByteArray &driver = access.first;
+ const QString &handle = access.second;
+ if (openDevice(driver, handle)) {
+ // we found the first pair in the list that works. done.
+ return;
+ }
+ // continue trying the other (driver, handle) pairs
+ }
+ // none of the (driver, handle) pairs worked, that means the whole AudioOutputDevice is
+ // inaccessible and the frontend needs to know (either by emitting audioDeviceFailed or
+ // returning false when called from setOutputDevice)
+ * \endcode
+ *
+ * At the time of this writing the following driver strings are known to be in use:
+ * \li \c alsa: The handle is the string to pass to snd_pcm_open (e.g. "dmix:CARD=0,DEV=1")
+ * \li \c oss: The handle is the device file (e.g. "/dev/dsp")
+ * \li \c pulseaudio: The handle contains the server string and the sink/source name
+ * separated by a newline character.
+ * (e.g. unix:/tmp/pulse-mkretz/native\nalsa_output.pci_8086_293e_sound_card_0_alsa_playback_0)
+ */
+ PHONON_EXPORT QList<QPair<QByteArray, QString> > deviceAccessListFor(const Phonon::AudioOutputDevice &) const;
+};
+
+} // namespace Phonon
+
+#ifdef PHONON_BACKEND_VERSION_4_2
+namespace Phonon { typedef AudioOutputInterface42 AudioOutputInterface; }
+Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface40, "AudioOutputInterface2.phonon.kde.org")
+Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface, "3AudioOutputInterface.phonon.kde.org")
+#else
+namespace Phonon { typedef AudioOutputInterface40 AudioOutputInterface; }
+Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface, "AudioOutputInterface2.phonon.kde.org")
+Q_DECLARE_INTERFACE(Phonon::AudioOutputInterface42, "3AudioOutputInterface.phonon.kde.org")
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_AUDIOOUTPUTINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/backend.dox b/src/3rdparty/phonon/phonon/backend.dox
new file mode 100644
index 0000000..8a9c5b2
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/backend.dox
@@ -0,0 +1,107 @@
+/**
+\page phonon_Backend The Backend Class
+\ingroup Backend
+
+\section phonon_Backend_requiredfunctions Required Functions
+\li bool \ref phonon_Backend_supportsOSD "supportsOSD()"
+\li bool \ref phonon_Backend_supportsFourcc "supportsFourcc( quint32 )"
+\li bool \ref phonon_Backend_supportsSubtitles "supportsSubtitles()"
+\li bool \ref phonon_Backend_supportsVideo "supportsVideo()"
+\li QStringList \ref phonon_Backend_availableMimeTypes "availableMimeTypes()"
+
+\section Member Function Documentation
+
+\subsection phonon_Backend_supportsFourcc bool supportsFourcc( quint32 fourcc )
+Tells whether the FOURCC (four character code) is supported for
+the \ref phonon_VideoDataOutput "VideoDataOutput" interface. If you return \c true, you have to be
+able to return VideoFrame objects accordingly from
+\ref phonon_VideoDataOutput "VideoDataOutput".
+\param fourcc A four character code defining a video frame format.
+\returns \c true if your \ref phonon_VideoDataOutput "VideoDataOutput" can
+output video frames in the requested format.
+\returns \c false if the video frames can not be converted into the requested
+format.
+
+\subsection phonon_Backend_availableMimeTypes QStringList availableMimeTypes()
+Lists the MIME types the backend can read and decode.
+
+\subsection phonon_Backend_xIndexes QSet<int> <device/codec/effect/...>Indexes()
+ Returns a set of indexes that identify the devices/codecs/effects/... the
+ backend supports. This list needs to be compiled from looking at
+ available hardware and virtual devices/plugins/... . The implementation
+ should use cached information, but you need to invalidate the cache
+ whenever the hardware configuration changes or new virtual devices come
+ available/new plugins are installed/... .
+
+ \return The indexes of the available devices/codecs/effects/...
+
+ \see \ref phonon_Backend_xName
+ \see \ref phonon_Backend_xDescription
+
+\subsection phonon_Backend_xName QString <device/codec/effect/...>Name( int index )
+ Returns the name of the given device/codec/effect/...
+
+ \param index The index of one device/codec/effect/... this is one index
+ out of \ref phonon_Backend_xIndexes
+
+ \returns A translated user visible string to name the device.
+
+ \see \ref phonon_Backend_xIndexes
+ \see \ref phonon_Backend_xDescription
+\subsection phonon_Backend_xDescription QString <device/codec/effect/...>Description( int index )
+ Returns the description of the given device/codec/effect/...
+
+ \param index The index of one device/codec/effect/... this is one index
+ out of \ref phonon_Backend_xIndexes
+
+ \returns A translated user visible string to describe the device.
+
+ \see \ref phonon_Backend_xIndexes
+ \see \ref phonon_Backend_xName
+
+\subsection phonon_Backend_audioCaptureDeviceVideoIndex qint32 audioCaptureDeviceVideoIndex( int index )
+ \param index The index of the device. This is one of the indexes the backend
+ returned via \ref phonon_Backend_xIndexes
+ \returns An index of a video capture device that is associated with the given
+ audio capture device. For example a webcam might have both a video and an audio
+ capture device, and in order give the user a hint that the audio and video
+ capture devices belong together this index is used.
+ \returns If there is no associated video capture device return -1.
+
+\subsection phonon_Backend_videoCaptureDeviceAudioIndex qint32 videoCaptureDeviceAudioIndex( int index )
+ \param index The index of the device. This is one of the indexes the backend
+ returned via \ref phonon_Backend_xIndexes
+ \returns An index of a audio capture device that is associated with the given
+ video capture device. For example a webcam might have both a audio and an video
+ capture device, and in order give the user a hint that the video and audio
+ capture devices belong together this index is used.
+ \returns If there is no associated audio capture device return -1.
+
+\page phonon_AudioDataOutput The AudioDataOutput Class
+\ingroup Backend
+
+\page phonon_AudioOutput The AudioOutput Class
+\ingroup Backend
+
+\page phonon_VideoDataOutput The VideoDataOutput Class
+\ingroup Backend
+
+\page phonon_VideoWidget The VideoWidget Class
+\ingroup Backend
+
+\page phonon_Effect The Effect Class
+\ingroup Backend
+
+\page phonon_BrightnessControl The BrightnessControl Class
+\ingroup Backend
+
+\page phonon_VideoEffect The VideoEffect Class
+\ingroup Backend
+
+\page phonon_Visualization The Visualization Class
+\ingroup Backend
+
+\page phonon_VolumeFaderEffect The VolumeFaderEffect Class
+\ingroup Backend
+
+*/
diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/backendcapabilities.cpp
new file mode 100644
index 0000000..8dad589
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/backendcapabilities.cpp
@@ -0,0 +1,123 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "backendcapabilities.h"
+#include "backendcapabilities_p.h"
+
+#include "phonondefs_p.h"
+#include "backendinterface.h"
+#include "factory_p.h"
+#include "globalconfig.h"
+#include "globalstatic_p.h"
+#include "objectdescription.h"
+
+#include <QtCore/QList>
+#include <QtCore/QSet>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+PHONON_GLOBAL_STATIC(Phonon::BackendCapabilitiesPrivate, globalBCPrivate)
+
+namespace Phonon
+{
+
+BackendCapabilities::Notifier *BackendCapabilities::notifier()
+{
+ return globalBCPrivate;
+}
+
+QStringList BackendCapabilities::availableMimeTypes()
+{
+ if (BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend()))
+ return backendIface->availableMimeTypes();
+ else
+ return QStringList();
+}
+
+bool BackendCapabilities::isMimeTypeAvailable(const QString &mimeType)
+{
+ QObject *m_backendObject = Factory::backend(false);
+ if (!m_backendObject) {
+ if (!Factory::isMimeTypeAvailable(mimeType)) {
+ return false;
+ }
+ // without loading the backend we found out that the MIME type might be supported, now we
+ // want to know for certain. For that we need to load the backend.
+ m_backendObject = Factory::backend(true);
+ }
+ if (!m_backendObject) {
+ // no backend == no MIME type supported at all
+ return false;
+ }
+ return availableMimeTypes().contains(mimeType);
+}
+
+QList<AudioOutputDevice> BackendCapabilities::availableAudioOutputDevices()
+{
+ QList<AudioOutputDevice> ret;
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+ const QList<int> deviceIndexes = GlobalConfig().audioOutputDeviceListFor(Phonon::NoCategory);
+ for (int i = 0; i < deviceIndexes.count(); ++i) {
+ ret.append(AudioOutputDevice::fromIndex(deviceIndexes.at(i)));
+ }
+#endif //QT_NO_PHONON_SETTINGSGROUP
+ return ret;
+}
+
+
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+QList<AudioCaptureDevice> BackendCapabilities::availableAudioCaptureDevices()
+{
+ QList<AudioCaptureDevice> ret;
+ const QList<int> deviceIndexes = GlobalConfig().audioCaptureDeviceListFor(Phonon::NoCategory);
+ for (int i = 0; i < deviceIndexes.count(); ++i) {
+ ret.append(AudioCaptureDevice::fromIndex(deviceIndexes.at(i)));
+ }
+ return ret;
+}
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+
+#ifndef QT_NO_PHONON_EFFECT
+QList<EffectDescription> BackendCapabilities::availableAudioEffects()
+{
+ BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
+ QList<EffectDescription> ret;
+ if (backendIface) {
+ const QList<int> deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::EffectType);
+ for (int i = 0; i < deviceIndexes.count(); ++i) {
+ ret.append(EffectDescription::fromIndex(deviceIndexes.at(i)));
+ }
+ }
+ return ret;
+}
+#endif //QT_NO_PHONON_EFFECT
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_backendcapabilities.cpp"
+
+// vim: sw=4 ts=4
+
+
diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.h b/src/3rdparty/phonon/phonon/backendcapabilities.h
new file mode 100644
index 0000000..643c8ef
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/backendcapabilities.h
@@ -0,0 +1,212 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef Phonon_BACKENDCAPABILITIES_H
+#define Phonon_BACKENDCAPABILITIES_H
+
+#include "phonon_export.h"
+#include "objectdescription.h"
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifdef __QT_SYNCQT__
+// Tell syncqt that the BackendCapabilities namespace should be treated like a class
+#pragma qt_class(Phonon::BackendCapabilities)
+#pragma qt_sync_stop_processing
+#endif
+
+template<class T> class QList;
+class QStringList;
+
+namespace Phonon
+{
+
+/**
+ * Collection of functions describing the capabilities of the Backend.
+ *
+ * \ingroup BackendInformation
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+namespace BackendCapabilities
+{
+ /** \class Notifier backendcapabilities.h Phonon/BackendCapabilities
+ * Notifications about backend capabilities.
+ *
+ * \ingroup BackendInformation
+ */
+ class Notifier : public QObject
+ {
+ Q_OBJECT
+ Q_SIGNALS:
+ /**
+ * This signal is emitted if the capabilities have changed. This can
+ * happen if the user has requested a backend change.
+ */
+ void capabilitiesChanged();
+
+ /**
+ * This signal is emitted when audio output devices were plugged or
+ * unplugged.
+ *
+ * Check BackendCapabilities::availableAudioOutputDevices to get the
+ * current list of available devices.
+ */
+ void availableAudioOutputDevicesChanged();
+
+ /**
+ * This signal is emitted when audio capture devices were plugged or
+ * unplugged.
+ *
+ * Check BackendCapabilities::availableAudioCaptureDevices to get the
+ * current list of available devices.
+ */
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ void availableAudioCaptureDevicesChanged();
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+ };
+
+ /**
+ * Use this function to get a QObject pointer to connect to one of the Notifier signals.
+ *
+ * \return a pointer to a QObject.
+ *
+ * To connect to the signal do the following:
+ * \code
+ * QObject::connect(BackendCapabilities::notifier(), SIGNAL(capabilitiesChanged()), ...
+ * \endcode
+ *
+ * \see Notifier::capabilitiesChanged()
+ * \see Notifier::availableAudioOutputDevicesChanged()
+ * \see Notifier::availableAudioCaptureDevicesChanged()
+ */
+ PHONON_EXPORT Notifier *notifier();
+
+ /**
+ * Returns a list of mime types that the Backend can decode.
+ *
+ * \see isMimeTypeAvailable()
+ */
+ PHONON_EXPORT QStringList availableMimeTypes();
+
+ /**
+ * Often all you want to know is whether one given MIME type can be
+ * decoded by the backend. Use this method in favor of availableMimeTypes()
+ * as it can give you a negative answer without having a backend loaded.
+ *
+ * \see availableMimeTypes();
+ */
+ PHONON_EXPORT bool isMimeTypeAvailable(const QString &mimeType);
+
+ /**
+ * Returns the audio output devices the backend supports.
+ *
+ * \return A list of AudioOutputDevice objects that give a name and
+ * description for every supported audio output device.
+ */
+ PHONON_EXPORT QList<AudioOutputDevice> availableAudioOutputDevices();
+
+ /**
+ * Returns the audio capture devices the backend supports.
+ *
+ * \return A list of AudioCaptureDevice objects that give a name and
+ * description for every supported audio capture device.
+ */
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ PHONON_EXPORT QList<AudioCaptureDevice> availableAudioCaptureDevices();
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+
+ /**
+ * Returns the video output devices the backend supports.
+ *
+ * \return A list of VideoOutputDevice objects that give a name and
+ * description for every supported video output device.
+ */
+// PHONON_EXPORT QList<VideoOutputDevice> availableVideoOutputDevices();
+
+ /**
+ * Returns the video capture devices the backend supports.
+ *
+ * \return A list of VideoCaptureDevice objects that give a name and
+ * description for every supported video capture device.
+ */
+// PHONON_EXPORT QList<VideoCaptureDevice> availableVideoCaptureDevices();
+
+ /**
+ * Returns the visualization effects the backend supports.
+ *
+ * \return A list of VisualizationEffect objects that give a name and
+ * description for every supported visualization effect.
+ */
+// PHONON_EXPORT QList<VisualizationDescription> availableVisualizations();
+
+ /**
+ * Returns descriptions for the audio effects the backend supports.
+ *
+ * \return A list of AudioEffectDescription objects that give a name and
+ * description for every supported audio effect.
+ */
+#ifndef QT_NO_PHONON_EFFECT
+ PHONON_EXPORT QList<EffectDescription> availableAudioEffects();
+#endif //QT_NO_PHONON_EFFECT
+
+//X /**
+//X * Returns descriptions for the video effects the backend supports.
+//X *
+//X * \return A list of VideoEffectDescription objects that give a name and
+//X * description for every supported video effect.
+//X */
+//X PHONON_EXPORT QList<EffectDescription> availableVideoEffects();
+
+ /**
+ * Returns descriptions for the audio codecs the backend supports.
+ *
+ * \return A list of AudioCodec objects that give a name and
+ * description for every supported audio codec.
+ */
+// PHONON_EXPORT QList<AudioCodecDescription> availableAudioCodecs();
+
+ /**
+ * Returns descriptions for the video codecs the backend supports.
+ *
+ * \return A list of VideoCodec objects that give a name and
+ * description for every supported video codec.
+ */
+// PHONON_EXPORT QList<VideoCodecDescription> availableVideoCodecs();
+
+ /**
+ * Returns descriptions for the container formats the backend supports.
+ *
+ * \return A list of ContainerFormat objects that give a name and
+ * description for every supported container format.
+ */
+// PHONON_EXPORT QList<ContainerFormatDescription> availableContainerFormats();
+} // namespace BackendCapabilities
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // Phonon_BACKENDCAPABILITIES_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/backendcapabilities_p.h b/src/3rdparty/phonon/phonon/backendcapabilities_p.h
new file mode 100644
index 0000000..5ef18a4
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/backendcapabilities_p.h
@@ -0,0 +1,50 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_BACKENDCAPABILITIES_P_H
+#define PHONON_BACKENDCAPABILITIES_P_H
+
+#include "backendcapabilities.h"
+#include <QtCore/QObject>
+#include "factory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+class BackendCapabilitiesPrivate : public BackendCapabilities::Notifier
+{
+ public:
+ BackendCapabilitiesPrivate()
+ {
+ connect(Factory::sender(), SIGNAL(backendChanged()), SIGNAL(capabilitiesChanged()));
+ connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SIGNAL(availableAudioOutputDevicesChanged()));
+ connect(Factory::sender(), SIGNAL(availableAudioCaptureDevicesChanged()), SIGNAL(availableAudioCaptureDevicesChanged()));
+ }
+};
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // PHONON_BACKENDCAPABILITIES_P_H
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/phonon/backendinterface.h b/src/3rdparty/phonon/phonon/backendinterface.h
new file mode 100644
index 0000000..5deee75
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/backendinterface.h
@@ -0,0 +1,287 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_BACKENDINTERFACE_H
+#define PHONON_BACKENDINTERFACE_H
+
+#include "phonon_export.h"
+#include "objectdescription.h"
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QVariant;
+
+namespace Phonon
+{
+
+/** \class BackendInterface backendinterface.h Phonon/BackendInterface
+ * \short Main Backend class interface
+ *
+ * This interface defines the main factory of the backend. The createObject function creates all the
+ * objects needed by the frontend.
+ *
+ * The objectDescriptionIndexes and objectDescriptionProperties functions return information about
+ * available devices, effects and codecs.
+ *
+ * An implementation could look like this:
+ * \code
+ * QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+ * {
+ * switch (c) {
+ * case MediaObjectClass:
+ * return new MediaObject(parent);
+ * case VolumeFaderEffectClass:
+ * return new VolumeFaderEffect(parent);
+ * case AudioOutputClass:
+ * return new AudioOutput(parent);
+ * case AudioDataOutputClass:
+ * return new AudioDataOutput(parent);
+ * case VisualizationClass:
+ * return new Visualization(parent);
+ * case VideoDataOutputClass:
+ * return new VideoDataOutput(parent);
+ * case EffectClass:
+ * return new Effect(args[0].toInt(), parent);
+ * case VideoWidgetClass:
+ * return new VideoWidget(qobject_cast<QWidget *>(parent));
+ * }
+ * return 0;
+ * }
+ *
+ * QSet<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
+ * {
+ * QSet<int> set;
+ * switch(type)
+ * {
+ * case Phonon::AudioOutputDeviceType:
+ * // use AudioDeviceEnumerator to list ALSA and OSS devices
+ * set << 10000 << 10001;
+ * break;
+ * case Phonon::AudioCaptureDeviceType:
+ * set << 20000 << 20001;
+ * break;
+ * case Phonon::VideoOutputDeviceType:
+ * break;
+ * case Phonon::VideoCaptureDeviceType:
+ * set << 30000 << 30001;
+ * break;
+ * case Phonon::VisualizationType:
+ * case Phonon::AudioCodecType:
+ * case Phonon::VideoCodecType:
+ * case Phonon::ContainerFormatType:
+ * break;
+ * case Phonon::EffectType:
+ * set << 0x7F000001;
+ * break;
+ * }
+ * return set;
+ * }
+ *
+ * QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+ * {
+ * QHash<QByteArray, QVariant> ret;
+ * switch (type) {
+ * case Phonon::AudioOutputDeviceType:
+ * switch (index) {
+ * case 10000:
+ * ret.insert("name", QLatin1String("internal Soundcard"));
+ * break;
+ * case 10001:
+ * ret.insert("name", QLatin1String("USB Headset"));
+ * ret.insert("icon", KIcon("usb-headset"));
+ * ret.insert("available", false);
+ * break;
+ * }
+ * break;
+ * case Phonon::AudioCaptureDeviceType:
+ * switch (index) {
+ * case 20000:
+ * ret.insert("name", QLatin1String("Soundcard"));
+ * ret.insert("description", QLatin1String("first description"));
+ * break;
+ * case 20001:
+ * ret.insert("name", QLatin1String("DV"));
+ * ret.insert("description", QLatin1String("second description"));
+ * break;
+ * }
+ * break;
+ * case Phonon::VideoOutputDeviceType:
+ * break;
+ * case Phonon::VideoCaptureDeviceType:
+ * switch (index) {
+ * case 30000:
+ * ret.insert("name", QLatin1String("USB Webcam"));
+ * ret.insert("description", QLatin1String("first description"));
+ * break;
+ * case 30001:
+ * ret.insert("name", QLatin1String("DV"));
+ * ret.insert("description", QLatin1String("second description"));
+ * break;
+ * }
+ * break;
+ * case Phonon::VisualizationType:
+ * break;
+ * case Phonon::AudioCodecType:
+ * break;
+ * case Phonon::VideoCodecType:
+ * break;
+ * case Phonon::ContainerFormatType:
+ * break;
+ * case Phonon::EffectType:
+ * switch (index) {
+ * case 0x7F000001:
+ * ret.insert("name", QLatin1String("Delay"));
+ * ret.insert("description", QLatin1String("Simple delay effect with time, feedback and level controls."));
+ * break;
+ * }
+ * break;
+ * }
+ * return ret;
+ * }
+ * \endcode
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class BackendInterface
+{
+ public:
+ /**
+ * \internal
+ *
+ * Silence gcc's warning.
+ */
+ virtual ~BackendInterface() {}
+
+ /**
+ * Classes that the createObject function has to handle.
+ */
+ enum Class {
+ /**
+ * Request to return a %MediaObject object.
+ */
+ MediaObjectClass,
+ /**
+ * Request to return a %VolumeFaderEffect object.
+ */
+ VolumeFaderEffectClass,
+ /**
+ * Request to return a %AudioOutput object.
+ */
+ AudioOutputClass,
+ /**
+ * Request to return a %AudioDataOutput object.
+ */
+ AudioDataOutputClass,
+ /**
+ * Request to return a %Visualization object.
+ */
+ VisualizationClass,
+ /**
+ * Request to return a %VideoDataOutput object.
+ */
+ VideoDataOutputClass,
+ /**
+ * Request to return a %Effect object.
+ *
+ * Takes an additional int that specifies the effect Id.
+ */
+ EffectClass,
+ /**
+ * Request to return a %VideoWidget object.
+ */
+ VideoWidgetClass
+ };
+
+ /**
+ * Returns a new instance of the requested class.
+ *
+ * \param c The requested class.
+ * \param parent The parent object.
+ * \param args Additional arguments (documented in \ref Class).
+ */
+ virtual QObject *createObject(Class c, QObject *parent, const QList<QVariant> &args = QList<QVariant>()) = 0;
+
+ /**
+ * Returns the unique identifiers for the devices/effects/codecs of the given \p type.
+ *
+ * \param type see \ref ObjectDescriptionType
+ */
+ virtual QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const = 0;
+
+ /**
+ * Given a unique identifier that was returned from objectDescriptionIndexes this function
+ * returns a hash mapping property names to values.
+ *
+ * The property "name" must always be present. All other properties are optional.
+ *
+ * List of possible properties:
+ * \li \c \b name: The name of the device/effect/codec/...
+ * \li \c \b description: A text explaining what this device/effect/codec/... is/can do
+ * \li \c \b icon: An icon name (using the freedesktop naming scheme) or a QIcon for this
+ * device/effect/codec/...
+ * \li \c \b available: A bool telling whether the device is present or unplugged.
+ *
+ * \param type see \ref ObjectDescriptionType
+ * \param index The unique identifier that is returned from objectDescriptionIndexes
+ */
+ virtual QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const = 0;
+
+ /**
+ * When this function is called the nodes given in the parameter list should not lose any
+ * signal data when connections are changed.
+ */
+ virtual bool startConnectionChange(QSet<QObject *>) = 0;
+
+ /**
+ * Defines a signal connection between the two given nodes.
+ */
+ virtual bool connectNodes(QObject *, QObject *) = 0;
+
+ /**
+ * Cuts a signal connection between the two given nodes.
+ */
+ virtual bool disconnectNodes(QObject *, QObject *) = 0;
+
+ /**
+ * When this function is called the nodes given in the parameter list may lose
+ * signal data when a port is not connected.
+ */
+ virtual bool endConnectionChange(QSet<QObject *>) = 0;
+
+ /**
+ * gets all available mime types
+ */
+ virtual QStringList availableMimeTypes() const = 0;
+
+};
+} // namespace Phonon
+
+Q_DECLARE_INTERFACE(Phonon::BackendInterface, "BackendInterface3.phonon.kde.org")
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_BACKENDINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/effect.cpp b/src/3rdparty/phonon/phonon/effect.cpp
new file mode 100644
index 0000000..dfcb290
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effect.cpp
@@ -0,0 +1,138 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "effect.h"
+#include "effect_p.h"
+#include "effectparameter.h"
+#include "effectinterface.h"
+#include "factory_p.h"
+
+#define PHONON_INTERFACENAME EffectInterface
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+Effect::~Effect()
+{
+}
+
+Effect::Effect(const EffectDescription &description, QObject *parent)
+ : QObject(parent), MediaNode(*new EffectPrivate)
+{
+ K_D(Effect);
+ d->description = description;
+ d->createBackendObject();
+}
+
+Effect::Effect(EffectPrivate &dd, QObject *parent)
+ : QObject(parent), MediaNode(dd)
+{
+}
+
+void EffectPrivate::createBackendObject()
+{
+ if (m_backendObject)
+ return;
+ Q_Q(Effect);
+ m_backendObject = Factory::createEffect(description.index(), q);
+ if (m_backendObject) {
+ setupBackendObject();
+ }
+}
+
+//X Effect::Type Effect::type() const
+//X {
+//X K_D(const Effect);
+//X return d->type;
+//X }
+//X
+EffectDescription Effect::description() const
+{
+ K_D(const Effect);
+ return d->description;
+}
+
+QList<EffectParameter> Effect::parameters() const
+{
+ K_D(const Effect);
+ // there should be an iface object, but better be safe for those backend
+ // switching corner-cases: when the backend switches the new backend might
+ // not support this effect -> no iface object
+ if (d->m_backendObject) {
+ return INTERFACE_CALL(parameters());
+ }
+ return QList<EffectParameter>();
+}
+
+QVariant Effect::parameterValue(const EffectParameter &param) const
+{
+ K_D(const Effect);
+ if (!d->m_backendObject) {
+ return d->parameterValues[param];
+ }
+ return INTERFACE_CALL(parameterValue(param));
+}
+
+void Effect::setParameterValue(const EffectParameter &param, const QVariant &newValue)
+{
+ K_D(Effect);
+ d->parameterValues[param] = newValue;
+ if (d->backendObject()) {
+ INTERFACE_CALL(setParameterValue(param, newValue));
+ }
+}
+
+bool EffectPrivate::aboutToDeleteBackendObject()
+{
+ if (m_backendObject) {
+ const QList<EffectParameter> parameters = pINTERFACE_CALL(parameters());
+ for (int i = 0; i < parameters.count(); ++i) {
+ const EffectParameter &p = parameters.at(i);
+ parameterValues[p] = pINTERFACE_CALL(parameterValue(p));
+ }
+ }
+ return true;
+}
+
+void EffectPrivate::setupBackendObject()
+{
+ Q_ASSERT(m_backendObject);
+
+ // set up attributes
+ const QList<EffectParameter> parameters = pINTERFACE_CALL(parameters());
+ for (int i = 0; i < parameters.count(); ++i) {
+ const EffectParameter &p = parameters.at(i);
+ pINTERFACE_CALL(setParameterValue(p, parameterValues[p]));
+ }
+}
+
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
+
+#include "moc_effect.cpp"
+
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/effect.h b/src/3rdparty/phonon/phonon/effect.h
new file mode 100644
index 0000000..e403482
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effect.h
@@ -0,0 +1,119 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef PHONON_EFFECT_H
+#define PHONON_EFFECT_H
+
+#include "phonondefs.h"
+#include <QtCore/QObject>
+#include "objectdescription.h"
+#include "medianode.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+class QString;
+template<class T> class QList;
+
+namespace Phonon
+{
+ class EffectParameter;
+ class EffectPrivate;
+
+ /** \class Effect effect.h Phonon/Effect
+ * \short Effects that can be inserted into a Path.
+ * An effect is a special object which can perform
+ * transformations on the specified path. Examples may include simple
+ * modifiers such as fading or pitch shifting, or more complex mathematical
+ * transformations.
+ *
+ * In order to use an effect, insert it into the path as follows:
+ * \code
+ * Path path = Phonon::createPath(...);
+ * Effect *effect = new Effect(this);
+ * path.insertEffect(effect);
+ * \endcode
+ *
+ * The effect will immediately begin applying it's transformations on
+ * the path. To stop it, remove the Effect from the path.
+ *
+ * \ingroup PhononEffects
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class PHONON_EXPORT Effect : public QObject, public MediaNode
+ {
+ Q_OBJECT
+ K_DECLARE_PRIVATE(Effect)
+
+ public:
+ ~Effect();
+
+//X enum Type {
+//X AudioEffect,
+//X VideoEffect
+//X };
+
+ /**
+ * QObject constructor.
+ *
+ * \param description An EffectDescription object to determine the
+ * type of effect. See BackendCapabilities::availableAudioEffects().
+ * \param parent QObject parent
+ */
+ explicit Effect(const EffectDescription &description, QObject *parent = 0);
+
+//X Type type() const;
+
+ /**
+ * Returns the description of this effect. This is the same type as was
+ * passed to the constructor.
+ */
+ EffectDescription description() const;
+
+ /**
+ * Returns a list of parameters that this effect provides to control
+ * its behaviour.
+ *
+ * \see EffectParameter
+ * \see EffectWidget
+ */
+ QList<EffectParameter> parameters() const;
+
+ QVariant parameterValue(const EffectParameter&) const;
+ void setParameterValue(const EffectParameter&, const QVariant &value);
+
+ protected:
+ Effect(EffectPrivate &dd, QObject *parent);
+ };
+} //namespace Phonon
+
+#endif // QT_NO_EFFECT
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // PHONON_EFFECT_H
+
diff --git a/src/3rdparty/phonon/phonon/effect_p.h b/src/3rdparty/phonon/phonon/effect_p.h
new file mode 100644
index 0000000..6cc42d9
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effect_p.h
@@ -0,0 +1,61 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef EFFECT_P_H
+#define EFFECT_P_H
+
+#include "effect.h"
+#include "effectparameter.h"
+#include "medianode_p.h"
+#include <QtCore/QHash>
+#include <QtCore/QVariant>
+#include "phonondefs_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+class EffectPrivate : public MediaNodePrivate
+{
+ Q_DECLARE_PUBLIC(Effect)
+ PHONON_PRIVATECLASS
+ public:
+ virtual QObject *qObject() { return q_func(); }
+ protected:
+ EffectPrivate()
+ {
+ }
+
+//X Effect::Type type;
+ EffectDescription description;
+ QHash<EffectParameter, QVariant> parameterValues;
+};
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_PHONON_EFFECT
+
+#endif // EFFECT_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/effectinterface.h b/src/3rdparty/phonon/phonon/effectinterface.h
new file mode 100644
index 0000000..59c69d9
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effectinterface.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_EFFECTINTERFACE_H
+#define PHONON_EFFECTINTERFACE_H
+
+#include "phononnamespace.h"
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+ class EffectParameter;
+ /** \class EffectInterface effectinterface.h Phonon/EffectInterface
+ * \short Interface for Effect objects
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class EffectInterface
+ {
+ public:
+ virtual ~EffectInterface() {}
+ /**
+ * Returns the EffectParameter objects to describe the parameters of this effect.
+ */
+ virtual QList<EffectParameter> parameters() const = 0;
+ /**
+ * Returns the value for the selected parameter.
+ */
+ virtual QVariant parameterValue(const EffectParameter &) const = 0;
+ /**
+ * Sets the value for the selected parameter.
+ */
+ virtual void setParameterValue(const EffectParameter &, const QVariant &newValue) = 0;
+ };
+} //namespace Phonon
+
+Q_DECLARE_INTERFACE(Phonon::EffectInterface, "EffectInterface0.phonon.kde.org")
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_EFFECTINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/effectparameter.cpp b/src/3rdparty/phonon/phonon/effectparameter.cpp
new file mode 100644
index 0000000..0447f5b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effectparameter.cpp
@@ -0,0 +1,142 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "effectparameter.h"
+#include "effectparameter_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+
+uint qHash(const Phonon::EffectParameter &param)
+{
+ return param.id();
+}
+
+EffectParameter::EffectParameter()
+ : d(new EffectParameterPrivate)
+{
+}
+
+EffectParameter::EffectParameter(int parameterId, const QString &name, Hints hints,
+ const QVariant &defaultValue, const QVariant &min, const QVariant &max,
+ const QVariantList &values, const QString &description)
+ : d(new EffectParameterPrivate)
+{
+ d->parameterId = parameterId;
+ d->min = min;
+ d->max = max;
+ d->defaultValue = defaultValue;
+ d->name = name;
+ d->possibleValues = values;
+ d->description = description;
+ d->hints = hints;
+}
+
+EffectParameter::~EffectParameter()
+{
+}
+
+EffectParameter::EffectParameter(const EffectParameter &rhs)
+ : d(rhs.d)
+{
+}
+
+EffectParameter &EffectParameter::operator=(const EffectParameter &rhs)
+{
+ d = rhs.d;
+ return *this;
+}
+
+bool EffectParameter::operator<(const EffectParameter &rhs) const
+{
+ return d->parameterId < rhs.d->parameterId;
+}
+
+bool EffectParameter::operator==(const EffectParameter &rhs) const
+{
+ return d->parameterId == rhs.d->parameterId;
+}
+
+bool EffectParameter::operator>(const EffectParameter &rhs) const
+{
+ return d->parameterId > rhs.d->parameterId;
+}
+
+const QString &EffectParameter::name() const
+{
+ return d->name;
+}
+
+const QString &EffectParameter::description() const
+{
+ return d->description;
+}
+
+bool EffectParameter::isLogarithmicControl() const
+{
+ return d->hints & LogarithmicHint;
+}
+
+QVariant::Type EffectParameter::type() const
+{
+ if (d->possibleValues.isEmpty()) {
+ return d->defaultValue.type();
+ }
+ return QVariant::String;
+}
+
+QVariantList EffectParameter::possibleValues() const
+{
+ return d->possibleValues;
+}
+
+QVariant EffectParameter::minimumValue() const
+{
+ return d->min;
+}
+
+QVariant EffectParameter::maximumValue() const
+{
+ return d->max;
+}
+
+QVariant EffectParameter::defaultValue() const
+{
+ return d->defaultValue;
+}
+
+int EffectParameter::id() const
+{
+ return d->parameterId;
+}
+
+}
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/effectparameter.h b/src/3rdparty/phonon/phonon/effectparameter.h
new file mode 100644
index 0000000..4471a16
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effectparameter.h
@@ -0,0 +1,237 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_EFFECTPARAMETER_H
+#define PHONON_EFFECTPARAMETER_H
+
+#include "phonon_export.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+
+class Effect;
+class EffectParameterPrivate;
+
+/** \class EffectParameter effectparameter.h Phonon/EffectParameter
+ * \brief This class describes one parameter of an effect.
+ *
+ * \ingroup PhononEffects
+ * \author Matthias Kretz <kretz@kde.org>
+ * \see Effect
+ */
+class PHONON_EXPORT EffectParameter
+{
+ friend class BrightnessControl;
+ public:
+ /**
+ * \internal
+ *
+ * Creates an invalid effect parameter.
+ */
+ EffectParameter();
+
+ /**
+ * The name of the parameter. Can be used as the label.
+ *
+ * \return A label for the parameter.
+ */
+ const QString &name() const;
+
+ /**
+ * The parameter may come with a description (LADSPA doesn't have a
+ * field for this, so don't expect many effects to provide a
+ * description).
+ *
+ * The description can be used for a tooltip or WhatsThis help.
+ *
+ * \return A text describing the parameter.
+ */
+ const QString &description() const;
+
+ /**
+ * Returns the parameter type.
+ *
+ * Common types are QVariant::Int, QVariant::Double, QVariant::Bool and QVariant::String. When
+ * QVariant::String is returned you get the possible values from possibleValues.
+ */
+ QVariant::Type type() const;
+
+ /**
+ * Returns whether the parameter should be
+ * displayed using a logarithmic scale. This is particularly useful for
+ * frequencies and gains.
+ */
+ bool isLogarithmicControl() const;
+
+ /**
+ * The minimum value to be used for the control to edit the parameter.
+ *
+ * If the returned QVariant is invalid the value is not bounded from
+ * below.
+ */
+ QVariant minimumValue() const;
+
+ /**
+ * The maximum value to be used for the control to edit the parameter.
+ *
+ * If the returned QVariant is invalid the value is not bounded from
+ * above.
+ */
+ QVariant maximumValue() const;
+
+ /**
+ * The default value.
+ */
+ QVariant defaultValue() const;
+
+ /**
+ * The possible values to be used for the control to edit the parameter.
+ *
+ * if the value of this parameter is to be picked from predefined values
+ * this returns the list (otherwise it returns an empty QVariantList).
+ */
+ QVariantList possibleValues() const;
+
+ /**
+ * \internal
+ * compares the ids of the parameters
+ */
+ bool operator<(const EffectParameter &rhs) const;
+
+ /**
+ * \internal
+ * compares the ids of the parameters
+ */
+ bool operator>(const EffectParameter &rhs) const;
+
+ /**
+ * \internal
+ * compares the ids of the parameters
+ */
+ bool operator==(const EffectParameter &rhs) const;
+
+ /* dtor, cctor and operator= for forward decl of EffectParameterPrivate */
+ ~EffectParameter();
+ EffectParameter(const EffectParameter &rhs);
+ EffectParameter &operator=(const EffectParameter &rhs);
+
+ /**
+ * Only for backend developers:
+ *
+ * Flags to set the return values of isToggleControl(),
+ * isLogarithmicControl(), isIntegerControl(), isBoundedBelow() and
+ * isBoundedAbove(). The values of the flags correspond to the values
+ * used for LADSPA effects.
+ */
+ enum Hint {
+ /**
+ * If this hint is set it means that
+ * the the control has only two states: zero and non-zero.
+ *
+ * \see isToggleControl()
+ */
+ ToggledHint = 0x04,
+
+ /* LADSPA's SAMPLE_RATE hint needs to be translated by the backend
+ * to normal bounds, as the backend knows the sample rate - and the
+ * frontend doesn't */
+
+ /**
+ * \see isLogarithmicControl()
+ */
+ LogarithmicHint = 0x10,
+ /**
+ * \see isIntegerControl
+ */
+ IntegerHint = 0x20
+ };
+ Q_DECLARE_FLAGS(Hints, Hint)
+
+ /**
+ * Only to be used by backend implementations:
+ *
+ * Creates a new effect parameter.
+ *
+ * \param parameterId This is a number to uniquely identify the
+ * parameter. The id is used for value() and setValue().
+ *
+ * \param name The name/label for this parameter.
+ *
+ * \param hints Sets the hints for the type of parameter.
+ *
+ * \param defaultValue The value that should be used as a default.
+ *
+ * \param min The minimum value allowed for this parameter. You only
+ * need to set this if the BoundedBelowHint is set.
+ *
+ * \param max The maximum value allowed for this parameter. You only
+ * need to set this if the BoundedAboveHint is set.
+ *
+ * \param description A descriptive text for the parameter
+ * (explaining what it controls) to be used as a tooltip or
+ * WhatsThis help.
+ */
+ EffectParameter(int parameterId, const QString &name, Hints hints,
+ const QVariant &defaultValue, const QVariant &min = QVariant(),
+ const QVariant &max = QVariant(), const QVariantList &values = QVariantList(),
+ const QString &description = QString());
+
+ /**
+ * \internal
+ *
+ * Returns the parameter's id.
+ */
+ int id() const;
+
+ protected:
+ /**
+ * The data is implicitly shared.
+ */
+ QExplicitlySharedDataPointer<EffectParameterPrivate> d;
+};
+
+uint PHONON_EXPORT qHash(const Phonon::EffectParameter &param);
+
+} // namespace Phonon
+
+#if defined(Q_CC_MSVC) && _MSC_VER <= 1300
+//this ensures that code outside Phonon can use the hash function
+//it also a workaround for some compilers
+inline uint qHash(const Phonon::EffectParameter &param) { return Phonon::qHash(param); } //krazy:exclude=inline
+#endif
+Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::EffectParameter::Hints)
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_EFFECTPARAMETER_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/effectparameter_p.h b/src/3rdparty/phonon/phonon/effectparameter_p.h
new file mode 100644
index 0000000..f3f9f88
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effectparameter_p.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef EFFECTPARAMETER_P_H
+#define EFFECTPARAMETER_P_H
+
+#include "effectparameter.h"
+#include <QtCore/QSharedData>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECT
+
+namespace Phonon
+{
+
+class EffectParameterPrivate : public QSharedData
+{
+ public:
+ int parameterId;
+ QVariant min;
+ QVariant max;
+ QVariant defaultValue;
+ QString name;
+ QString description;
+ QVariantList possibleValues;
+ EffectParameter::Hints hints;
+};
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_EFFECT
+
+QT_END_NAMESPACE
+
+#endif // EFFECTPARAMETER_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/effectwidget.cpp b/src/3rdparty/phonon/phonon/effectwidget.cpp
new file mode 100644
index 0000000..edcbe1f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effectwidget.cpp
@@ -0,0 +1,259 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "effectwidget.h"
+#include "effectwidget_p.h"
+
+#include <QtCore/QtAlgorithms>
+#include <QtCore/QList>
+
+#include "effect.h"
+#include "effectparameter.h"
+#include "phonondefs_p.h"
+#include <QtGui/QBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QSpinBox>
+#include <QtGui/QCheckBox>
+#include <QtGui/QComboBox>
+#include <QtGui/QSlider>
+#include <limits>
+
+#ifdef min
+#undef min
+#endif
+#ifdef max
+#undef max
+#endif
+static const qreal DEFAULT_MIN = std::numeric_limits<qreal>::min();
+static const qreal DEFAULT_MAX = std::numeric_limits<qreal>::max();
+static const int DEFAULT_MIN_INT = std::numeric_limits<int>::min();
+static const int DEFAULT_MAX_INT = std::numeric_limits<int>::max();
+static const int SLIDER_RANGE = 8;
+static const int TICKINTERVAL = 4;
+
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECTWIDGET
+
+namespace Phonon
+{
+
+EffectWidget::EffectWidget(Effect *effect, QWidget *parent)
+ : QWidget(parent),
+ k_ptr(new EffectWidgetPrivate(effect))
+{
+ K_D(EffectWidget);
+ d->q_ptr = this;
+ d->autogenerateUi();
+}
+
+EffectWidget::~EffectWidget()
+{
+ delete k_ptr;
+}
+
+/*
+EffectWidget::EffectWidget(EffectWidgetPrivate &dd, QWidget *parent)
+ : QWidget(parent)
+ , k_ptr(&dd)
+{
+ K_D(EffectWidget);
+ d->q_ptr = this;
+ d->autogenerateUi();
+}
+*/
+
+EffectWidgetPrivate::EffectWidgetPrivate(Effect *e)
+ : effect(e)
+{
+ //TODO: look up whether there is a specialized widget for this effect. This
+ //could be a DSO or a Designer ui file found via KTrader.
+ //
+ //if no specialized widget is available:
+}
+
+void EffectWidgetPrivate::autogenerateUi()
+{
+ Q_Q(EffectWidget);
+ QVBoxLayout *mainLayout = new QVBoxLayout(q);
+ mainLayout->setMargin(0);
+ const QList<Phonon::EffectParameter> parameters = effect->parameters();
+ for (int i = 0; i < parameters.count(); ++i) {
+ const EffectParameter &para = parameters.at(i);
+ QVariant value = effect->parameterValue(para);
+ QHBoxLayout *pLayout = new QHBoxLayout;
+ mainLayout->addLayout(pLayout);
+
+ QLabel *label = new QLabel(q);
+ pLayout->addWidget(label);
+ label->setText(para.name());
+#ifndef QT_NO_TOOLTIP
+ label->setToolTip(para.description());
+#endif
+
+ QWidget *control = 0;
+ switch (int(para.type())) {
+ case QVariant::String:
+ {
+ QComboBox *cb = new QComboBox(q);
+ control = cb;
+ if (value.type() == QVariant::Int) {
+ //value just defines the item index
+ for (int i = 0; i < para.possibleValues().count(); ++i) {
+ cb->addItem(para.possibleValues().at(i).toString());
+ }
+ cb->setCurrentIndex(value.toInt());
+ QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int)));
+ } else {
+ for (int i = 0; i < para.possibleValues().count(); ++i) {
+ const QVariant &item = para.possibleValues().at(i);
+ cb->addItem(item.toString());
+ if (item == value) {
+ cb->setCurrentIndex(cb->count() - 1);
+ }
+ }
+ QObject::connect(cb, SIGNAL(currentIndexChanged(QString)), q, SLOT(_k_setStringParameter(QString)));
+ }
+ }
+ break;
+ case QVariant::Bool:
+ {
+ QCheckBox *cb = new QCheckBox(q);
+ control = cb;
+ cb->setChecked(value.toBool());
+ QObject::connect(cb, SIGNAL(toggled(bool)), q, SLOT(_k_setToggleParameter(bool)));
+ }
+ break;
+ case QVariant::Int:
+ {
+ QSpinBox *sb = new QSpinBox(q);
+ control = sb;
+ bool minValueOk = false;
+ bool maxValueOk = false;
+ const int minValue = para.minimumValue().toInt(&minValueOk);
+ const int maxValue = para.maximumValue().toInt(&maxValueOk);
+
+ sb->setRange(minValueOk ? minValue : DEFAULT_MIN_INT, maxValueOk ? maxValue : DEFAULT_MAX_INT);
+ sb->setValue(value.toInt());
+ QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int)));
+ }
+ break;
+ case QMetaType::Float:
+ case QVariant::Double:
+ {
+ const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ?
+ para.minimumValue().toReal() : DEFAULT_MIN;
+ const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ?
+ para.maximumValue().toReal() : DEFAULT_MAX;
+
+ if (minValue == -1. && maxValue == 1.) {
+ //Special case values between -1 and 1.0 to use a slider for improved usability
+ QSlider *slider = new QSlider(Qt::Horizontal, q);
+ control = slider;
+ slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE);
+ slider->setValue(int(SLIDER_RANGE * value.toReal()));
+ slider->setTickPosition(QSlider::TicksBelow);
+ slider->setTickInterval(TICKINTERVAL);
+ QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int)));
+ } else {
+ double step = 0.1;
+ if (qAbs(maxValue - minValue) > 50)
+ step = 1.0;
+ QDoubleSpinBox *sb = new QDoubleSpinBox(q);
+ control = sb;
+ sb->setRange(minValue, maxValue);
+ sb->setValue(value.toDouble());
+ sb->setSingleStep(step);
+ QObject::connect(sb, SIGNAL(valueChanged(double)), q,
+ SLOT(_k_setDoubleParameter(double)));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (control) {
+#ifndef QT_NO_TOOLTIP
+ control->setToolTip(para.description());
+#endif
+#ifndef QT_NO_SHORTCUT
+ label->setBuddy(control);
+#endif
+ pLayout->addWidget(control);
+ parameterForObject.insert(control, para);
+ }
+ }
+}
+
+void EffectWidgetPrivate::_k_setToggleParameter(bool checked)
+{
+ Q_Q(EffectWidget);
+ if (parameterForObject.contains(q->sender())) {
+ effect->setParameterValue(parameterForObject[q->sender()], checked);
+ }
+}
+
+void EffectWidgetPrivate::_k_setIntParameter(int value)
+{
+ Q_Q(EffectWidget);
+ if (parameterForObject.contains(q->sender())) {
+ effect->setParameterValue(parameterForObject[q->sender()], value);
+ }
+}
+
+void EffectWidgetPrivate::_k_setDoubleParameter(double value)
+{
+ Q_Q(EffectWidget);
+ if (parameterForObject.contains(q->sender())) {
+ effect->setParameterValue(parameterForObject[q->sender()], value);
+ }
+}
+
+void EffectWidgetPrivate::_k_setStringParameter(const QString &value)
+{
+ Q_Q(EffectWidget);
+ if (parameterForObject.contains(q->sender())) {
+ effect->setParameterValue(parameterForObject[q->sender()], value);
+ }
+}
+
+void EffectWidgetPrivate::_k_setSliderParameter(int value)
+{
+ Q_Q(EffectWidget);
+ if (parameterForObject.contains(q->sender())) {
+ effect->setParameterValue(parameterForObject[q->sender()], double(value) / double(SLIDER_RANGE));
+ }
+}
+
+
+} // namespace Phonon
+
+
+#endif // QT_NO_PHONON_EFFECTWIDGET
+
+QT_END_NAMESPACE
+
+#include "moc_effectwidget.cpp"
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/effectwidget.h b/src/3rdparty/phonon/phonon/effectwidget.h
new file mode 100644
index 0000000..17a310f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effectwidget.h
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_UI_EFFECTWIDGET_H
+#define PHONON_UI_EFFECTWIDGET_H
+
+#include "phonon_export.h"
+#include "phonondefs.h"
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECTWIDGET
+
+namespace Phonon
+{
+class Effect;
+
+ class EffectWidgetPrivate;
+
+ /** \class EffectWidget effectwidget.h Phonon/EffectWidget
+ * \brief Widget to control the parameters of an Effect.
+ *
+ * \ingroup PhononWidgets
+ * \ingroup PhononEffects
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class PHONON_EXPORT EffectWidget : public QWidget
+ {
+ Q_OBJECT
+ K_DECLARE_PRIVATE(EffectWidget)
+ public:
+ explicit EffectWidget(Effect *effect, QWidget *parent = 0);
+ ~EffectWidget();
+
+ protected:
+ //EffectWidget(EffectWidgetPrivate &dd, QWidget *parent);
+ EffectWidgetPrivate *const k_ptr;
+
+ private:
+ Q_PRIVATE_SLOT(k_func(), void _k_setToggleParameter(bool checked))
+ Q_PRIVATE_SLOT(k_func(), void _k_setIntParameter(int value))
+ Q_PRIVATE_SLOT(k_func(), void _k_setDoubleParameter(double value))
+ Q_PRIVATE_SLOT(k_func(), void _k_setStringParameter(const QString &))
+ Q_PRIVATE_SLOT(k_func(), void _k_setSliderParameter(int))
+ };
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_EFFECTWIDGET
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_UI_EFFECTWIDGET_H
+
+// vim: sw=4 ts=4 tw=100
diff --git a/src/3rdparty/phonon/phonon/effectwidget_p.h b/src/3rdparty/phonon/phonon/effectwidget_p.h
new file mode 100644
index 0000000..aad422a
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/effectwidget_p.h
@@ -0,0 +1,64 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_UI_EFFECTWIDGET_P_H
+#define PHONON_UI_EFFECTWIDGET_P_H
+
+#include "effectwidget.h"
+#include "effectparameter.h"
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_EFFECTWIDGET
+
+namespace Phonon
+{
+ class EffectWidgetPrivate
+ {
+ Q_DECLARE_PUBLIC(EffectWidget)
+ protected:
+ EffectWidgetPrivate(Effect *effect);
+
+ EffectWidget *q_ptr;
+
+ private:
+ Effect *effect;
+ QHash<QObject *, EffectParameter> parameterForObject;
+
+ void _k_setToggleParameter(bool checked);
+ void _k_setIntParameter(int value);
+ void _k_setDoubleParameter(double value);
+ void _k_setStringParameter(const QString &);
+ void _k_setSliderParameter(int);
+
+ void autogenerateUi();
+ };
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_EFFECTWIDGET
+
+QT_END_NAMESPACE
+
+#endif // PHONON_UI_EFFECTWIDGET_P_H
+
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/extractmethodcalls.rb b/src/3rdparty/phonon/phonon/extractmethodcalls.rb
new file mode 100755
index 0000000..9100489
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/extractmethodcalls.rb
@@ -0,0 +1,527 @@
+#!/usr/bin/ruby
+
+class MethodDef
+ def initialize(returnType, signature, optional)
+ @returnType = returnType
+ @signature = signature
+ @optional = optional
+ end
+
+ attr_reader :returnType, :signature, :optional
+ attr_writer :optional
+end
+
+class SignalDef
+ def initialize(signature)
+ @signature = signature
+ end
+
+ attr_reader :signature
+end
+
+class Parser
+ def initialize(filename)
+ @file = File.new filename, "r"
+ @signatures = Hash.new
+ parse
+ end
+
+ attr_reader :signatures
+
+ private
+ def addSignal(signature)
+ unless @signatures.include? signature
+ @signatures[signature] = SignalDef.new(signature)
+ end
+ end
+
+ def addMethod(returnType, signature, optional)
+ if @signatures.include? signature
+ if returnType != ''
+ if @signatures[signature].returnType == ''
+ optional = false if @signatures[signature].optional == false
+ @signatures[signature] = MethodDef.new(returnType, signature, optional)
+ elsif @signatures[signature].returnType != returnType
+ fail "same signature '#{signature}' but differing return types: #{returnType} and #{@signatures[signature].returnType}"
+ end
+ elsif not optional and @signatures[signature].optional
+ @signatures[signature].optional = false
+ end
+ else
+ @signatures[signature] = MethodDef.new(returnType, signature, optional)
+ end
+ end
+
+ PARSER_RETURN_TYPE = 0
+ PARSER_RETURN_VAR = 1
+ PARSER_METHOD_NAME = 2
+ PARSER_ARGUMENT_TYPE = 3
+ PARSER_ARGUMENT_VAR = 4
+
+ PARSER2_CLASSNAME = 0
+ PARSER2_METHODPREFIX = 1
+
+ PARSER3_QMETAOBJECT = 0
+ PARSER3_SCOPEDELIMIT = 1
+ PARSER3_INVOKEMETHOD = 2
+ PARSER3_OPENPARENTH = 3
+ PARSER3_BACKENDOBJ = 4
+ PARSER3_METHODNAME = 5
+ PARSER3_CONNECTION = 6
+ PARSER3_RET_OR_ARG = 7
+ PARSER3_RET_OPEN = 8
+ PARSER3_RET_TYPE = 9
+ PARSER3_RET_NAME = 10
+ PARSER3_RET_CLOSE = 11
+ PARSER3_ARG = 12
+ PARSER3_ARG_OPEN = 13
+ PARSER3_ARG_TYPE = 14
+ PARSER3_ARG_NAME = 15
+ PARSER3_ARG_CLOSE = 16
+ PARSER3_CLOSE = 17
+ PARSER3_DONE = 18
+
+ PARSER4_OPENING_PAREN = 0
+ PARSER4_SENDER = 1
+ PARSER4_PRIVATE_SENDER = 2
+ PARSER4_COMMA_1 = 3
+ PARSER4_SIGNAL_MACRO = 4
+ PARSER4_SIGNAL_OPENING_PAREN = 5
+ PARSER4_SIGNAL_SIGNATURE = 6
+ PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN = 7
+ PARSER4_SIGNAL_SIGNATURE_CONST = 8
+ PARSER4_SIGNAL_SIGNATURE_TYPE1 = 9
+ PARSER4_SIGNAL_SIGNATURE_TYPE2_1 = 10
+ PARSER4_SIGNAL_SIGNATURE_TYPE2_2 = 11
+ PARSER4_SIGNAL_CLOSING_PAREN = 12
+
+ def parse
+ inbackendcall = false
+ innamedescriptioncall = false
+ ininvokemethodcall = false
+ invokemethodcallOnBackendObject = false
+ inconnect = false
+ optionalmethod = false
+ lasttoken = ';'
+ thistoken = ';'
+ returnType = String.new
+ signature = String.new
+ parserstate = PARSER_RETURN_TYPE
+ depth = 0
+ tokenize do |token|
+ #STDERR.puts token
+ lasttoken = thistoken
+ thistoken = token
+ token = token[1..-1] if token[0,9] == "pBACKEND_"
+ if token[0,8] == "BACKEND_"
+ fail if innamedescriptioncall
+ fail if inbackendcall
+ fail if ininvokemethodcall
+ fail if inconnect
+ inbackendcall = true
+ if token[8,3] != "GET" # skip return arg
+ parserstate = PARSER_METHOD_NAME
+ returnType = ''
+ else
+ parserstate = PARSER_RETURN_TYPE
+ end
+ elsif token == 'NAMEDESCRIPTIONFROMINDEX'
+ fail if innamedescriptioncall
+ fail if inbackendcall
+ fail if ininvokemethodcall
+ fail if inconnect
+ innamedescriptioncall = true
+ parserstate = PARSER2_CLASSNAME
+ elsif token == 'QMetaObject'
+ fail if innamedescriptioncall
+ fail if inbackendcall
+ fail if ininvokemethodcall
+ fail if inconnect
+ ininvokemethodcall = true
+ parserstate = PARSER3_SCOPEDELIMIT
+ optionalmethod = (lasttoken[-1,1] == '=' or lasttoken == '(' or lasttoken == '!') ? true : false
+ elsif token == 'connect'
+ fail if innamedescriptioncall
+ fail if inbackendcall
+ fail if ininvokemethodcall
+ fail if inconnect
+ inconnect = true
+ parserstate = PARSER4_OPENING_PAREN
+ elsif inconnect
+ #puts "state = #{parserstate}, token = #{token}"
+ lastparserstate = parserstate
+ case parserstate
+ when PARSER4_OPENING_PAREN
+ parserstate = PARSER4_SENDER if token == '('
+ when PARSER4_SENDER
+ # d->m_backendObject or only m_backendObject
+ parserstate = PARSER4_COMMA_1 if token == 'm_backendObject'
+ parserstate = PARSER4_PRIVATE_SENDER if token == 'd'
+ when PARSER4_PRIVATE_SENDER
+ parserstate = PARSER4_SENDER if token == '->'
+ when PARSER4_COMMA_1
+ parserstate = PARSER4_SIGNAL_MACRO if token == ','
+ when PARSER4_SIGNAL_MACRO
+ parserstate = PARSER4_SIGNAL_OPENING_PAREN if token == 'SIGNAL'
+ when PARSER4_SIGNAL_OPENING_PAREN
+ parserstate = PARSER4_SIGNAL_SIGNATURE if token == '('
+ when PARSER4_SIGNAL_SIGNATURE
+ signature = token
+ parserstate = PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN
+ when PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN
+ case token
+ when '('
+ signature += '('
+ parserstate = PARSER4_SIGNAL_SIGNATURE_CONST
+ when '()'
+ signature += '()'
+ parserstate = PARSER4_SIGNAL_CLOSING_PAREN
+ end
+ when PARSER4_SIGNAL_SIGNATURE_CONST
+ case token
+ when 'const'
+ signature += 'const '
+ parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1
+ when ')'
+ signature += ')'
+ parserstate = PARSER4_SIGNAL_CLOSING_PAREN
+ else
+ signature += token
+ parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1
+ end
+ when PARSER4_SIGNAL_SIGNATURE_TYPE1
+ case token
+ when 'const'
+ when ')'
+ else
+ signature += token
+ parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1
+ end
+ when PARSER4_SIGNAL_SIGNATURE_TYPE2_1
+ case token
+ when ','
+ signature += ', '
+ parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1
+ when ')'
+ signature += ')'
+ parserstate = PARSER4_SIGNAL_CLOSING_PAREN
+ else
+ signature += token
+ parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_2
+ end
+ when PARSER4_SIGNAL_SIGNATURE_TYPE2_2
+ case token
+ when ','
+ signature += ', '
+ parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1
+ when ')'
+ signature += ')'
+ parserstate = PARSER4_SIGNAL_CLOSING_PAREN
+ else
+ signature += token
+ parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1
+ end
+ when PARSER4_SIGNAL_CLOSING_PAREN
+ addSignal(signature) if token == ')'
+ end
+ if parserstate == lastparserstate
+ inconnect = false
+ signature = String.new
+ end
+ elsif ininvokemethodcall
+ case parserstate
+ when PARSER3_BACKENDOBJ
+ if token == ','
+ if invokemethodcallOnBackendObject
+ parserstate += 1
+ else
+ ininvokemethodcall = false
+ end
+ elsif token =~ /backendObject/
+ invokemethodcallOnBackendObject = true
+ end
+ when PARSER3_SCOPEDELIMIT
+ if token == '::'
+ parserstate += 1
+ else
+ ininvokemethodcall = false
+ end
+ when PARSER3_INVOKEMETHOD
+ if token == 'invokeMethod'
+ parserstate += 1
+ else
+ ininvokemethodcall = false
+ end
+ when PARSER3_OPENPARENTH
+ fail if token != '('
+ parserstate += 1
+ invokemethodcallOnBackendObject = false
+ when PARSER3_METHODNAME
+ case token
+ when ','
+ signature += '('
+ parserstate = PARSER3_CONNECTION
+ else
+ fail if signature.length > 0
+ signature = token[1..-2]
+ end
+ when PARSER3_CONNECTION
+ case token
+ when ','
+ parserstate = PARSER3_RET_OR_ARG
+ when ')'
+ parserstate = PARSER3_CLOSE
+# the connection is optional
+ when 'Q_RETURN_ARG'
+ parserstate = PARSER3_RET_OPEN
+ when 'Q_ARG'
+ returnType = ''
+ parserstate = PARSER3_ARG_OPEN
+ end
+ when PARSER3_RET_OR_ARG
+ if token == 'Q_RETURN_ARG'
+ parserstate = PARSER3_RET_OPEN
+ elsif token == 'Q_ARG'
+ returnType = ''
+ parserstate = PARSER3_ARG_OPEN
+ else
+ fail "unexpected token '#{token}"
+ end
+ when PARSER3_RET_TYPE
+ if token == ','
+ parserstate += 1
+ else
+ if token == '*' or token == '&' or token == '<' or token == '>' or token == '::' or returnType.empty? or returnType[-1,1] == '<' or returnType[-2,2] == '::'
+ returnType += token
+ else
+ returnType += ' ' + token
+ end
+ end
+ when PARSER3_RET_NAME
+ parserstate = PARSER3_RET_CLOSE if token == ')'
+ when PARSER3_RET_CLOSE
+ case token
+ when ')'
+ parserstate = PARSER3_CLOSE
+ when ','
+ parserstate = PARSER3_ARG
+ end
+ when PARSER3_ARG
+ if token == 'Q_ARG'
+ parserstate = PARSER3_ARG_OPEN
+ else
+ fail "unexpected token '#{token}"
+ end
+ when PARSER3_ARG_TYPE
+ if token == ','
+ parserstate += 1
+ else
+ signature += ' ' if signature[-1,1] =~ /\w/ and token[0,1] =~ /\w/
+ signature += token
+ end
+ when PARSER3_ARG_NAME
+ case token
+ when '('
+ depth += 1
+ when ')'
+ if depth == 0
+ parserstate = PARSER3_ARG_CLOSE
+ else
+ depth -= 1
+ end
+ end
+ when PARSER3_ARG_CLOSE
+ case token
+ when ','
+ signature += ','
+ parserstate = PARSER3_ARG
+ when ')'
+ parserstate = PARSER3_CLOSE
+ else
+ fail
+ end
+ when PARSER3_ARG_OPEN, PARSER3_RET_OPEN
+ fail if token != '('
+ parserstate += 1
+ when PARSER3_CLOSE
+ signature += ')'
+ addMethod returnType, signature, optionalmethod
+ ininvokemethodcall = false
+ returnType = String.new
+ signature = String.new
+ end
+ elsif innamedescriptioncall
+ case parserstate
+ when PARSER2_CLASSNAME
+ parserstate = PARSER2_METHODPREFIX if token == ','
+ when PARSER2_METHODPREFIX
+ addMethod 'QSet<int>', token + 'Indexes()', false
+ addMethod 'int', token + 'Name()', false
+ addMethod 'int', token + 'Description()', false
+ innamedescriptioncall = false
+ end
+ elsif inbackendcall
+ next if token == '(' # skip (
+ if token == ';'
+ if signature.length > 0
+ signature += ')'
+ addMethod returnType, signature, false
+ signature = String.new
+ returnType = String.new
+ end
+ inbackendcall = false
+ else
+ if token == ','
+ if parserstate == PARSER_ARGUMENT_VAR
+ signature += ','
+ parserstate = PARSER_ARGUMENT_TYPE
+ else
+ parserstate += 1
+ end
+ next
+ end
+ case parserstate
+ when PARSER_RETURN_TYPE
+ returnType += token
+ when PARSER_RETURN_VAR
+ when PARSER_METHOD_NAME
+ next if token == ')'
+ fail if token[0,1] != '"' or token[-1,1] != '"'
+ fail if signature.length > 0
+ signature = token[1..-2] + '('
+ when PARSER_ARGUMENT_TYPE
+ signature += token
+ end
+ end
+ end
+ end
+ end
+
+ def tokenize
+ incomment = false
+ instring = false
+ laststring = ''
+ linenum = 0
+ @file.each_line do |line|
+ linenum += 1
+ line.strip!
+ next if line[0..1] == "//"
+ next if line[0,1] == "#" # ignore preprocessor statements
+ line.split(/(\b|\s+)/).each do |token|
+ #STDERR.puts "string: #{instring} comment: #{incomment} token: '#{token}'"
+ if instring
+ indexOfEscapedQuote = token.index '\\"'
+ if indexOfEscapedQuote != nil
+ laststring += token
+ next
+ end
+ indexOfQuote = token.index '"'
+ if indexOfQuote and indexOfQuote > 0
+ fail if token[indexOfQuote-1,1] == '\\'
+ laststring += token[0..indexOfQuote-1]
+ token = token[indexOfQuote..-1]
+ end
+ if token[0,2] == '""'
+ laststring += token[2..-1]
+ next
+ elsif token[0,1] == '"'
+ if laststring[-1,1] == '\\'
+ laststring[-1,1] = '"'
+ laststring += token[1..-1]
+ next
+ end
+ instring = false
+ yield laststring + '"'
+ token = token[1..-1]
+ else
+ laststring += token
+ next
+ end
+ end
+ token.strip!
+ next if token.empty?
+ if incomment
+ incomment = false if token[0..1] == "*/"
+ next
+ else
+ if token[0..1] == "/*"
+ incomment = true
+ next
+ end
+ break if token == "//"
+ end
+ doublequote = token.index '""'
+ if doublequote != nil
+ if doublequote > 0
+ yield token[0,doublequote]
+ end
+ yield '""'
+ if token.length > doublequote+2
+ token = token[doublequote+2..-1]
+ else
+ next
+ end
+ end
+ quote = token.index '"'
+ if quote != nil
+ laststring = token[quote..-1]
+ instring = true
+ if quote > 0
+ token = token[0,quote]
+ else
+ next
+ end
+ end
+ semicolon = token.index ';'
+ if not semicolon
+ tokenize2(token) { |i| yield i }
+ elsif semicolon > 0
+ tokenize2(token[0..semicolon-1]) { |i| yield i }
+ yield ';'
+ if token.length > semicolon + 1
+ tokenize2(token[semicolon+1..-1]) { |i| yield i }
+ end
+ elsif (semicolon == 0 and token.length > 1)
+ yield ';'
+ tokenize2(token[1..-1]) { |i| yield i }
+ else
+ yield token # a single ;
+ end
+ end
+ end
+ end
+
+ def tokenize2(token)
+ if token.length > 1
+ #STDERR.puts "long token: #{token}"
+ while token[0,1] == '(' or token[0,1] == ')' or token[0,1] == "'" or token[0,1] == '&'
+ yield token[0,1]
+ token = token[1..-1]
+ #STDERR.puts "less long token: #{token}"
+ end
+ return if token.empty?
+ if token.length == 1
+ yield token
+ return
+ elsif token[-1,1] == ',' or token[-1,1] == "'"
+ yield token[0..-2]
+ yield token[-1,1]
+ return
+ end
+ end
+ yield token
+ end
+end
+
+p = Parser.new ARGV[0]
+p.signatures.each do |signature,method|
+ if method.class == SignalDef
+ puts "addSignal(\"#{signature}\");"
+ else
+ if method.optional
+ puts "addMethod(\"#{method.returnType}\", \"#{signature}\", true);"
+ else
+ puts "addMethod(\"#{method.returnType}\", \"#{signature}\");"
+ end
+ end
+end
diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp
new file mode 100644
index 0000000..b5e565b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/factory.cpp
@@ -0,0 +1,474 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "factory_p.h"
+
+#include "backendinterface.h"
+#include "medianode_p.h"
+#include "mediaobject.h"
+#include "audiooutput.h"
+#include "globalstatic_p.h"
+#include "objectdescription.h"
+#include "platformplugin.h"
+#include "phononnamespace_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QList>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QPointer>
+#ifndef QT_NO_DBUS
+#include <QtDBus/QtDBus>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+class PlatformPlugin;
+class FactoryPrivate : public Phonon::Factory::Sender
+{
+ friend QObject *Factory::backend(bool);
+ Q_OBJECT
+ public:
+ FactoryPrivate();
+ ~FactoryPrivate();
+ bool createBackend();
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ PlatformPlugin *platformPlugin();
+
+ PlatformPlugin *m_platformPlugin;
+ bool m_noPlatformPlugin;
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ QPointer<QObject> m_backendObject;
+
+ QList<QObject *> objects;
+ QList<MediaNodePrivate *> mediaNodePrivateList;
+
+ private Q_SLOTS:
+ /**
+ * This is called via DBUS when the user changes the Phonon Backend.
+ */
+#ifndef QT_NO_DBUS
+ void phononBackendChanged();
+#endif //QT_NO_DBUS
+
+ /**
+ * unregisters the backend object
+ */
+ void objectDestroyed(QObject *);
+
+ void objectDescriptionChanged(ObjectDescriptionType);
+};
+
+PHONON_GLOBAL_STATIC(Phonon::FactoryPrivate, globalFactory)
+
+static inline void ensureLibraryPathSet()
+{
+#ifdef PHONON_LIBRARY_PATH
+ static bool done = false;
+ if (!done) {
+ done = true;
+ QCoreApplication::addLibraryPath(QLatin1String(PHONON_LIBRARY_PATH));
+ }
+#endif // PHONON_LIBRARY_PATH
+}
+
+void Factory::setBackend(QObject *b)
+{
+ Q_ASSERT(globalFactory->m_backendObject == 0);
+ globalFactory->m_backendObject = b;
+}
+
+/*void Factory::createBackend(const QString &library, const QString &version)
+{
+ Q_ASSERT(globalFactory->m_backendObject == 0);
+ PlatformPlugin *f = globalFactory->platformPlugin();
+ if (f) {
+ globalFactory->m_backendObject = f->createBackend(library, version);
+ }
+}*/
+
+bool FactoryPrivate::createBackend()
+{
+#ifndef QT_NO_LIBRARY
+ Q_ASSERT(m_backendObject == 0);
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ PlatformPlugin *f = globalFactory->platformPlugin();
+ if (f) {
+ m_backendObject = f->createBackend();
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ if (!m_backendObject) {
+ ensureLibraryPathSet();
+
+ // could not load a backend through the platform plugin. Falling back to the default
+ // (finding the first loadable backend).
+ const QLatin1String suffix("/phonon_backend/");
+ const QStringList paths = QCoreApplication::libraryPaths();
+ for (int i = 0; i < paths.count(); ++i) {
+ const QString libPath = paths.at(i) + suffix;
+ const QDir dir(libPath);
+ if (!dir.exists()) {
+ pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist";
+ continue;
+ }
+
+ QStringList plugins(dir.entryList(QDir::Files));
+
+#ifdef Q_OS_SYMBIAN
+ static const QString preferredPluginName = QLatin1String("phonon_mmf");
+ const int preferredPluginIndex = plugins.indexOf(preferredPluginName + ".qtplugin");
+ if (preferredPluginIndex != -1)
+ plugins.move(preferredPluginIndex, 0);
+#endif
+
+ const QStringList files = dir.entryList(QDir::Files);
+ for (int i = 0; i < plugins.count(); ++i) {
+ QPluginLoader pluginLoader(libPath + plugins.at(i));
+ if (!pluginLoader.load()) {
+ pDebug() << Q_FUNC_INFO << " load failed:"
+ << pluginLoader.errorString();
+ continue;
+ }
+ pDebug() << pluginLoader.instance();
+ m_backendObject = pluginLoader.instance();
+ if (m_backendObject) {
+ break;
+ }
+
+ // no backend found, don't leave an unused plugin in memory
+ pluginLoader.unload();
+ }
+
+ if (m_backendObject) {
+ break;
+ }
+ }
+ if (!m_backendObject) {
+ pWarning() << Q_FUNC_INFO << "phonon backend plugin could not be loaded";
+ return false;
+ }
+ }
+
+ connect(m_backendObject, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
+ SLOT(objectDescriptionChanged(ObjectDescriptionType)));
+
+ return true;
+#else //QT_NO_LIBRARY
+ pWarning() << Q_FUNC_INFO << "Trying to use Phonon with QT_NO_LIBRARY defined. "
+ "That is currently not supported";
+ return false;
+#endif
+}
+
+FactoryPrivate::FactoryPrivate()
+ :
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ m_platformPlugin(0),
+ m_noPlatformPlugin(false),
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ m_backendObject(0)
+{
+ // Add the post routine to make sure that all other global statics (especially the ones from Qt)
+ // are still available. If the FactoryPrivate dtor is called too late many bad things can happen
+ // as the whole backend might still be alive.
+ qAddPostRoutine(globalFactory.destroy);
+#ifndef QT_NO_DBUS
+ QDBusConnection::sessionBus().connect(QString(), QString(), QLatin1String("org.kde.Phonon.Factory"),
+ QLatin1String("phononBackendChanged"), this, SLOT(phononBackendChanged()));
+#endif
+}
+
+FactoryPrivate::~FactoryPrivate()
+{
+ for (int i = 0; i < mediaNodePrivateList.count(); ++i) {
+ mediaNodePrivateList.at(i)->deleteBackendObject();
+ }
+ if (objects.size() > 0) {
+ pError() << "The backend objects are not deleted as was requested.";
+ qDeleteAll(objects);
+ }
+ delete m_backendObject;
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ delete m_platformPlugin;
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+}
+
+void FactoryPrivate::objectDescriptionChanged(ObjectDescriptionType type)
+{
+#ifdef PHONON_METHODTEST
+ Q_UNUSED(type);
+#else
+ pDebug() << Q_FUNC_INFO << type;
+ switch (type) {
+ case AudioOutputDeviceType:
+ emit availableAudioOutputDevicesChanged();
+ break;
+ case AudioCaptureDeviceType:
+ emit availableAudioCaptureDevicesChanged();
+ break;
+ default:
+ break;
+ }
+ //emit capabilitiesChanged();
+#endif // PHONON_METHODTEST
+}
+
+Factory::Sender *Factory::sender()
+{
+ return globalFactory;
+}
+
+bool Factory::isMimeTypeAvailable(const QString &mimeType)
+{
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ PlatformPlugin *f = globalFactory->platformPlugin();
+ if (f) {
+ return f->isMimeTypeAvailable(mimeType);
+ }
+#else
+ Q_UNUSED(mimeType);
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ return true; // the MIME type might be supported, let BackendCapabilities find out
+}
+
+void Factory::registerFrontendObject(MediaNodePrivate *bp)
+{
+ globalFactory->mediaNodePrivateList.prepend(bp); // inserted last => deleted first
+}
+
+void Factory::deregisterFrontendObject(MediaNodePrivate *bp)
+{
+ // The Factory can already be cleaned up while there are other frontend objects still alive.
+ // When those are deleted they'll call deregisterFrontendObject through ~BasePrivate
+ if (!globalFactory.isDestroyed()) {
+ globalFactory->mediaNodePrivateList.removeAll(bp);
+ }
+}
+
+#ifndef QT_NO_DBUS
+void FactoryPrivate::phononBackendChanged()
+{
+ if (m_backendObject) {
+ for (int i = 0; i < mediaNodePrivateList.count(); ++i) {
+ mediaNodePrivateList.at(i)->deleteBackendObject();
+ }
+ if (objects.size() > 0) {
+ pDebug() << "WARNING: we were asked to change the backend but the application did\n"
+ "not free all references to objects created by the factory. Therefore we can not\n"
+ "change the backend without crashing. Now we have to wait for a restart to make\n"
+ "backendswitching possible.";
+ // in case there were objects deleted give 'em a chance to recreate
+ // them now
+ for (int i = 0; i < mediaNodePrivateList.count(); ++i) {
+ mediaNodePrivateList.at(i)->createBackendObject();
+ }
+ return;
+ }
+ delete m_backendObject;
+ m_backendObject = 0;
+ }
+ createBackend();
+ for (int i = 0; i < mediaNodePrivateList.count(); ++i) {
+ mediaNodePrivateList.at(i)->createBackendObject();
+ }
+ emit backendChanged();
+}
+#endif //QT_NO_DBUS
+
+//X void Factory::freeSoundcardDevices()
+//X {
+//X if (globalFactory->backend) {
+//X globalFactory->backend->freeSoundcardDevices();
+//X }
+//X }
+
+void FactoryPrivate::objectDestroyed(QObject * obj)
+{
+ //pDebug() << Q_FUNC_INFO << obj;
+ objects.removeAll(obj);
+}
+
+#define FACTORY_IMPL(classname) \
+QObject *Factory::create ## classname(QObject *parent) \
+{ \
+ if (backend()) { \
+ return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent)); \
+ } \
+ return 0; \
+}
+#define FACTORY_IMPL_1ARG(classname) \
+QObject *Factory::create ## classname(int arg1, QObject *parent) \
+{ \
+ if (backend()) { \
+ return registerQObject(qobject_cast<BackendInterface *>(backend())->createObject(BackendInterface::classname##Class, parent, QList<QVariant>() << arg1)); \
+ } \
+ return 0; \
+}
+
+FACTORY_IMPL(MediaObject)
+#ifndef QT_NO_PHONON_EFFECT
+FACTORY_IMPL_1ARG(Effect)
+#endif //QT_NO_PHONON_EFFECT
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+FACTORY_IMPL(VolumeFaderEffect)
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+FACTORY_IMPL(AudioOutput)
+#ifndef QT_NO_PHONON_VIDEO
+FACTORY_IMPL(VideoWidget)
+#endif //QT_NO_PHONON_VIDEO
+FACTORY_IMPL(AudioDataOutput)
+
+#undef FACTORY_IMPL
+
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+PlatformPlugin *FactoryPrivate::platformPlugin()
+{
+ if (m_platformPlugin) {
+ return m_platformPlugin;
+ }
+ if (m_noPlatformPlugin) {
+ return 0;
+ }
+#ifndef QT_NO_DBUS
+ if (!QCoreApplication::instance() || QCoreApplication::applicationName().isEmpty()) {
+ pWarning() << "Phonon needs QCoreApplication::applicationName to be set to export audio output names through the DBUS interface";
+ }
+#endif
+ Q_ASSERT(QCoreApplication::instance());
+ const QByteArray platform_plugin_env = qgetenv("PHONON_PLATFORMPLUGIN");
+ if (!platform_plugin_env.isEmpty()) {
+ QPluginLoader pluginLoader(QString::fromLocal8Bit(platform_plugin_env.constData()));
+ if (pluginLoader.load()) {
+ m_platformPlugin = qobject_cast<PlatformPlugin *>(pluginLoader.instance());
+ if (m_platformPlugin) {
+ return m_platformPlugin;
+ }
+ }
+ }
+ const QString suffix(QLatin1String("/phonon_platform/"));
+ ensureLibraryPathSet();
+ QDir dir;
+ dir.setNameFilters(
+ !qgetenv("KDE_FULL_SESSION").isEmpty() ? QStringList(QLatin1String("kde.*")) :
+ (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty() ? QStringList(QLatin1String("gnome.*")) :
+ QStringList())
+ );
+ dir.setFilter(QDir::Files);
+ const QStringList libPaths = QCoreApplication::libraryPaths();
+ forever {
+ for (int i = 0; i < libPaths.count(); ++i) {
+ const QString libPath = libPaths.at(i) + suffix;
+ dir.setPath(libPath);
+ if (!dir.exists()) {
+ continue;
+ }
+ const QStringList files = dir.entryList(QDir::Files);
+ for (int i = 0; i < files.count(); ++i) {
+ QPluginLoader pluginLoader(libPath + files.at(i));
+ if (!pluginLoader.load()) {
+ pDebug() << Q_FUNC_INFO << " platform plugin load failed:"
+ << pluginLoader.errorString();
+ continue;
+ }
+ pDebug() << pluginLoader.instance();
+ QObject *qobj = pluginLoader.instance();
+ m_platformPlugin = qobject_cast<PlatformPlugin *>(qobj);
+ pDebug() << m_platformPlugin;
+ if (m_platformPlugin) {
+ connect(qobj, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
+ SLOT(objectDescriptionChanged(ObjectDescriptionType)));
+ return m_platformPlugin;
+ } else {
+ delete qobj;
+ pDebug() << Q_FUNC_INFO << dir.absolutePath() << "exists but the platform plugin was not loadable:" << pluginLoader.errorString();
+ pluginLoader.unload();
+ }
+ }
+ }
+ if (dir.nameFilters().isEmpty()) {
+ break;
+ }
+ dir.setNameFilters(QStringList());
+ }
+ pDebug() << Q_FUNC_INFO << "platform plugin could not be loaded";
+ m_noPlatformPlugin = true;
+ return 0;
+}
+
+PlatformPlugin *Factory::platformPlugin()
+{
+ return globalFactory->platformPlugin();
+}
+#endif // QT_NO_PHONON_PLATFORMPLUGIN
+
+QObject *Factory::backend(bool createWhenNull)
+{
+ if (globalFactory.isDestroyed()) {
+ return 0;
+ }
+ if (createWhenNull && globalFactory->m_backendObject == 0) {
+ globalFactory->createBackend();
+ // XXX: might create "reentrancy" problems:
+ // a method calls this method and is called again because the
+ // backendChanged signal is emitted
+ emit globalFactory->backendChanged();
+ }
+ return globalFactory->m_backendObject;
+}
+
+#ifndef QT_NO_PROPERTIES
+#define GET_STRING_PROPERTY(name) \
+QString Factory::name() \
+{ \
+ if (globalFactory->m_backendObject) { \
+ return globalFactory->m_backendObject->property(#name).toString(); \
+ } \
+ return QString(); \
+} \
+
+GET_STRING_PROPERTY(identifier)
+GET_STRING_PROPERTY(backendName)
+GET_STRING_PROPERTY(backendComment)
+GET_STRING_PROPERTY(backendVersion)
+GET_STRING_PROPERTY(backendIcon)
+GET_STRING_PROPERTY(backendWebsite)
+#endif //QT_NO_PROPERTIES
+QObject *Factory::registerQObject(QObject *o)
+{
+ if (o) {
+ QObject::connect(o, SIGNAL(destroyed(QObject *)), globalFactory, SLOT(objectDestroyed(QObject *)), Qt::DirectConnection);
+ globalFactory->objects.append(o);
+ }
+ return o;
+}
+
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+#include "factory.moc"
+#include "moc_factory_p.cpp"
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/factory_p.h b/src/3rdparty/phonon/phonon/factory_p.h
new file mode 100644
index 0000000..41b8c5b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/factory_p.h
@@ -0,0 +1,203 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_FACTORY_P_H
+#define PHONON_FACTORY_P_H
+
+#include "phonon_export.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QUrl;
+class QIcon;
+
+namespace Phonon
+{
+ class PlatformPlugin;
+ class MediaNodePrivate;
+ class AbstractMediaStream;
+
+/**
+ * \internal
+ * \brief Factory to access the preferred Backend.
+ *
+ * This class is used internally to get the backend's implementation.
+ * It keeps track of the objects that were created. When a
+ * request for a backend change comes, it asks all frontend objects to delete
+ * their backend objects and then checks whether they were all deleted. Only
+ * then the old backend is unloaded and the new backend is loaded.
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+namespace Factory
+{
+ /**
+ * Emits signals for Phonon::Factory.
+ */
+ class Sender : public QObject
+ {
+ Q_OBJECT
+ Q_SIGNALS:
+ /**
+ * Emitted after the backend has successfully been changed.
+ */
+ void backendChanged();
+
+ /**
+ * \copydoc BackendCapabilities::Notifier::availableAudioOutputDevicesChanged
+ */
+ void availableAudioOutputDevicesChanged();
+
+ /**
+ * \copydoc BackendCapabilities::Notifier::availableAudioCaptureDevicesChanged
+ */
+ void availableAudioCaptureDevicesChanged();
+ };
+
+ /**
+ * Returns a pointer to the object emitting the signals.
+ *
+ * \see Sender::backendChanged()
+ */
+ PHONON_EXPORT Sender *sender();
+
+ /**
+ * Create a new backend object for a MediaObject.
+ *
+ * \return a pointer to the MediaObject the backend provides.
+ */
+ QObject *createMediaObject(QObject *parent = 0);
+ /**
+ * Create a new backend object for a Effect.
+ *
+ * \return a pointer to the Effect the backend provides.
+ */
+#ifndef QT_NO_PHONON_EFFECT
+ QObject *createEffect(int effectId, QObject *parent = 0);
+#endif //QT_NO_PHONON_EFFECT
+ /**
+ * Create a new backend object for a VolumeFaderEffect.
+ *
+ * \return a pointer to the VolumeFaderEffect the backend provides.
+ */
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+ QObject *createVolumeFaderEffect(QObject *parent = 0);
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+ /**
+ * Create a new backend object for a AudioOutput.
+ *
+ * \return a pointer to the AudioOutput the backend provides.
+ */
+ QObject *createAudioOutput(QObject *parent = 0);
+ /**
+ * Create a new backend object for a VideoWidget.
+ *
+ * \return a pointer to the VideoWidget the backend provides.
+ */
+#ifndef QT_NO_PHONON_VIDEO
+ QObject *createVideoWidget(QObject *parent = 0);
+#endif //QT_NO_PHONON_VIDEO
+
+ /**
+ * Create a new backend object for a AudioDataOutput.
+ *
+ * \return a pointer to the AudioDataOutput the backend provides.
+ */
+ PHONON_EXPORT QObject *createAudioDataOutput(QObject *parent = 0);
+
+ /**
+ * \return a pointer to the backend interface.
+ */
+ PHONON_EXPORT QObject *backend(bool createWhenNull = true);
+
+ /**
+ * Unique identifier for the Backend. Can be used in configuration files
+ * for example.
+ */
+ QString identifier();
+
+ /**
+ * Get the name of the Backend. It's the name from the .desktop file.
+ */
+ PHONON_EXPORT QString backendName();
+
+ /**
+ * Get the comment of the Backend. It's the comment from the .desktop file.
+ */
+ QString backendComment();
+
+ /**
+ * Get the version of the Backend. It's the version from the .desktop file.
+ *
+ * The version is especially interesting if there are several versions
+ * available for binary incompatible versions of the backend's media
+ * framework.
+ */
+ QString backendVersion();
+
+ /**
+ * Get the icon (name) of the Backend. It's the icon from the .desktop file.
+ */
+ QString backendIcon();
+
+ /**
+ * Get the website of the Backend. It's the website from the .desktop file.
+ */
+ QString backendWebsite();
+
+ /**
+ * registers the backend object
+ */
+ PHONON_EXPORT QObject *registerQObject(QObject *o);
+
+ bool isMimeTypeAvailable(const QString &mimeType);
+
+ PHONON_EXPORT void registerFrontendObject(MediaNodePrivate *);
+ PHONON_EXPORT void deregisterFrontendObject(MediaNodePrivate *);
+
+ PHONON_EXPORT void setBackend(QObject *);
+ //PHONON_EXPORT void createBackend(const QString &library, const QString &version = QString());
+
+ PHONON_EXPORT PlatformPlugin *platformPlugin();
+
+//X It is probably better if we can get away with internal handling of
+//X freeing the soundcard device when it's not needed anymore and
+//X providing an IPC method to stop all MediaObjects -> free all
+//X devices
+//X /**
+//X * \internal
+//X * This is called when the application needs to free the soundcard
+//X * device(s).
+//X */
+//X void freeSoundcardDevices();
+} // namespace Factory
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_FACTORY_P_H
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/frontendinterface_p.h b/src/3rdparty/phonon/phonon/frontendinterface_p.h
new file mode 100644
index 0000000..83ad780
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/frontendinterface_p.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_FRONTENDINTERFACEPRIVATE_H
+#define PHONON_FRONTENDINTERFACEPRIVATE_H
+
+#include "addoninterface.h"
+#include "mediaobject_p.h"
+#include "phononnamespace_p.h"
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+
+namespace Phonon
+{
+class FrontendInterfacePrivate
+{
+ public:
+ FrontendInterfacePrivate(MediaObject *mp) : media(mp) {
+ Q_ASSERT(media);
+ MediaObjectPrivate *d = media->k_func();
+ d->interfaceList << this;
+ }
+ virtual ~FrontendInterfacePrivate() {
+ if (media) {
+ MediaObjectPrivate *d = media->k_func();
+ d->interfaceList << this;
+ }
+ }
+ virtual void backendObjectChanged(QObject *iface) = 0;
+ void _backendObjectChanged() {
+ pDebug() << Q_FUNC_INFO;
+ QObject *x = media->k_ptr->backendObject();
+ if (x) {
+ backendObjectChanged(x);
+ }
+ }
+ AddonInterface *iface() { return qobject_cast<AddonInterface *>(media->k_ptr->backendObject()); }
+ QPointer<MediaObject> media;
+};
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+QT_END_NAMESPACE
+
+#endif // PHONON_FRONTENDINTERFACEPRIVATE_H
diff --git a/src/3rdparty/phonon/phonon/globalconfig.cpp b/src/3rdparty/phonon/phonon/globalconfig.cpp
new file mode 100644
index 0000000..f83ebc4
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/globalconfig.cpp
@@ -0,0 +1,449 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "globalconfig.h"
+#include "globalconfig_p.h"
+
+#include "factory_p.h"
+#include "objectdescription.h"
+#include "phonondefs_p.h"
+#include "platformplugin.h"
+#include "backendinterface.h"
+#include "qsettingsgroup_p.h"
+#include "phononnamespace_p.h"
+#include "pulsesupport.h"
+
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+GlobalConfigPrivate::GlobalConfigPrivate() : config(QLatin1String("kde.org"), QLatin1String("libphonon"))
+{
+}
+
+GlobalConfig::GlobalConfig()
+ : k_ptr(new GlobalConfigPrivate)
+{
+}
+
+GlobalConfig::~GlobalConfig()
+{
+ delete k_ptr;
+}
+
+enum WhatToFilter {
+ FilterAdvancedDevices = 1,
+ FilterHardwareDevices = 2,
+ FilterUnavailableDevices = 4
+};
+
+static void filter(ObjectDescriptionType type, BackendInterface *backendIface, QList<int> *list, int whatToFilter)
+{
+ QMutableListIterator<int> it(*list);
+ while (it.hasNext()) {
+ QHash<QByteArray, QVariant> properties;
+ if (backendIface)
+ properties = backendIface->objectDescriptionProperties(type, it.next());
+ else
+ properties = PulseSupport::getInstance()->objectDescriptionProperties(type, it.next());
+ QVariant var;
+ if (whatToFilter & FilterAdvancedDevices) {
+ var = properties.value("isAdvanced");
+ if (var.isValid() && var.toBool()) {
+ it.remove();
+ continue;
+ }
+ }
+ if (whatToFilter & FilterHardwareDevices) {
+ var = properties.value("isHardwareDevice");
+ if (var.isValid() && var.toBool()) {
+ it.remove();
+ continue;
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+ }
+ }
+ if (whatToFilter & FilterUnavailableDevices) {
+ var = properties.value("available");
+ if (var.isValid() && !var.toBool()) {
+ it.remove();
+ continue;
+ }
+ }
+ }
+}
+
+static QList<int> sortDevicesByCategoryPriority(const GlobalConfig *config, const QSettingsGroup *backendConfig, ObjectDescriptionType type, Phonon::Category category, QList<int> &defaultList)
+{
+ Q_ASSERT(config); Q_UNUSED(config);
+ Q_ASSERT(backendConfig);
+ Q_ASSERT(type == AudioOutputDeviceType || type == AudioCaptureDeviceType);
+
+ if (defaultList.size() <= 1) {
+ // nothing to sort
+ return defaultList;
+ } else {
+ // make entries unique
+ QSet<int> seen;
+ QMutableListIterator<int> it(defaultList);
+ while (it.hasNext()) {
+ if (seen.contains(it.next())) {
+ it.remove();
+ } else {
+ seen.insert(it.value());
+ }
+ }
+ }
+
+ QList<int> deviceList;
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ deviceList = pulse->objectIndexesByCategory(type, category);
+ } else {
+ QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
+ if (!backendConfig->hasKey(categoryKey)) {
+ // no list in config for the given category
+ categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory));
+ if (!backendConfig->hasKey(categoryKey)) {
+ // no list in config for NoCategory
+ return defaultList;
+ }
+ }
+
+ //Now the list from d->config
+ deviceList = backendConfig->value(categoryKey, QList<int>());
+ }
+
+ //if there are devices in d->config that the backend doesn't report, remove them from the list
+ QMutableListIterator<int> i(deviceList);
+ while (i.hasNext()) {
+ if (0 == defaultList.removeAll(i.next())) {
+ i.remove();
+ }
+ }
+
+ //if the backend reports more devices that are not in d->config append them to the list
+ deviceList += defaultList;
+
+ return deviceList;
+}
+
+bool GlobalConfig::hideAdvancedDevices() const
+{
+ K_D(const GlobalConfig);
+ //The devices need to be stored independently for every backend
+ const QSettingsGroup generalGroup(&d->config, QLatin1String("General"));
+ return generalGroup.value(QLatin1String("HideAdvancedDevices"), true);
+}
+
+void GlobalConfig::setHideAdvancedDevices(bool hide)
+{
+ K_D(GlobalConfig);
+ QSettingsGroup generalGroup(&d->config, QLatin1String("General"));
+ generalGroup.setValue(QLatin1String("HideAdvancedDevices"), hide);
+}
+
+static bool isHiddenAudioOutputDevice(const GlobalConfig *config, int i)
+{
+ Q_ASSERT(config);
+
+ if (!config->hideAdvancedDevices())
+ return false;
+
+ AudioOutputDevice ad = AudioOutputDevice::fromIndex(i);
+ const QVariant var = ad.property("isAdvanced");
+ return (var.isValid() && var.toBool());
+}
+
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+static bool isHiddenAudioCaptureDevice(const GlobalConfig *config, int i)
+{
+ Q_ASSERT(config);
+
+ if (!config->hideAdvancedDevices())
+ return false;
+
+ AudioCaptureDevice ad = AudioCaptureDevice::fromIndex(i);
+ const QVariant var = ad.property("isAdvanced");
+ return (var.isValid() && var.toBool());
+}
+#endif
+
+static QList<int> reindexList(const GlobalConfig *config, Phonon::Category category, QList<int>newOrder, bool output)
+{
+ Q_ASSERT(config);
+#ifdef QT_NO_PHONON_AUDIOCAPTURE
+ Q_ASSERT(output);
+#endif
+
+ /*QString sb;
+ sb = QString("(Size %1)").arg(currentList.size());
+ foreach (int i, currentList)
+ sb += QString("%1, ").arg(i);
+ fprintf(stderr, "=== Reindex Current: %s\n", sb.toUtf8().constData());
+ sb = QString("(Size %1)").arg(newOrder.size());
+ foreach (int i, newOrder)
+ sb += QString("%1, ").arg(i);
+ fprintf(stderr, "=== Reindex Before : %s\n", sb.toUtf8().constData());*/
+
+ QList<int> currentList;
+ if (output)
+ currentList = config->audioOutputDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices);
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ else
+ currentList = config->audioCaptureDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices);
+#endif
+
+ QList<int> newList;
+
+ foreach (int i, newOrder) {
+ int found = currentList.indexOf(i);
+ if (found < 0) {
+ // It's not in the list, so something is odd (e.g. client error). Ignore it.
+ continue;
+ }
+
+ // Iterate through the list from this point onward. If there are hidden devices
+ // immediately following, take them too.
+ newList.append(currentList.takeAt(found));
+ while (found < currentList.size()) {
+ bool hidden = true;
+ if (output)
+ hidden = isHiddenAudioOutputDevice(config, currentList.at(found));
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ else
+ hidden = isHiddenAudioCaptureDevice(config, currentList.at(found));
+#endif
+
+ if (!hidden)
+ break;
+ newList.append(currentList.takeAt(found));
+ }
+ }
+
+ // If there are any devices left in.. just tack them on the end.
+ if (currentList.size() > 0)
+ newList += currentList;
+
+ /*sb = QString("(Size %1)").arg(newList.size());
+ foreach (int i, newList)
+ sb += QString("%1, ").arg(i);
+ fprintf(stderr, "=== Reindex After : %s\n", sb.toUtf8().constData());*/
+ return newList;
+}
+
+
+void GlobalConfig::setAudioOutputDeviceListFor(Phonon::Category category, QList<int> order)
+{
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ pulse->setOutputDevicePriorityForCategory(category, order);
+ return;
+ }
+
+ K_D(GlobalConfig);
+ QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
+
+ order = reindexList(this, category, order, true);
+
+ const QList<int> noCategoryOrder = audioOutputDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices);
+ if (category != Phonon::NoCategory && order == noCategoryOrder) {
+ backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category));
+ } else {
+ backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order);
+ }
+}
+#endif //QT_NO_PHONON_SETTINGSGROUP
+
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int override) const
+{
+ K_D(const GlobalConfig);
+
+ const bool hide = ((override & AdvancedDevicesFromSettings)
+ ? hideAdvancedDevices()
+ : static_cast<bool>(override & HideAdvancedDevices));
+
+ QList<int> defaultList;
+
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ defaultList = pulse->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
+ if (hide || (override & HideUnavailableDevices)) {
+ filter(AudioOutputDeviceType, NULL, &defaultList,
+ (hide ? FilterAdvancedDevices : 0)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ } else {
+ BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
+
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
+ // the platform plugin lists the audio devices for the platform
+ // this list already is in default order (as defined by the platform plugin)
+ defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
+ if (hide) {
+ QMutableListIterator<int> it(defaultList);
+ while (it.hasNext()) {
+ AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
+ const QVariant var = objDesc.property("isAdvanced");
+ if (var.isValid() && var.toBool()) {
+ it.remove();
+ }
+ }
+ }
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+
+ // lookup the available devices directly from the backend
+ if (backendIface) {
+ // this list already is in default order (as defined by the backend)
+ QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
+ if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
+ filter(AudioOutputDeviceType, backendIface, &list,
+ (hide ? FilterAdvancedDevices : 0)
+ // the platform plugin maybe already provided the hardware devices?
+ | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ defaultList += list;
+ }
+ }
+
+ const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
+ return sortDevicesByCategoryPriority(this, &backendConfig, AudioOutputDeviceType, category, defaultList);
+}
+#endif //QT_NO_PHONON_SETTINGSGROUP
+int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override) const
+{
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+ QList<int> ret = audioOutputDeviceListFor(category, override);
+ if (!ret.isEmpty())
+ return ret.first();
+#endif //QT_NO_PHONON_SETTINGSGROUP
+ return -1;
+}
+
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+void GlobalConfig::setAudioCaptureDeviceListFor(Phonon::Category category, QList<int> order)
+{
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ pulse->setCaptureDevicePriorityForCategory(category, order);
+ return;
+ }
+
+ K_D(GlobalConfig);
+ QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
+
+ order = reindexList(this, category, order, false);
+
+ const QList<int> noCategoryOrder = audioCaptureDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices);
+ if (category != Phonon::NoCategory && order == noCategoryOrder) {
+ backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category));
+ } else {
+ backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order);
+ }
+}
+
+QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, int override) const
+{
+ K_D(const GlobalConfig);
+
+ const bool hide = ((override & AdvancedDevicesFromSettings)
+ ? hideAdvancedDevices()
+ : static_cast<bool>(override & HideAdvancedDevices));
+
+ QList<int> defaultList;
+
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ defaultList = pulse->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
+ if (hide || (override & HideUnavailableDevices)) {
+ filter(AudioCaptureDeviceType, NULL, &defaultList,
+ (hide ? FilterAdvancedDevices : 0)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ } else {
+ BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
+
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+#else //QT_NO_SETTINGSGROUP
+ return QList<int>();
+#endif //QT_NO_SETTINGSGROUP
+ if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
+ // the platform plugin lists the audio devices for the platform
+ // this list already is in default order (as defined by the platform plugin)
+ defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
+ if (hide) {
+ QMutableListIterator<int> it(defaultList);
+ while (it.hasNext()) {
+ AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
+ const QVariant var = objDesc.property("isAdvanced");
+ if (var.isValid() && var.toBool()) {
+ it.remove();
+ }
+ }
+ }
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+
+ // lookup the available devices directly from the backend
+ if (backendIface) {
+ // this list already is in default order (as defined by the backend)
+ QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
+ if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
+ filter(AudioCaptureDeviceType, backendIface, &list,
+ (hide ? FilterAdvancedDevices : 0)
+ // the platform plugin maybe already provided the hardware devices?
+ | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ defaultList += list;
+ }
+ }
+
+ const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
+ return sortDevicesByCategoryPriority(this, &backendConfig, AudioCaptureDeviceType, category, defaultList);
+}
+
+int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category, int override) const
+{
+ QList<int> ret = audioCaptureDeviceListFor(category, override);
+ if (ret.isEmpty())
+ return -1;
+ return ret.first();
+}
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/globalconfig.h b/src/3rdparty/phonon/phonon/globalconfig.h
new file mode 100644
index 0000000..5233c7b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/globalconfig.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project
+Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_GLOBALCONFIG_H
+#define PHONON_GLOBALCONFIG_H
+
+#include "phonon_export.h"
+#include "phononnamespace.h"
+#include "phonondefs.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class GlobalConfigPrivate;
+
+ class PHONON_EXPORT GlobalConfig
+ {
+ K_DECLARE_PRIVATE(GlobalConfig)
+ public:
+ GlobalConfig();
+ virtual ~GlobalConfig();
+
+ enum DevicesToHideFlag {
+ ShowUnavailableDevices = 0,
+ ShowAdvancedDevices = 0,
+ HideAdvancedDevices = 1,
+ AdvancedDevicesFromSettings = 2,
+ HideUnavailableDevices = 4
+ };
+ bool hideAdvancedDevices() const;
+ void setHideAdvancedDevices(bool hide = true);
+ void setAudioOutputDeviceListFor(Phonon::Category category, QList<int> order);
+ QList<int> audioOutputDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+ int audioOutputDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ void setAudioCaptureDeviceListFor(Phonon::Category category, QList<int> order);
+ QList<int> audioCaptureDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+ int audioCaptureDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+
+ protected:
+ GlobalConfigPrivate *const k_ptr;
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_GLOBALCONFIG_H
diff --git a/src/3rdparty/phonon/phonon/globalconfig_p.h b/src/3rdparty/phonon/phonon/globalconfig_p.h
new file mode 100644
index 0000000..090ca6b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/globalconfig_p.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_GLOBALCONFIG_P_H
+#define PHONON_GLOBALCONFIG_P_H
+
+#include <QtCore/QSettings>
+
+#include "phonon_export.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class GlobalConfigPrivate
+ {
+ public:
+ GlobalConfigPrivate();
+ virtual ~GlobalConfigPrivate() {}
+
+ QSettings config;
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_GLOBALCONFIG_P_H
diff --git a/src/3rdparty/phonon/phonon/globalstatic_p.h b/src/3rdparty/phonon/phonon/globalstatic_p.h
new file mode 100644
index 0000000..cf80512
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/globalstatic_p.h
@@ -0,0 +1,293 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_GLOBALSTATIC_P_H
+#define PHONON_GLOBALSTATIC_P_H
+
+#include <QtCore/QAtomicPointer>
+
+//
+// WARNING!!
+// This code uses undocumented Qt API
+// Do not copy it to your application! Use only the functions that are here!
+// Otherwise, it could break when a new version of Qt ships.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+/**
+ * @internal
+ */
+typedef void (*CleanUpFunction)();
+
+/**
+ * @internal
+ *
+ * Helper class for PHONON_GLOBAL_STATIC to clean up the object on library unload or application
+ * shutdown.
+ */
+class CleanUpGlobalStatic
+{
+ public:
+ CleanUpFunction func;
+
+ inline ~CleanUpGlobalStatic() { func(); }
+};
+
+} // namespace Phonon
+
+#ifdef Q_CC_MSVC
+/**
+ * @internal
+ *
+ * MSVC seems to give anonymous structs the same name which fails at link time. So instead we name
+ * the struct and hope that by adding the line number to the name it's unique enough to never clash.
+ */
+# define PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME) _k_##NAME##__LINE__
+#else
+/**
+ * @internal
+ *
+ * Make the struct of the PHONON_GLOBAL_STATIC anonymous.
+ */
+# define PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME)
+#endif
+
+/**
+ * This macro makes it easy to use non-POD types as global statics.
+ * The object is created on first use and creation is threadsafe.
+ *
+ * The object is destructed on library unload or application exit.
+ * Be careful with calling other objects in the destructor of the class
+ * as you have to be sure that they (or objects they depend on) are not already destructed.
+ *
+ * @param TYPE The type of the global static object. Do not add a *.
+ * @param NAME The name of the function to get a pointer to the global static object.
+ *
+ * If you have code that might be called after the global object has been destroyed you can check
+ * for that using the isDestroyed() function.
+ *
+ * If needed (If the destructor of the global object calls other functions that depend on other
+ * global statics (e.g. KConfig::sync) your destructor has to be called before those global statics
+ * are destroyed. A Qt post routine does that.) you can also install a post routine (@ref qAddPostRoutine) to clean up the object
+ * using the destroy() method. If you registered a post routine and the object is destroyed because
+ * of a lib unload you have to call qRemovePostRoutine!
+ *
+ * Example:
+ * @code
+ * class A {
+ * public:
+ * ~A();
+ * ...
+ * };
+ *
+ * PHONON_GLOBAL_STATIC(A, globalA)
+ * // The above creates a new globally static variable named 'globalA' which you
+ * // can use as a pointer to an instance of A.
+ *
+ * void doSomething()
+ * {
+ * // The first time you access globalA a new instance of A will be created automatically.
+ * A *a = globalA;
+ * ...
+ * }
+ *
+ * void doSomethingElse()
+ * {
+ * if (globalA.isDestroyed()) {
+ * return;
+ * }
+ * A *a = globalA;
+ * ...
+ * }
+ *
+ * void installPostRoutine()
+ * {
+ * // A post routine can be used to delete the object when QCoreApplication destructs,
+ * // not adding such a post routine will delete the object normally at program unload
+ * qAddPostRoutine(globalA.destroy);
+ * }
+ *
+ * A::~A()
+ * {
+ * // When you install a post routine you have to remove the post routine from the destructor of
+ * // the class used as global static!
+ * qRemovePostRoutine(globalA.destroy);
+ * }
+ * @endcode
+ *
+ * A common case for the need of deletion on lib unload/app shutdown are Singleton classes. Here's
+ * an example how to do it:
+ * @code
+ * class MySingletonPrivate;
+ * class EXPORT_MACRO MySingleton
+ * {
+ * friend class MySingletonPrivate;
+ * public:
+ * static MySingleton *self();
+ * QString someFunction();
+ *
+ * private:
+ * MySingleton();
+ * ~MySingleton();
+ * };
+ * @endcode
+ * in the .cpp file:
+ * @code
+ * // This class will be instantiated and referenced as a singleton in this example
+ * class MySingletonPrivate
+ * {
+ * public:
+ * QString foo;
+ * MySingleton instance;
+ * };
+ *
+ * PHONON_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate)
+ *
+ * MySingleton *MySingleton::self()
+ * {
+ * // returns the singleton; automatically creates a new instance if that has not happened yet.
+ * return &mySingletonPrivate->instance;
+ * }
+ * QString MySingleton::someFunction()
+ * {
+ * // Refencing the singleton directly is possible for your convenience
+ * return mySingletonPrivate->foo;
+ * }
+ * @endcode
+ *
+ * Instead of the above you can use also the following pattern (ignore the name of the namespace):
+ * @code
+ * namespace MySingleton
+ * {
+ * EXPORT_MACRO QString someFunction();
+ * }
+ * @endcode
+ * in the .cpp file:
+ * @code
+ * class MySingletonPrivate
+ * {
+ * public:
+ * QString foo;
+ * };
+ *
+ * PHONON_GLOBAL_STATIC(MySingletonPrivate, mySingletonPrivate)
+ *
+ * QString MySingleton::someFunction()
+ * {
+ * return mySingletonPrivate->foo;
+ * }
+ * @endcode
+ *
+ * Now code that wants to call someFunction() doesn't have to do
+ * @code
+ * MySingleton::self()->someFunction();
+ * @endcode
+ * anymore but instead:
+ * @code
+ * MySingleton::someFunction();
+ * @endcode
+ *
+ * @ingroup KDEMacros
+ */
+#define PHONON_GLOBAL_STATIC(TYPE, NAME) PHONON_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ())
+
+/**
+ * @overload
+ * This is the same as PHONON_GLOBAL_STATIC, but can take arguments that are passed
+ * to the object's constructor
+ *
+ * @param TYPE The type of the global static object. Do not add a *.
+ * @param NAME The name of the function to get a pointer to the global static object.
+ * @param ARGS the list of arguments, between brackets
+ *
+ * Example:
+ * @code
+ * class A
+ * {
+ * public:
+ * A(const char *s, int i);
+ * ...
+ * };
+ *
+ * PHONON_GLOBAL_STATIC_WITH_ARG(A, globalA, ("foo", 0))
+ * // The above creates a new globally static variable named 'globalA' which you
+ * // can use as a pointer to an instance of A.
+ *
+ * void doSomething()
+ * {
+ * // The first time you access globalA a new instance of A will be created automatically.
+ * A *a = globalA;
+ * ...
+ * }
+ * @endcode
+ *
+ * @ingroup KDEMacros
+ */
+#define PHONON_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \
+static QBasicAtomicPointer<TYPE > _k_static_##NAME = Q_BASIC_ATOMIC_INITIALIZER(0); \
+static bool _k_static_##NAME##_destroyed; \
+static struct PHONON_GLOBAL_STATIC_STRUCT_NAME(NAME) \
+{ \
+ bool isDestroyed() \
+ { \
+ return _k_static_##NAME##_destroyed; \
+ } \
+ inline operator TYPE*() \
+ { \
+ return operator->(); \
+ } \
+ inline TYPE *operator->() \
+ { \
+ TYPE *p = _k_static_##NAME; \
+ if (!p) { \
+ if (isDestroyed()) { \
+ qFatal("Fatal Error: Accessed global static '%s *%s()' after destruction. " \
+ "Defined at %s:%d", #TYPE, #NAME, __FILE__, __LINE__); \
+ } \
+ p = new TYPE ARGS; \
+ if (!_k_static_##NAME.testAndSetOrdered(0, p)) { \
+ delete p; \
+ p = _k_static_##NAME; \
+ } else { \
+ static Phonon::CleanUpGlobalStatic cleanUpObject = { destroy }; \
+ } \
+ } \
+ return p; \
+ } \
+ inline TYPE &operator*() \
+ { \
+ return *operator->(); \
+ } \
+ static void destroy() \
+ { \
+ _k_static_##NAME##_destroyed = true; \
+ TYPE *x = _k_static_##NAME; \
+ _k_static_##NAME = 0; \
+ delete x; \
+ } \
+} NAME;
+
+QT_END_NAMESPACE
+#endif // PHONON_GLOBALSTATIC_P_H
diff --git a/src/3rdparty/phonon/phonon/iodevicestream.cpp b/src/3rdparty/phonon/phonon/iodevicestream.cpp
new file mode 100644
index 0000000..3735f75
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/iodevicestream.cpp
@@ -0,0 +1,100 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "iodevicestream_p.h"
+#include "abstractmediastream_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+
+class IODeviceStreamPrivate : public AbstractMediaStreamPrivate
+{
+ Q_DECLARE_PUBLIC(IODeviceStream)
+ protected:
+ IODeviceStreamPrivate(QIODevice *_ioDevice)
+ : ioDevice(_ioDevice)
+ {
+ if (!ioDevice->isOpen()) {
+ ioDevice->open(QIODevice::ReadOnly);
+ }
+ Q_ASSERT(ioDevice->isOpen());
+ Q_ASSERT(ioDevice->isReadable());
+ streamSize = ioDevice->size();
+ streamSeekable = !ioDevice->isSequential();
+ }
+
+ private:
+ QIODevice *ioDevice;
+};
+
+IODeviceStream::IODeviceStream(QIODevice *ioDevice, QObject *parent)
+ : AbstractMediaStream(*new IODeviceStreamPrivate(ioDevice), parent)
+{
+ Q_D(IODeviceStream);
+ d->ioDevice->reset();
+}
+
+IODeviceStream::~IODeviceStream()
+{
+}
+
+void IODeviceStream::reset()
+{
+ Q_D(IODeviceStream);
+ d->ioDevice->reset();
+ //resetDone();
+}
+
+void IODeviceStream::needData()
+{
+ quint32 size = 4096;
+ Q_D(IODeviceStream);
+ const QByteArray data = d->ioDevice->read(size);
+ if (data.isEmpty() && !d->ioDevice->atEnd()) {
+ error(Phonon::NormalError, d->ioDevice->errorString());
+ }
+ writeData(data);
+ if (d->ioDevice->atEnd()) {
+ endOfData();
+ }
+}
+
+void IODeviceStream::seekStream(qint64 offset)
+{
+ Q_D(IODeviceStream);
+ d->ioDevice->seek(offset);
+ //seekStreamDone();
+}
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+
+#include "moc_iodevicestream_p.cpp"
+
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/phonon/iodevicestream_p.h b/src/3rdparty/phonon/phonon/iodevicestream_p.h
new file mode 100644
index 0000000..cca77e3
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/iodevicestream_p.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_IODEVICESTREAM_P_H
+#define PHONON_IODEVICESTREAM_P_H
+
+#include "abstractmediastream.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+class QIODevice;
+
+namespace Phonon
+{
+
+class IODeviceStreamPrivate;
+class IODeviceStream : public AbstractMediaStream
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(IODeviceStream)
+ public:
+ explicit IODeviceStream(QIODevice *ioDevice, QObject *parent = 0);
+ ~IODeviceStream();
+
+ void reset();
+ void needData();
+ void seekStream(qint64);
+};
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_IODEVICESTREAM_P_H
diff --git a/src/3rdparty/phonon/phonon/mediacontroller.cpp b/src/3rdparty/phonon/phonon/mediacontroller.cpp
new file mode 100644
index 0000000..3dc22b7
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediacontroller.cpp
@@ -0,0 +1,239 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2008 Ian Monroe <ian@monroe.nu>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "mediacontroller.h"
+#include "mediaobject.h"
+#include "addoninterface.h"
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+#include "frontendinterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+
+namespace Phonon
+{
+
+class MediaControllerPrivate : public FrontendInterfacePrivate
+{
+ public:
+ MediaControllerPrivate(MediaObject *mp) : FrontendInterfacePrivate(mp) {}
+
+ virtual void backendObjectChanged(QObject *);
+ MediaController *q;
+};
+
+MediaController::MediaController(MediaObject *mp)
+ : QObject(mp)
+ , d(new MediaControllerPrivate(mp))
+{
+ d->q = this;
+ d->_backendObjectChanged();
+}
+
+void MediaControllerPrivate::backendObjectChanged(QObject *m_backendObject)
+{
+ QObject::connect(m_backendObject, SIGNAL(availableSubtitlesChanged()), q, SIGNAL(availableSubtitlesChanged()));
+ QObject::connect(m_backendObject, SIGNAL(availableAudioChannelsChanged()), q, SIGNAL(availableAudioChannelsChanged()));
+ QObject::connect(m_backendObject, SIGNAL(titleChanged(int)), q, SIGNAL(titleChanged(int)));
+ QObject::connect(m_backendObject, SIGNAL(availableTitlesChanged(int)), q, SIGNAL(availableTitlesChanged(int)));
+ QObject::connect(m_backendObject, SIGNAL(chapterChanged(int)), q, SIGNAL(chapterChanged(int)));
+ QObject::connect(m_backendObject, SIGNAL(availableChaptersChanged(int)), q, SIGNAL(availableChaptersChanged(int)));
+ QObject::connect(m_backendObject, SIGNAL(angleChanged(int)), q, SIGNAL(angleChanged(int)));
+ QObject::connect(m_backendObject, SIGNAL(availableAnglesChanged(int)), q, SIGNAL(availableAnglesChanged(int)));
+}
+
+MediaController::~MediaController()
+{
+ delete d;
+}
+
+#define IFACE \
+ AddonInterface *iface = d->iface(); \
+ if (!iface) return
+
+MediaController::Features MediaController::supportedFeatures() const
+{
+ if (!d || !d->media) {
+ return Features();
+ }
+ IFACE Features();
+ Features ret;
+ if (iface->hasInterface(AddonInterface::AngleInterface)) {
+ ret |= Angles;
+ }
+ if (iface->hasInterface(AddonInterface::ChapterInterface)) {
+ ret |= Chapters;
+ }
+ if (iface->hasInterface(AddonInterface::TitleInterface)) {
+ ret |= Titles;
+ }
+ return ret;
+}
+
+int MediaController::availableTitles() const
+{
+ IFACE 0;
+ return iface->interfaceCall(AddonInterface::TitleInterface,
+ AddonInterface::availableTitles).toInt();
+}
+
+int MediaController::currentTitle() const
+{
+ IFACE 0;
+ return iface->interfaceCall(AddonInterface::TitleInterface,
+ AddonInterface::title).toInt();
+}
+
+void MediaController::setCurrentTitle(int titleNumber)
+{
+ IFACE;
+ iface->interfaceCall(AddonInterface::TitleInterface,
+ AddonInterface::setTitle, QList<QVariant>() << QVariant(titleNumber));
+}
+
+bool MediaController::autoplayTitles() const
+{
+ IFACE true;
+ return iface->interfaceCall(AddonInterface::TitleInterface,
+ AddonInterface::autoplayTitles).toBool();
+}
+
+void MediaController::setAutoplayTitles(bool b)
+{
+ IFACE;
+ iface->interfaceCall(AddonInterface::TitleInterface,
+ AddonInterface::setAutoplayTitles, QList<QVariant>() << QVariant(b));
+}
+
+void MediaController::nextTitle()
+{
+ setCurrentTitle(currentTitle() + 1);
+}
+
+void MediaController::previousTitle()
+{
+ setCurrentTitle(currentTitle() - 1);
+}
+
+int MediaController::availableChapters() const
+{
+ IFACE 0;
+ return iface->interfaceCall(AddonInterface::ChapterInterface,
+ AddonInterface::availableChapters).toInt();
+}
+
+int MediaController::currentChapter() const
+{
+ IFACE 0;
+ return iface->interfaceCall(AddonInterface::ChapterInterface,
+ AddonInterface::chapter).toInt();
+}
+
+void MediaController::setCurrentChapter(int titleNumber)
+{
+ IFACE;
+ iface->interfaceCall(AddonInterface::ChapterInterface,
+ AddonInterface::setChapter, QList<QVariant>() << QVariant(titleNumber));
+}
+
+int MediaController::availableAngles() const
+{
+ IFACE 0;
+ return iface->interfaceCall(AddonInterface::AngleInterface,
+ AddonInterface::availableAngles).toInt();
+}
+
+int MediaController::currentAngle() const
+{
+ IFACE 0;
+ return iface->interfaceCall(AddonInterface::AngleInterface,
+ AddonInterface::angle).toInt();
+}
+
+void MediaController::setCurrentAngle(int titleNumber)
+{
+ IFACE;
+ iface->interfaceCall(AddonInterface::AngleInterface,
+ AddonInterface::setAngle, QList<QVariant>() << QVariant(titleNumber));
+}
+
+AudioChannelDescription MediaController::currentAudioChannel() const
+{
+ IFACE AudioChannelDescription();
+ return iface->interfaceCall(AddonInterface::AudioChannelInterface,
+ AddonInterface::currentAudioChannel).value<AudioChannelDescription>();
+}
+
+SubtitleDescription MediaController::currentSubtitle() const
+{
+ IFACE SubtitleDescription();
+ return iface->interfaceCall(AddonInterface::SubtitleInterface,
+ AddonInterface::currentSubtitle).value<SubtitleDescription>();
+}
+
+QList<AudioChannelDescription> MediaController::availableAudioChannels() const
+{
+ QList<AudioChannelDescription> retList;
+ IFACE retList;
+ retList = iface->interfaceCall(AddonInterface::AudioChannelInterface,
+ AddonInterface::availableAudioChannels).value< QList<AudioChannelDescription> >();
+ return retList;
+}
+
+QList<SubtitleDescription> MediaController::availableSubtitles() const
+{
+ QList<SubtitleDescription> retList;
+ IFACE retList;
+ retList = iface->interfaceCall(AddonInterface::SubtitleInterface,
+ AddonInterface::availableSubtitles)
+ .value< QList<SubtitleDescription> >();
+ return retList;
+}
+
+void MediaController::setCurrentAudioChannel(const Phonon::AudioChannelDescription &stream)
+{
+ IFACE;
+ iface->interfaceCall(AddonInterface::AudioChannelInterface,
+ AddonInterface::setCurrentAudioChannel, QList<QVariant>() << QVariant::fromValue(stream));
+}
+
+void MediaController::setCurrentSubtitle(const Phonon::SubtitleDescription &stream)
+{
+ IFACE;
+ iface->interfaceCall(AddonInterface::SubtitleInterface,
+ AddonInterface::setCurrentSubtitle, QList<QVariant>() << QVariant::fromValue(stream));
+}
+
+#undef IFACE
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+QT_END_NAMESPACE
+
+#include "moc_mediacontroller.cpp"
+
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/phonon/mediacontroller.h b/src/3rdparty/phonon/phonon/mediacontroller.h
new file mode 100644
index 0000000..109a79e
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediacontroller.h
@@ -0,0 +1,188 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MEDIACONTROLLER_H
+#define PHONON_MEDIACONTROLLER_H
+
+#include "phonon_export.h"
+#include "objectdescription.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+
+namespace Phonon
+{
+class MediaControllerPrivate;
+class MediaObject;
+
+/** \class MediaController mediacontroller.h Phonon/MediaController
+ * \brief Controls optional features of a media file/device like title, chapter, angle.
+ *
+ * \ingroup Playback
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class PHONON_EXPORT MediaController : public QObject
+{
+ Q_OBJECT
+ Q_FLAGS(Features)
+ public:
+ enum Feature {
+ Angles = 1,
+ Chapters = 2,
+ Titles = 4
+ };
+ Q_DECLARE_FLAGS(Features, Feature)
+
+ MediaController(MediaObject *parent);
+ ~MediaController();
+
+ Features supportedFeatures() const;
+
+ int availableAngles() const;
+ int currentAngle() const;
+
+ int availableChapters() const;
+ int currentChapter() const;
+
+ int availableTitles() const;
+ int currentTitle() const;
+
+ bool autoplayTitles() const;
+
+ /**
+ * Returns the selected audio stream.
+ *
+ * \see availableAudioChannels
+ * \see setCurrentAudioChannel
+ */
+ AudioChannelDescription currentAudioChannel() const;
+
+ /**
+ * Returns the selected subtitle stream.
+ *
+ * \see availableSubtitles
+ * \see setCurrentSubtitle
+ */
+ SubtitleDescription currentSubtitle() const;
+
+ /**
+ * Returns the audio streams that can be selected by the user. The
+ * strings can directly be used in the user interface.
+ *
+ * \see selectedAudioChannel
+ * \see setCurrentAudioChannel
+ */
+ QList<AudioChannelDescription> availableAudioChannels() const;
+
+ /**
+ * Returns the subtitle streams that can be selected by the user. The
+ * strings can directly be used in the user interface.
+ *
+ * \see selectedSubtitle
+ * \see setCurrentSubtitle
+ */
+ QList<SubtitleDescription> availableSubtitles() const;
+
+ /**
+ * Selects an audio stream from the media.
+ *
+ * Some media formats allow multiple audio streams to be stored in
+ * the same file. Normally only one should be played back.
+ *
+ * \param stream Description of an audio stream
+ *
+ * \see availableAudioChannels()
+ * \see currentAudioChannel()
+ */
+ void setCurrentAudioChannel(const Phonon::AudioChannelDescription &stream);
+
+ /**
+ * Selects a subtitle stream from the media.
+ *
+ * Some media formats allow multiple subtitle streams to be stored in
+ * the same file. Normally only one should be displayed.
+ *
+ * \param stream description of a subtitle stream
+ *
+ * \see availableSubtitles()
+ * \see currentSubtitle()
+ */
+ void setCurrentSubtitle(const Phonon::SubtitleDescription &stream);
+
+ public Q_SLOTS:
+ void setCurrentAngle(int angleNumber);
+ void setCurrentChapter(int chapterNumber);
+
+ /**
+ * Skips to the given title \p titleNumber.
+ *
+ * If it was playing before the title change it will start playback on the new title if
+ * autoplayTitles is enabled.
+ */
+ void setCurrentTitle(int titleNumber);
+ void setAutoplayTitles(bool);
+
+ /**
+ * Skips to the next title.
+ *
+ * If it was playing before the title change it will start playback on the next title if
+ * autoplayTitles is enabled.
+ */
+ void nextTitle();
+
+ /**
+ * Skips to the previous title.
+ *
+ * If it was playing before the title change it will start playback on the previous title if
+ * autoplayTitles is enabled.
+ */
+ void previousTitle();
+
+ Q_SIGNALS:
+ void availableSubtitlesChanged();
+ void availableAudioChannelsChanged();
+ void availableAnglesChanged(int availableAngles);
+ void angleChanged(int angleNumber);
+ void availableChaptersChanged(int availableChapters);
+ void chapterChanged(int chapterNumber);
+ void availableTitlesChanged(int availableTitles);
+ void titleChanged(int titleNumber);
+
+ protected:
+ MediaControllerPrivate *const d;
+};
+
+} // namespace Phonon
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::MediaController::Features)
+
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_MEDIACONTROLLER_H
diff --git a/src/3rdparty/phonon/phonon/medianode.cpp b/src/3rdparty/phonon/phonon/medianode.cpp
new file mode 100644
index 0000000..bc1caed
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/medianode.cpp
@@ -0,0 +1,130 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "medianode.h"
+#include "medianode_p.h"
+#include "medianodedestructionhandler_p.h"
+#include "factory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+ MediaNode::MediaNode(MediaNodePrivate &dd)
+ : k_ptr(&dd)
+ {
+ k_ptr->q_ptr = this;
+ }
+
+bool MediaNode::isValid() const
+{
+ return const_cast<MediaNodePrivate *>(k_ptr)->backendObject() != 0;
+}
+
+ QList<Path> MediaNode::inputPaths() const
+ {
+ return k_ptr->inputPaths;
+ }
+
+ QList<Path> MediaNode::outputPaths() const
+ {
+ return k_ptr->outputPaths;
+ }
+
+ MediaNode::~MediaNode()
+ {
+ delete k_ptr;
+ }
+
+ QObject *MediaNodePrivate::backendObject()
+ {
+ if (!m_backendObject && Factory::backend()) {
+ createBackendObject();
+ }
+ return m_backendObject;
+ }
+
+ MediaNodePrivate::~MediaNodePrivate()
+ {
+ for (int i = 0 ; i < handlers.count(); ++i) {
+ handlers.at(i)->phononObjectDestroyed(this);
+ }
+ Factory::deregisterFrontendObject(this);
+ delete m_backendObject;
+ m_backendObject = 0;
+ }
+
+void MediaNodePrivate::deleteBackendObject()
+{
+ if (m_backendObject && aboutToDeleteBackendObject()) {
+ delete m_backendObject;
+ m_backendObject = 0;
+ }
+}
+
+ MediaNodePrivate::MediaNodePrivate(MediaNodePrivate::CastId _castId) : castId(_castId),
+ m_backendObject(0)
+ {
+ Factory::registerFrontendObject(this);
+ }
+
+ void MediaNodePrivate::addDestructionHandler(MediaNodeDestructionHandler *handler)
+ {
+ handlers.append(handler);
+ }
+
+ void MediaNodePrivate::removeDestructionHandler(MediaNodeDestructionHandler *handler)
+ {
+ handlers.removeAll(handler);
+ }
+
+ void MediaNodePrivate::addOutputPath(const Path &p)
+ {
+ outputPaths.append(p);
+ }
+
+ void MediaNodePrivate::addInputPath(const Path &p)
+ {
+ inputPaths.append(p);
+ }
+
+ void MediaNodePrivate::removeOutputPath(const Path &p)
+ {
+ int ret = outputPaths.removeAll(p);
+ Q_ASSERT(ret == 1);
+ Q_UNUSED(ret);
+ }
+
+ void MediaNodePrivate::removeInputPath(const Path &p)
+ {
+ int ret = inputPaths.removeAll(p);
+ Q_ASSERT(ret == 1);
+ Q_UNUSED(ret);
+ }
+
+
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/medianode.h b/src/3rdparty/phonon/phonon/medianode.h
new file mode 100644
index 0000000..6aab189
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/medianode.h
@@ -0,0 +1,69 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MEDIANODE_H
+#define PHONON_MEDIANODE_H
+
+#include "phonondefs.h"
+#include "phonon_export.h"
+#include "path.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+ class Path;
+ class MediaNodePrivate;
+ class PHONON_EXPORT MediaNode
+ {
+ friend class Path;
+ friend class PathPrivate;
+ friend PHONON_EXPORT Path createPath(MediaNode *source, MediaNode *sink);
+ K_DECLARE_PRIVATE(MediaNode)
+ public:
+ virtual ~MediaNode();
+ /**
+ * Tells whether the backend provides an implementation of this
+ * class.
+ *
+ * \return \c true if backend provides an implementation
+ * \return \c false if the object is not implemented by the backend
+ */
+ bool isValid() const;
+
+ QList<Path> inputPaths() const;
+ QList<Path> outputPaths() const;
+
+ protected:
+ MediaNode(MediaNodePrivate &dd);
+ MediaNodePrivate *const k_ptr;
+ };
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_MEDIANODE_H
diff --git a/src/3rdparty/phonon/phonon/medianode_p.h b/src/3rdparty/phonon/phonon/medianode_p.h
new file mode 100644
index 0000000..e2329a9
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/medianode_p.h
@@ -0,0 +1,145 @@
+/* This file is part of the KDE project
+Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MEDIANODE_P_H
+#define PHONON_MEDIANODE_P_H
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include "path.h"
+#include "phonon_export.h"
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+
+namespace Phonon
+{
+ class MediaNode;
+ class MediaNodeDestructionHandler;
+
+ class PHONON_EXPORT MediaNodePrivate
+ {
+ Q_DECLARE_PUBLIC(MediaNode)
+
+ friend class AudioOutputPrivate;
+ friend class FactoryPrivate;
+
+ protected:
+ enum CastId {
+ MediaNodePrivateType,
+ AbstractAudioOutputPrivateType,
+ AudioOutputType
+ };
+ public:
+ /**
+ * Returns the backend object. If the object does not exist it tries to
+ * create it before returning.
+ *
+ * \return the Iface object, might return \c 0
+ */
+ QObject *backendObject();
+
+ const CastId castId;
+
+ protected:
+ MediaNodePrivate(CastId _castId = MediaNodePrivateType);
+
+ virtual ~MediaNodePrivate();
+
+ /**
+ * \internal
+ * This method cleanly deletes the Iface object. It is called on
+ * destruction and before a backend change.
+ */
+ void deleteBackendObject();
+
+ virtual bool aboutToDeleteBackendObject() = 0;
+
+ /**
+ * \internal
+ * Creates the Iface object belonging to this class. For most cases the
+ * implementation is
+ * \code
+ * Q_Q(ClassName);
+ * m_iface = Factory::createClassName(this);
+ * return m_iface;
+ * \endcode
+ *
+ * This function should not be called except from slotCreateIface.
+ *
+ * \see slotCreateIface
+ */
+ virtual void createBackendObject() = 0;
+
+ public:
+ /**
+ * \internal
+ * This class has its own destroyed signal since some cleanup calls
+ * need the pointer to the backend object intact. The
+ * QObject::destroyed signals comes after the backend object was
+ * deleted.
+ *
+ * As this class cannot derive from QObject a simple handler
+ * interface is used.
+ */
+ void addDestructionHandler(MediaNodeDestructionHandler *handler);
+
+ /**
+ * \internal
+ * This class has its own destroyed signal since some cleanup calls
+ * need the pointer to the backend object intact. The
+ * QObject::destroyed signals comes after the backend object was
+ * deleted.
+ *
+ * As this class cannot derive from QObject a simple handler
+ * interface is used.
+ */
+ void removeDestructionHandler(MediaNodeDestructionHandler *handler);
+
+ void addOutputPath(const Path &);
+ void addInputPath(const Path &);
+ void removeOutputPath(const Path &);
+ void removeInputPath(const Path &);
+
+ const QObject *qObject() const { return const_cast<MediaNodePrivate *>(this)->qObject(); }
+ virtual QObject *qObject() { return 0; }
+
+ protected:
+ MediaNode *q_ptr;
+ public:
+ QObject *m_backendObject;
+ protected:
+ QList<Path> outputPaths;
+ QList<Path> inputPaths;
+
+ private:
+ QList<MediaNodeDestructionHandler *> handlers;
+ Q_DISABLE_COPY(MediaNodePrivate)
+ };
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // PHONON_MEDIANODE_P_H
diff --git a/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h b/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h
new file mode 100644
index 0000000..9c893f4
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MEDIANODEDESTRUCTIONHANDLER_P_H
+#define MEDIANODEDESTRUCTIONHANDLER_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+/**
+ * \internal
+ *
+ * Callback interface to keep track of Phonon frontend object destruction.
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+
+class MediaNodePrivate;
+
+class MediaNodeDestructionHandler
+{
+ friend class MediaNodePrivate;
+
+public:
+ virtual ~MediaNodeDestructionHandler() {}
+protected:
+ /**
+ * \internal
+ * called from Base::~Base if this object was registered
+ * using BasePrivate::addDestructionHandler().
+ */
+ virtual void phononObjectDestroyed(MediaNodePrivate *) = 0;
+};
+}
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // MEDIANODEDESTRUCTIONHANDLER_P_H
diff --git a/src/3rdparty/phonon/phonon/mediaobject.cpp b/src/3rdparty/phonon/phonon/mediaobject.cpp
new file mode 100644
index 0000000..13d303c
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediaobject.cpp
@@ -0,0 +1,572 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "mediaobject.h"
+#include "mediaobject_p.h"
+
+#include "factory_p.h"
+#include "mediaobjectinterface.h"
+#include "audiooutput.h"
+#include "phonondefs_p.h"
+#include "abstractmediastream.h"
+#include "abstractmediastream_p.h"
+#include "frontendinterface_p.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+#include <QtCore/QTimer>
+
+#include "phononnamespace_p.h"
+#include "platform_p.h"
+
+#define PHONON_CLASSNAME MediaObject
+#define PHONON_INTERFACENAME MediaObjectInterface
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+PHONON_OBJECT_IMPL
+
+MediaObject::~MediaObject()
+{
+ K_D(MediaObject);
+ if (d->m_backendObject) {
+ switch (state()) {
+ case PlayingState:
+ case BufferingState:
+ case PausedState:
+ stop();
+ break;
+ case ErrorState:
+ case StoppedState:
+ case LoadingState:
+ break;
+ }
+ }
+}
+
+Phonon::State MediaObject::state() const
+{
+ K_D(const MediaObject);
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (d->errorOverride) {
+ return d->state;
+ }
+ if (d->ignoreLoadingToBufferingStateChange) {
+ return BufferingState;
+ }
+ if (d->ignoreErrorToLoadingStateChange) {
+ return LoadingState;
+ }
+#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (!d->m_backendObject) {
+ return d->state;
+ }
+ return INTERFACE_CALL(state());
+}
+
+PHONON_INTERFACE_SETTER(setTickInterval, tickInterval, qint32)
+PHONON_INTERFACE_GETTER(qint32, tickInterval, d->tickInterval)
+PHONON_INTERFACE_GETTER(bool, hasVideo, false)
+PHONON_INTERFACE_GETTER(bool, isSeekable, false)
+PHONON_INTERFACE_GETTER(qint64, currentTime, d->currentTime)
+
+static inline bool isPlayable(const MediaSource::Type t)
+{
+ return t != MediaSource::Invalid && t != MediaSource::Empty;
+}
+
+void MediaObject::play()
+{
+ K_D(MediaObject);
+ if (d->backendObject() && isPlayable(d->mediaSource.type())) {
+ INTERFACE_CALL(play());
+ }
+}
+
+void MediaObject::pause()
+{
+ K_D(MediaObject);
+ if (d->backendObject() && isPlayable(d->mediaSource.type())) {
+ INTERFACE_CALL(pause());
+ }
+}
+
+void MediaObject::stop()
+{
+ K_D(MediaObject);
+ if (d->backendObject() && isPlayable(d->mediaSource.type())) {
+ INTERFACE_CALL(stop());
+ }
+}
+
+void MediaObject::seek(qint64 time)
+{
+ K_D(MediaObject);
+ if (d->backendObject() && isPlayable(d->mediaSource.type())) {
+ INTERFACE_CALL(seek(time));
+ }
+}
+
+QString MediaObject::errorString() const
+{
+ if (state() == Phonon::ErrorState) {
+ K_D(const MediaObject);
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (d->errorOverride) {
+ return d->errorString;
+ }
+#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ return INTERFACE_CALL(errorString());
+ }
+ return QString();
+}
+
+ErrorType MediaObject::errorType() const
+{
+ if (state() == Phonon::ErrorState) {
+ K_D(const MediaObject);
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (d->errorOverride) {
+ return d->errorType;
+ }
+#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ return INTERFACE_CALL(errorType());
+ }
+ return Phonon::NoError;
+}
+
+QStringList MediaObject::metaData(Phonon::MetaData f) const
+{
+ switch (f) {
+ case ArtistMetaData:
+ return metaData(QLatin1String("ARTIST" ));
+ case AlbumMetaData:
+ return metaData(QLatin1String("ALBUM" ));
+ case TitleMetaData:
+ return metaData(QLatin1String("TITLE" ));
+ case DateMetaData:
+ return metaData(QLatin1String("DATE" ));
+ case GenreMetaData:
+ return metaData(QLatin1String("GENRE" ));
+ case TracknumberMetaData:
+ return metaData(QLatin1String("TRACKNUMBER"));
+ case DescriptionMetaData:
+ return metaData(QLatin1String("DESCRIPTION"));
+ case MusicBrainzDiscIdMetaData:
+ return metaData(QLatin1String("MUSICBRAINZ_DISCID"));
+ }
+ return QStringList();
+}
+
+QStringList MediaObject::metaData(const QString &key) const
+{
+ K_D(const MediaObject);
+ return d->metaData.values(key);
+}
+
+QMultiMap<QString, QString> MediaObject::metaData() const
+{
+ K_D(const MediaObject);
+ return d->metaData;
+}
+
+PHONON_INTERFACE_GETTER(qint32, prefinishMark, d->prefinishMark)
+PHONON_INTERFACE_SETTER(setPrefinishMark, prefinishMark, qint32)
+
+PHONON_INTERFACE_GETTER(qint32, transitionTime, d->transitionTime)
+PHONON_INTERFACE_SETTER(setTransitionTime, transitionTime, qint32)
+
+qint64 MediaObject::totalTime() const
+{
+ K_D(const MediaObject);
+ if (!d->m_backendObject) {
+ return -1;
+ }
+ return INTERFACE_CALL(totalTime());
+}
+
+qint64 MediaObject::remainingTime() const
+{
+ K_D(const MediaObject);
+ if (!d->m_backendObject) {
+ return -1;
+ }
+ qint64 ret = INTERFACE_CALL(remainingTime());
+ if (ret < 0) {
+ return -1;
+ }
+ return ret;
+}
+
+MediaSource MediaObject::currentSource() const
+{
+ K_D(const MediaObject);
+ return d->mediaSource;
+}
+
+void MediaObject::setCurrentSource(const MediaSource &newSource)
+{
+ K_D(MediaObject);
+ if (!k_ptr->backendObject()) {
+ d->mediaSource = newSource;
+ return;
+ }
+
+ pDebug() << Q_FUNC_INFO << newSource.url();
+
+ stop(); // first call stop as that often is the expected state
+ // for setting a new URL
+
+ d->mediaSource = newSource;
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ d->kiofallback = 0; // kiofallback auto-deletes
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+//X if (url.scheme() == "http") {
+//X d->kiofallback = Platform::createMediaStream(url, this);
+//X if (d->kiofallback) {
+//X ...
+//X return;
+//X }
+//X }
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (d->mediaSource.type() == MediaSource::Stream) {
+ Q_ASSERT(d->mediaSource.stream());
+ d->mediaSource.stream()->d_func()->setMediaObjectPrivate(d);
+ }
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+ INTERFACE_CALL(setSource(d->mediaSource));
+}
+
+void MediaObject::clear()
+{
+ K_D(MediaObject);
+ d->sourceQueue.clear();
+ setCurrentSource(MediaSource());
+}
+
+QList<MediaSource> MediaObject::queue() const
+{
+ K_D(const MediaObject);
+ return d->sourceQueue;
+}
+
+void MediaObject::setQueue(const QList<MediaSource> &sources)
+{
+ K_D(MediaObject);
+ d->sourceQueue.clear();
+ enqueue(sources);
+}
+
+void MediaObject::setQueue(const QList<QUrl> &urls)
+{
+ K_D(MediaObject);
+ d->sourceQueue.clear();
+ enqueue(urls);
+}
+
+void MediaObject::enqueue(const MediaSource &source)
+{
+ K_D(MediaObject);
+ if (!isPlayable(d->mediaSource.type())) {
+ // the current source is nothing valid so this source needs to become the current one
+ setCurrentSource(source);
+ } else {
+ d->sourceQueue << source;
+ }
+}
+
+void MediaObject::enqueue(const QList<MediaSource> &sources)
+{
+ for (int i = 0; i < sources.count(); ++i) {
+ enqueue(sources.at(i));
+ }
+}
+
+void MediaObject::enqueue(const QList<QUrl> &urls)
+{
+ for (int i = 0; i < urls.count(); ++i) {
+ enqueue(urls.at(i));
+ }
+}
+
+void MediaObject::clearQueue()
+{
+ K_D(MediaObject);
+ d->sourceQueue.clear();
+}
+
+bool MediaObjectPrivate::aboutToDeleteBackendObject()
+{
+ //pDebug() << Q_FUNC_INFO;
+ prefinishMark = pINTERFACE_CALL(prefinishMark());
+ transitionTime = pINTERFACE_CALL(transitionTime());
+ //pDebug() << Q_FUNC_INFO;
+ if (m_backendObject) {
+ state = pINTERFACE_CALL(state());
+ currentTime = pINTERFACE_CALL(currentTime());
+ tickInterval = pINTERFACE_CALL(tickInterval());
+ }
+ return true;
+}
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+void MediaObjectPrivate::streamError(Phonon::ErrorType type, const QString &text)
+{
+ Q_Q(MediaObject);
+ State lastState = q->state();
+ errorOverride = true;
+ errorType = type;
+ errorString = text;
+ state = ErrorState;
+ QMetaObject::invokeMethod(q, "stateChanged", Qt::QueuedConnection, Q_ARG(Phonon::State, Phonon::ErrorState), Q_ARG(Phonon::State, lastState));
+ //emit q->stateChanged(ErrorState, lastState);
+}
+
+void MediaObjectPrivate::_k_stateChanged(Phonon::State newstate, Phonon::State oldstate)
+{
+ Q_Q(MediaObject);
+ if (mediaSource.type() != MediaSource::Url) {
+ // special handling only necessary for URLs because of the fallback
+ emit q->stateChanged(newstate, oldstate);
+ return;
+ }
+
+ if (errorOverride) {
+ errorOverride = false;
+ if (newstate == ErrorState) {
+ return;
+ }
+ oldstate = ErrorState;
+ }
+
+ // backend MediaObject reached ErrorState, try a KioMediaSource
+ if (newstate == Phonon::ErrorState && !kiofallback) {
+ kiofallback = Platform::createMediaStream(mediaSource.url(), q);
+ if (!kiofallback) {
+ pDebug() << "backend MediaObject reached ErrorState, no KIO fallback available";
+ emit q->stateChanged(newstate, oldstate);
+ return;
+ }
+ pDebug() << "backend MediaObject reached ErrorState, trying Platform::createMediaStream now";
+ ignoreLoadingToBufferingStateChange = false;
+ ignoreErrorToLoadingStateChange = false;
+ switch (oldstate) {
+ case Phonon::BufferingState:
+ // play() has already been called, we need to make sure it is called
+ // on the backend with the KioMediaStream MediaSource now, too
+ ignoreLoadingToBufferingStateChange = true;
+ break;
+ case Phonon::LoadingState:
+ ignoreErrorToLoadingStateChange = true;
+ // no extras
+ break;
+ default:
+ pError() << "backend MediaObject reached ErrorState after " << oldstate
+ << ". It seems a KioMediaStream will not help here, trying anyway.";
+ emit q->stateChanged(Phonon::LoadingState, oldstate);
+ break;
+ }
+ kiofallback->d_func()->setMediaObjectPrivate(this);
+ MediaSource mediaSource(kiofallback);
+ mediaSource.setAutoDelete(true);
+ pINTERFACE_CALL(setSource(mediaSource));
+ if (oldstate == Phonon::BufferingState) {
+ q->play();
+ }
+ return;
+ } else if (ignoreLoadingToBufferingStateChange &&
+ kiofallback &&
+ oldstate == Phonon::LoadingState) {
+ if (newstate != Phonon::BufferingState) {
+ emit q->stateChanged(newstate, Phonon::BufferingState);
+ }
+ return;
+ } else if (ignoreErrorToLoadingStateChange && kiofallback && oldstate == ErrorState) {
+ if (newstate != LoadingState) {
+ emit q->stateChanged(newstate, Phonon::LoadingState);
+ }
+ return;
+ }
+
+ emit q->stateChanged(newstate, oldstate);
+}
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+void MediaObjectPrivate::_k_aboutToFinish()
+{
+ Q_Q(MediaObject);
+ pDebug() << Q_FUNC_INFO;
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ kiofallback = 0; // kiofallback auto-deletes
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+ if (sourceQueue.isEmpty()) {
+ emit q->aboutToFinish();
+ if (sourceQueue.isEmpty()) {
+ return;
+ }
+ }
+
+ mediaSource = sourceQueue.head();
+ pINTERFACE_CALL(setNextSource(mediaSource));
+}
+
+void MediaObjectPrivate::_k_currentSourceChanged(const MediaSource &source)
+{
+ Q_Q(MediaObject);
+ pDebug() << Q_FUNC_INFO;
+
+ if (!sourceQueue.isEmpty() && sourceQueue.head() == source)
+ sourceQueue.dequeue();
+
+ emit q->currentSourceChanged(source);
+}
+
+void MediaObjectPrivate::setupBackendObject()
+{
+ Q_Q(MediaObject);
+ Q_ASSERT(m_backendObject);
+ //pDebug() << Q_FUNC_INFO;
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), q, SLOT(_k_stateChanged(Phonon::State, Phonon::State)));
+#else
+ QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), q, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
+#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ QObject::connect(m_backendObject, SIGNAL(tick(qint64)), q, SIGNAL(tick(qint64)));
+ QObject::connect(m_backendObject, SIGNAL(seekableChanged(bool)), q, SIGNAL(seekableChanged(bool)));
+#ifndef QT_NO_PHONON_VIDEO
+ QObject::connect(m_backendObject, SIGNAL(hasVideoChanged(bool)), q, SIGNAL(hasVideoChanged(bool)));
+#endif //QT_NO_PHONON_VIDEO
+ QObject::connect(m_backendObject, SIGNAL(bufferStatus(int)), q, SIGNAL(bufferStatus(int)));
+ QObject::connect(m_backendObject, SIGNAL(finished()), q, SIGNAL(finished()));
+ QObject::connect(m_backendObject, SIGNAL(aboutToFinish()), q, SLOT(_k_aboutToFinish()));
+ QObject::connect(m_backendObject, SIGNAL(prefinishMarkReached(qint32)), q, SIGNAL(prefinishMarkReached(qint32)));
+ QObject::connect(m_backendObject, SIGNAL(totalTimeChanged(qint64)), q, SIGNAL(totalTimeChanged(qint64)));
+ QObject::connect(m_backendObject, SIGNAL(metaDataChanged(const QMultiMap<QString, QString> &)),
+ q, SLOT(_k_metaDataChanged(const QMultiMap<QString, QString> &)));
+ QObject::connect(m_backendObject, SIGNAL(currentSourceChanged(const MediaSource&)),
+ q, SLOT(_k_currentSourceChanged(const MediaSource&)));
+
+ // set up attributes
+ pINTERFACE_CALL(setTickInterval(tickInterval));
+ pINTERFACE_CALL(setPrefinishMark(prefinishMark));
+ pINTERFACE_CALL(setTransitionTime(transitionTime));
+
+ switch(state)
+ {
+ case LoadingState:
+ case StoppedState:
+ case ErrorState:
+ break;
+ case PlayingState:
+ case BufferingState:
+ QTimer::singleShot(0, q, SLOT(_k_resumePlay()));
+ break;
+ case PausedState:
+ QTimer::singleShot(0, q, SLOT(_k_resumePause()));
+ break;
+ }
+ const State backendState = pINTERFACE_CALL(state());
+ if (state != backendState && state != ErrorState) {
+ // careful: if state is ErrorState we might be switching from a
+ // MediaObject to a ByteStream for KIO fallback. In that case the state
+ // change to ErrorState was already suppressed.
+ pDebug() << "emitting a state change because the backend object has been replaced";
+ emit q->stateChanged(backendState, state);
+ state = backendState;
+ }
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ for (int i = 0 ; i < interfaceList.count(); ++i) {
+ interfaceList.at(i)->_backendObjectChanged();
+ }
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+ // set up attributes
+ if (isPlayable(mediaSource.type())) {
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (mediaSource.type() == MediaSource::Stream) {
+ Q_ASSERT(mediaSource.stream());
+ mediaSource.stream()->d_func()->setMediaObjectPrivate(this);
+ }
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ pINTERFACE_CALL(setSource(mediaSource));
+ }
+}
+
+void MediaObjectPrivate::_k_resumePlay()
+{
+ qobject_cast<MediaObjectInterface *>(m_backendObject)->play();
+ if (currentTime > 0) {
+ qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime);
+ }
+}
+
+void MediaObjectPrivate::_k_resumePause()
+{
+ pINTERFACE_CALL(pause());
+ if (currentTime > 0) {
+ qobject_cast<MediaObjectInterface *>(m_backendObject)->seek(currentTime);
+ }
+}
+
+void MediaObjectPrivate::_k_metaDataChanged(const QMultiMap<QString, QString> &newMetaData)
+{
+ metaData = newMetaData;
+ emit q_func()->metaDataChanged();
+}
+
+void MediaObjectPrivate::phononObjectDestroyed(MediaNodePrivate *bp)
+{
+ // this method is called from Phonon::Base::~Base(), meaning the AudioPath
+ // dtor has already been called, also virtual functions don't work anymore
+ // (therefore qobject_cast can only downcast from Base)
+ Q_ASSERT(bp);
+ Q_UNUSED(bp);
+}
+
+MediaObject *createPlayer(Phonon::Category category, const MediaSource &source)
+{
+ MediaObject *mo = new MediaObject;
+ AudioOutput *ao = new AudioOutput(category, mo);
+ createPath(mo, ao);
+ if (isPlayable(source.type())) {
+ mo->setCurrentSource(source);
+ }
+ return mo;
+}
+
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_mediaobject.cpp"
+
+#undef PHONON_CLASSNAME
+#undef PHONON_INTERFACENAME
+// vim: sw=4 tw=100 et
diff --git a/src/3rdparty/phonon/phonon/mediaobject.dox b/src/3rdparty/phonon/phonon/mediaobject.dox
new file mode 100644
index 0000000..cc6fe5f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediaobject.dox
@@ -0,0 +1,71 @@
+/**
+\page phonon_MediaObject The MediaObject class
+
+\section phonon_MediaObject_derived Media Data Producing Class
+
+There is the class that produces the media data (often called a source in
+media frameworks).
+
+\section phonon_MediaObject_requiredfunctions Required Functions
+\li qint32 \ref phonon_MediaObject_prefinishMark "prefinishMark()"
+\li void \ref phonon_MediaObject_setPrefinishMark "setPrefinishMark(qint32)"
+
+\section phonon_MediaObject_optionalfunctions Optional Functions
+\li qint64 \ref phonon_MediaObject_remainingTime "remainingTime()"
+
+\section phonon_MediaObject_signals Signals
+\li void \ref phonon_MediaObject_totalTimeChanged "totalTimeChanged(qint64 totalTime)"
+\li void \ref phonon_MediaObject_prefinishMarkReached "prefinishMarkReached(qint32 msec)"
+\li void \ref phonon_MediaObject_finished "finished()"
+
+\section phonon_MediaObject_memberdocs Member Function Documentation
+
+\see \ref phonon_MediaObject_totalTimeChanged
+
+\subsection phonon_MediaObject_prefinishMark qint32 prefinishMark()
+Returns the time in milliseconds the \ref phonon_MediaObject_prefinishMarkReached
+"prefinishMarkReached" signal is emitted before the playback if finished and \ref
+phonon_MediaObject_finished "finished" is emitted.
+
+\subsection phonon_MediaObject_setPrefinishMark void setPrefinishMark(qint32 msec)
+Sets the time in milliseconds the \ref phonon_MediaObject_prefinishMarkReached
+"prefinishMarkReached" signal is emitted before the playback if finished and \ref
+phonon_MediaObject_finished "finished" is emitted.
+
+\param msec The time in milliseconds. If the value is less than or equal to 0
+the \ref phonon_MediaObject_prefinishMarkReached "prefinishMarkReached" signal is disabled.
+
+\subsection phonon_MediaObject_remainingTime qint64 remainingTime()
+Get the remaining time (in milliseconds) of the file currently being played. If
+the method is not implemented in the backend the frontend will use the
+difference between \link Phonon::MediaObjectInterface::totalTime() MediaObjectInterface::totalTime() \endlink and
+\link Phonon::MediaObjectInterface::currentTime() MediaObjectInterface::currentTime() \endlink.
+
+\section phonon_MediaObject_signaldocs Signals Documentation
+\subsection phonon_MediaObject_prefinishMarkReached void prefinishMarkReached(qint32 msec)
+Emitted when the file has finished playing on its own.
+I.e. it is not emitted if you call stop(), pause() or
+load(), but only on end-of-file or a critical error.
+void finished()
+
+\param msec The remaining time until the playback finishes
+
+\subsection phonon_MediaObject_totalTimeChanged void totalTimeChanged(qint64 totalTime)
+This signal is emitted as soon as the length of the media file is
+known or has changed. For most non-local media data the length of
+the media can only be known after some time. At that time the
+totalTime function can not return useful information. You have
+to wait for this signal to know the real length.
+
+\param totalTimeChanged The total time of the media file in milliseconds.
+
+\see \link Phonon::MediaObjectInterface::totalTime() MediaObjectInterface::totalTime() \endlink
+
+\subsection phonon_MediaObject_finished void finished()
+This signal is emitted when the playback of the media finished (on its own).
+It is not emitted if stop() or pause() are called - only on end-of-file or a
+critical error (for example the media data stream is corrupted and playback of
+the media has to be finished).
+
+\see \ref phonon_MediaObject_prefinishMarkReached
+*/
diff --git a/src/3rdparty/phonon/phonon/mediaobject.h b/src/3rdparty/phonon/phonon/mediaobject.h
new file mode 100644
index 0000000..ade966a
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediaobject.h
@@ -0,0 +1,623 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef Phonon_MEDIAOBJECT_H
+#define Phonon_MEDIAOBJECT_H
+
+#include "medianode.h"
+#include "mediasource.h"
+#include "phonon_export.h"
+#include "phonondefs.h"
+#include "phononnamespace.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class MediaObjectPrivate;
+
+ /** \class MediaObject mediaobject.h Phonon/MediaObject
+ * \short Interface for media playback of a given URL.
+ *
+ * This class is the most important class in %Phonon. Use it to open a media
+ * file at an arbitrary location, a CD or DVD or to stream media data from
+ * the application to the backend.
+ *
+ * This class controls the state (play, pause, stop, seek)
+ * and you can use it to get a lot of information about the media data.
+ *
+ * Notice that most functions of this class are asynchronous.
+ * That means if you call play() the object only starts playing when the
+ * stateChanged() signal tells you that the object changed into PlayingState.
+ * The states you can expect are documented for those methods.
+ *
+ * A common usage example is the following:
+ * \code
+ * media = new MediaObject(this);
+ * connect(media, SIGNAL(finished()), SLOT(slotFinished());
+ * media->setCurrentSource("/home/username/music/filename.ogg");
+ * media->play();
+ * \endcode
+ *
+ * If you want to play more than one media file (one after another) you can
+ * either tell MediaObject about all those files
+ * \code
+ * media->setCurrentSource(":/sounds/startsound.ogg");
+ * media->enqueue("/home/username/music/song.mp3");
+ * media->enqueue(":/sounds/endsound.ogg");
+ * \endcode
+ * or provide the next file just in time:
+ * \code
+ * media->setCurrentSource(":/sounds/startsound.ogg");
+ * connect(media, SIGNAL(aboutToFinish()), SLOT(enqueueNextSource()));
+ * }
+ *
+ * void enqueueNextSource()
+ * {
+ * media->enqueue("/home/username/music/song.mp3");
+ * }
+ * \endcode
+ *
+ * \ingroup Playback
+ * \ingroup Recording
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class PHONON_EXPORT MediaObject : public QObject, public MediaNode
+ {
+ friend class FrontendInterfacePrivate;
+ Q_OBJECT
+ K_DECLARE_PRIVATE(MediaObject)
+ PHONON_OBJECT(MediaObject)
+ /**
+ * \brief Defines the time between media sources.
+ *
+ * A positive transition time defines a gap of silence between queued
+ * media sources.
+ *
+ * A transition time of 0 ms requests gapless playback (sample precise
+ * queueing of the next source).
+ *
+ * A negative transition time defines a crossfade between the queued
+ * media sources.
+ *
+ * Defaults to 0 (gapless playback).
+ *
+ * \warning This feature might not work reliably on every platform.
+ */
+ Q_PROPERTY(qint32 transitionTime READ transitionTime WRITE setTransitionTime)
+
+ /**
+ * \brief Get a signal before playback finishes.
+ *
+ * This property specifies the time in milliseconds the
+ * prefinishMarkReached signal is
+ * emitted before the playback finishes. A value of \c 0 disables the
+ * signal.
+ *
+ * Defaults to \c 0 (disabled).
+ *
+ * \warning For some media data the total time cannot be determined
+ * accurately, therefore the accuracy of the prefinishMarkReached signal
+ * can be bad sometimes. Still, it is better to use this method than to
+ * look at totalTime() and currentTime() to emulate the behaviour
+ * because the backend might have more information available than your
+ * application does through totalTime and currentTime.
+ *
+ * \see prefinishMarkReached
+ */
+ Q_PROPERTY(qint32 prefinishMark READ prefinishMark WRITE setPrefinishMark)
+
+ /**
+ * \brief The time interval in milliseconds between two ticks.
+ *
+ * The %tick interval is the time that elapses between the emission of two tick signals.
+ * If you set the interval to \c 0 the tick signal gets disabled.
+ *
+ * Defaults to \c 0 (disabled).
+ *
+ * \warning The back-end is free to choose a different tick interval close
+ * to what you asked for. This means that the following code \em may \em fail:
+ * \code
+ * int x = 200;
+ * media->setTickInterval(x);
+ * Q_ASSERT(x == producer->tickInterval());
+ * \endcode
+ * On the other hand the following is guaranteed:
+ * \code
+ * int x = 200;
+ * media->setTickInterval(x);
+ * Q_ASSERT(x >= producer->tickInterval() &&
+ * x <= 2 * producer->tickInterval());
+ * \endcode
+ *
+ * \see tick
+ */
+ Q_PROPERTY(qint32 tickInterval READ tickInterval WRITE setTickInterval)
+ public:
+ /**
+ * Destroys the MediaObject.
+ */
+ ~MediaObject();
+
+ /**
+ * Get the current state.
+ *
+ * @return The state of the object.
+ *
+ * @see State
+ * \see stateChanged
+ */
+ State state() const;
+
+ /**
+ * Check whether the media data includes a video stream.
+ *
+ * \warning This information cannot be known immediately. It is best
+ * to also listen to the hasVideoChanged signal.
+ *
+ * \code
+ * connect(media, SIGNAL(hasVideoChanged(bool)), hasVideoChanged(bool));
+ * media->setCurrentSource("somevideo.avi");
+ * media->hasVideo(); // returns false;
+ * }
+ *
+ * void hasVideoChanged(bool b)
+ * {
+ * // b == true
+ * media->hasVideo(); // returns true;
+ * }
+ * \endcode
+ *
+ * \return \c true if the media contains video data. \c false
+ * otherwise.
+ *
+ * \see hasVideoChanged
+ */
+ bool hasVideo() const;
+
+ /**
+ * Check whether the current media may be seeked.
+ *
+ * \warning This information cannot be known immediately. It is best
+ * to also listen to the seekableChanged signal.
+ *
+ * \code
+ * connect(media, SIGNAL(seekableChanged(bool)), seekableChanged(bool));
+ * media->setCurrentSource("somevideo.avi");
+ * media->isSeekable(); // returns false;
+ * }
+ *
+ * void seekableChanged(bool b)
+ * {
+ * // b == true
+ * media->isSeekable(); // returns true;
+ * }
+ * \endcode
+ *
+ * \return \c true when the current media may be seeked. \c false
+ * otherwise.
+ *
+ * \see seekableChanged()
+ */
+ bool isSeekable() const;
+
+ qint32 tickInterval() const;
+
+ /**
+ * Returns the strings associated with the given \p key.
+ *
+ * Backends should use the keys specified in the Ogg Vorbis
+ * documentation: http://xiph.org/vorbis/doc/v-comment.html
+ *
+ * Therefore the following should work with every backend:
+ *
+ * A typical usage looks like this:
+ * \code
+ * setMetaArtist (media->metaData("ARTIST" ));
+ * setMetaAlbum (media->metaData("ALBUM" ));
+ * setMetaTitle (media->metaData("TITLE" ));
+ * setMetaDate (media->metaData("DATE" ));
+ * setMetaGenre (media->metaData("GENRE" ));
+ * setMetaTrack (media->metaData("TRACKNUMBER"));
+ * setMetaComment(media->metaData("DESCRIPTION"));
+ * \endcode
+ *
+ * For Audio CDs you can query
+ * \code
+ * metaData("MUSICBRAINZ_DISCID");
+ * \endcode
+ * to get a DiscID hash that you can use with the MusicBrainz
+ * service:
+ * http://musicbrainz.org/doc/ClientHOWTO
+ */
+ QStringList metaData(const QString &key) const;
+
+ /**
+ * Returns the strings associated with the given \p key.
+ *
+ * Same as above except that the keys are defined in the
+ * Phonon::MetaData enum.
+ */
+ QStringList metaData(Phonon::MetaData key) const;
+
+ /**
+ * Returns all meta data.
+ */
+ QMultiMap<QString, QString> metaData() const;
+
+ /**
+ * Returns a human-readable description of the last error that occurred.
+ */
+ QString errorString() const;
+
+ /**
+ * Tells your program what to do about the error.
+ *
+ * \see Phonon::ErrorType
+ */
+ ErrorType errorType() const;
+
+ /**
+ * Returns the current media source.
+ *
+ * \see setCurrentSource
+ */
+ MediaSource currentSource() const;
+
+ /**
+ * Set the media source the MediaObject should use.
+ *
+ * \param source The MediaSource object to the media data. You can
+ * just as well use a QUrl or QString (for a local file) here.
+ * Setting an empty (invalid) source, will stop and remove the
+ * current source.
+ *
+ * \code
+ * QUrl url("http://www.example.com/music.ogg");
+ * media->setCurrentSource(url);
+ * \endcode
+ *
+ * \see currentSource
+ */
+ void setCurrentSource(const MediaSource &source);
+
+ /**
+ * Returns the queued media sources. This list does not include
+ * the current source (returned by currentSource).
+ */
+ QList<MediaSource> queue() const;
+
+ /**
+ * Set the MediaSources to play when the current media has finished.
+ *
+ * This function will overwrite the current queue.
+ *
+ * \see clearQueue
+ * \see enqueue
+ */
+ void setQueue(const QList<MediaSource> &sources);
+
+ /**
+ * Set the MediaSources to play when the current media has finished.
+ *
+ * This function overwrites the current queue.
+ *
+ * \see clearQueue
+ * \see enqueue
+ */
+ void setQueue(const QList<QUrl> &urls);
+
+ /**
+ * Appends one source to the queue. Use this function to provide
+ * the next source just in time after the aboutToFinish signal was
+ * emitted.
+ *
+ * \see aboutToFinish
+ * \see setQueue
+ * \see clearQueue
+ */
+ void enqueue(const MediaSource &source);
+
+ /**
+ * Appends multiple sources to the queue.
+ *
+ * \see setQueue
+ * \see clearQueue
+ */
+ void enqueue(const QList<MediaSource> &sources);
+
+ /**
+ * Appends multiple sources to the queue.
+ *
+ * \see setQueue
+ * \see clearQueue
+ */
+ void enqueue(const QList<QUrl> &urls);
+
+ /**
+ * Clears the queue of sources.
+ */
+ void clearQueue();
+
+ /**
+ * Get the current time (in milliseconds) of the file currently being played.
+ *
+ * \return The current time in milliseconds.
+ *
+ * \see tick
+ */
+ qint64 currentTime() const;
+
+ /**
+ * Get the total time (in milliseconds) of the file currently being played.
+ *
+ * \return The total time in milliseconds.
+ *
+ * \see totalTimeChanged
+ */
+ qint64 totalTime() const;
+
+ /**
+ * Get the remaining time (in milliseconds) of the file currently being played.
+ *
+ * \return The remaining time in milliseconds.
+ */
+ qint64 remainingTime() const;
+
+ qint32 prefinishMark() const;
+ void setPrefinishMark(qint32 msecToEnd);
+
+ qint32 transitionTime() const;
+ void setTransitionTime(qint32 msec);
+
+ public Q_SLOTS:
+
+ void setTickInterval(qint32 newTickInterval);
+
+ /**
+ * Requests playback of the media data to start. Playback only
+ * starts when stateChanged() signals that it goes into PlayingState,
+ * though.
+ *
+ * \par Possible states right after this call:
+ * \li BufferingState
+ * \li PlayingState
+ * \li ErrorState
+ */
+ void play();
+
+ /**
+ * Requests playback to pause. If it was paused before nothing changes.
+ *
+ * \par Possible states right after this call:
+ * \li PlayingState
+ * \li PausedState
+ * \li ErrorState
+ */
+ void pause();
+
+ /**
+ * Requests playback to stop. If it was stopped before nothing changes.
+ *
+ * \par Possible states right after this call:
+ * \li the state it was in before (e.g. PlayingState)
+ * \li StoppedState
+ * \li ErrorState
+ */
+ void stop();
+
+ /**
+ * Requests a seek to the time indicated.
+ *
+ * You can only seek if state() == PlayingState, BufferingState or PausedState.
+ *
+ * The call is asynchronous, so currentTime can still be the old
+ * value right after this method was called. If all you need is a
+ * slider that shows the current position and allows the user to
+ * seek use the class SeekSlider.
+ *
+ * @param time The time in milliseconds where to continue playing.
+ *
+ * \par Possible states right after this call:
+ * \li BufferingState
+ * \li PlayingState
+ * \li ErrorState
+ *
+ * \see SeekSlider
+ */
+ void seek(qint64 time);
+
+ /**
+ * Stops and removes all playing and enqueued media sources.
+ *
+ * \see setCurrentSource
+ */
+ void clear();
+
+ Q_SIGNALS:
+ /**
+ * Emitted when the state of the MediaObject has changed.
+ *
+ * @param newstate The state the Player is in now.
+ * @param oldstate The state the Player was in before.
+ */
+ void stateChanged(Phonon::State newstate, Phonon::State oldstate);
+
+ /**
+ * This signal gets emitted every tickInterval milliseconds.
+ *
+ * @param time The position of the media file in milliseconds.
+ *
+ * @see setTickInterval, tickInterval
+ */
+ void tick(qint64 time);
+
+ /**
+ * This signal is emitted whenever the audio/video data that is
+ * being played is associated with new meta data. E.g. for radio
+ * streams this happens when the next song is played.
+ *
+ * You can get the new meta data with the metaData methods.
+ */
+ void metaDataChanged();
+
+ /**
+ * Emitted whenever the return value of isSeekable() changes.
+ *
+ * Normally you'll check isSeekable() first and then let this signal
+ * tell you whether seeking is possible now or not. That way you
+ * don't have to poll isSeekable().
+ *
+ * \param isSeekable \p true if the stream is seekable (i.e. calling
+ * seek() works)
+ * \p false if the stream is not seekable (i.e.
+ * all calls to seek() will be ignored)
+ */
+ void seekableChanged(bool isSeekable);
+
+ /**
+ * Emitted whenever the return value of hasVideo() changes.
+ *
+ * Normally you'll check hasVideo() first and then let this signal
+ * tell you whether video is available now or not. That way you
+ * don't have to poll hasVideo().
+ *
+ * \param hasVideo \p true The stream contains video and adding a
+ * VideoWidget will show a video.
+ * \p false There is no video data in the stream and
+ * adding a VideoWidget will show an empty (black)
+ * VideoWidget.
+ */
+#ifndef QT_NO_PHONON_VIDEO
+ void hasVideoChanged(bool hasVideo);
+#endif //QT_NO_PHONON_VIDEO
+
+ /**
+ * Tells about the status of the buffer.
+ *
+ * You can use this signal to show a progress bar to the user when
+ * in BufferingState:
+ *
+ * \code
+ * progressBar->setRange(0, 100); // this is the default
+ * connect(media, SIGNAL(bufferStatus(int)), progressBar, SLOT(setValue(int)));
+ * \endcode
+ *
+ * \param percentFilled A number between 0 and 100 telling you how
+ * much the buffer is filled.
+ */ // other names: bufferingProgress
+ void bufferStatus(int percentFilled);
+
+ /**
+ * Emitted when the object has finished playback.
+ * It is not emitted if you call stop(), pause() or
+ * load(), but only on end-of-queue or a critical error.
+ *
+ * \warning This signal is not emitted when the current source has
+ * finished and there's another source in the queue. It is only
+ * emitted when the queue is empty.
+ *
+ * \see currentSourceChanged
+ * \see aboutToFinish
+ * \see prefinishMarkReached
+ */
+ void finished();
+
+ /**
+ * Emitted when the MediaObject makes a transition to the next
+ * MediaSource in the queue().
+ *
+ * In other words, it is emitted when an individual MediaSource is
+ * finished.
+ *
+ * \param newSource The source that starts to play at the time the
+ * signal is emitted.
+ */
+ void currentSourceChanged(const Phonon::MediaSource &newSource);
+
+ /**
+ * Emitted before the playback of the whole queue stops. When this
+ * signal is emitted you still have time to provide the next
+ * MediaSource (using enqueue()) so that playback continues.
+ *
+ * This signal can be used to provide the next MediaSource just in
+ * time for the transition still to work.
+ *
+ * \see enqueue
+ */
+ void aboutToFinish();
+
+ /**
+ * Emitted when there are only \p msecToEnd milliseconds left
+ * for playback.
+ *
+ * \param msecToEnd The remaining time until the playback queue finishes.
+ *
+ * \warning This signal is not emitted when there is another source in the queue.
+ * It is only emitted when the queue is empty.
+ *
+ * \see setPrefinishMark
+ * \see prefinishMark
+ * \see aboutToFinish
+ * \see finished
+ */
+ void prefinishMarkReached(qint32 msecToEnd);
+
+ /**
+ * This signal is emitted as soon as the total time of the media file is
+ * known or has changed. For most non-local media data the total
+ * time of the media can only be known after some time. Initially the
+ * totalTime function can not return useful information. You have
+ * to wait for this signal to know the real total time.
+ *
+ * \param newTotalTime The length of the media file in milliseconds.
+ *
+ * \see totalTime
+ */
+ void totalTimeChanged(qint64 newTotalTime);
+
+ protected:
+ //MediaObject(Phonon::MediaObjectPrivate &dd, QObject *parent);
+
+ private:
+ Q_PRIVATE_SLOT(k_func(), void _k_resumePlay())
+ Q_PRIVATE_SLOT(k_func(), void _k_resumePause())
+ Q_PRIVATE_SLOT(k_func(), void _k_metaDataChanged(const QMultiMap<QString, QString> &))
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ Q_PRIVATE_SLOT(k_func(), void _k_stateChanged(Phonon::State, Phonon::State))
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ Q_PRIVATE_SLOT(k_func(), void _k_aboutToFinish())
+ Q_PRIVATE_SLOT(k_func(), void _k_currentSourceChanged(const MediaSource &))
+ };
+
+ /**
+ * Convenience function to create a MediaObject and AudioOutput connected by
+ * a path.
+ */
+ PHONON_EXPORT MediaObject *createPlayer(Phonon::Category category, const MediaSource &source = MediaSource());
+} //namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_MEDIAOBJECT_H
diff --git a/src/3rdparty/phonon/phonon/mediaobject_p.h b/src/3rdparty/phonon/phonon/mediaobject_p.h
new file mode 100644
index 0000000..c164490
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediaobject_p.h
@@ -0,0 +1,113 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MEDIAOBJECT_P_H
+#define MEDIAOBJECT_P_H
+
+#include "mediaobject.h"
+#include "medianode_p.h"
+#include <QtCore/QString>
+#include "medianodedestructionhandler_p.h"
+#include "mediasource.h"
+#include <QtCore/QQueue>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+class KioFallback;
+class KioFallbackImpl;
+class FrontendInterfacePrivate;
+
+class MediaObjectPrivate : public MediaNodePrivate, private MediaNodeDestructionHandler
+{
+ friend class KioFallbackImpl;
+ friend class AbstractMediaStream;
+ friend class AbstractMediaStreamPrivate;
+ Q_DECLARE_PUBLIC(MediaObject)
+ public:
+ virtual QObject *qObject() { return q_func(); }
+ QList<FrontendInterfacePrivate *> interfaceList;
+ protected:
+ virtual bool aboutToDeleteBackendObject();
+ virtual void createBackendObject();
+ virtual void phononObjectDestroyed(MediaNodePrivate *);
+ PHONON_EXPORT void setupBackendObject();
+
+ void _k_resumePlay();
+ void _k_resumePause();
+ void _k_metaDataChanged(const QMultiMap<QString, QString> &);
+ void _k_aboutToFinish();
+ void _k_currentSourceChanged(const MediaSource &);
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ void streamError(Phonon::ErrorType, const QString &);
+ PHONON_EXPORT void _k_stateChanged(Phonon::State, Phonon::State);
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+ MediaObjectPrivate()
+ : currentTime(0),
+ tickInterval(0),
+ metaData(),
+ errorString(),
+ prefinishMark(0),
+ transitionTime(0), // gapless playback
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ kiofallback(0),
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ state(Phonon::LoadingState)
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ , errorType(Phonon::NormalError),
+ errorOverride(false),
+ ignoreLoadingToBufferingStateChange(false),
+ ignoreErrorToLoadingStateChange(false)
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ {
+ }
+
+ qint64 currentTime;
+ qint32 tickInterval;
+ QMultiMap<QString, QString> metaData;
+ QString errorString;
+ qint32 prefinishMark;
+ qint32 transitionTime;
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ AbstractMediaStream *kiofallback;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ State state
+#ifdef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ ;
+#else
+ : 8;
+ ErrorType errorType : 4;
+ bool errorOverride : 1;
+ bool ignoreLoadingToBufferingStateChange : 1;
+ bool ignoreErrorToLoadingStateChange : 1;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ MediaSource mediaSource;
+ QQueue<MediaSource> sourceQueue;
+};
+}
+
+QT_END_NAMESPACE
+
+#endif // MEDIAOBJECT_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/mediaobjectinterface.h b/src/3rdparty/phonon/phonon/mediaobjectinterface.h
new file mode 100644
index 0000000..26c4c8e
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediaobjectinterface.h
@@ -0,0 +1,242 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MEDIAOBJECTINTERFACE_H
+#define PHONON_MEDIAOBJECTINTERFACE_H
+
+#include "mediaobject.h"
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+class StreamInterface;
+
+/** \class MediaObjectInterface mediaobjectinterface.h Phonon/MediaObjectInterface
+ * \short Backend interface for media sources.
+ *
+ * The backend implementation has to provide two signals, that are not defined
+ * in this interface:
+ * <ul>
+ * <li>\anchor phonon_MediaObjectInterface_stateChanged
+ * <b>void stateChanged(\ref Phonon::State newstate, \ref Phonon::State oldstate)</b>
+ *
+ * Emitted when the state of the MediaObject has changed.
+ * In case you're not interested in the old state you can also
+ * connect to a slot that only has one State argument.
+ *
+ * \param newstate The state the Player is in now.
+ * \param oldstate The state the Player was in before.
+ * </li>
+ * <li>\anchor phonon_MediaObjectInterface_tick
+ * <b>void tick(qint64 time)</b>
+ *
+ * This signal gets emitted every tickInterval milliseconds.
+ *
+ * \param time The position of the media file in milliseconds.
+ *
+ * \see setTickInterval()
+ * \see tickInterval()
+ * </li>
+ * </ul>
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ * \see MediaObject
+ */
+class MediaObjectInterface
+{
+ public:
+ virtual ~MediaObjectInterface() {}
+
+ /**
+ * Requests the playback to start.
+ *
+ * This method is only called if the state transition to \ref PlayingState is possible.
+ *
+ * The backend should react immediately
+ * by either going into \ref PlayingState or \ref BufferingState if the
+ * former is not possible.
+ */
+ virtual void play() = 0;
+
+ /**
+ * Requests the playback to pause.
+ *
+ * This method is only called if the state transition to \ref PausedState is possible.
+ *
+ * The backend should react as fast as possible. Go to \ref PausedState
+ * as soon as playback is paused.
+ */
+ virtual void pause() = 0;
+
+ /**
+ * Requests the playback to be stopped.
+ *
+ * This method is only called if the state transition to \ref StoppedState is possible.
+ *
+ * The backend should react as fast as possible. Go to \ref StoppedState
+ * as soon as playback is stopped.
+ *
+ * A subsequent call to play() will start playback at the beginning of
+ * the media.
+ */
+ virtual void stop() = 0;
+
+ /**
+ * Requests the playback to be seeked to the given time.
+ *
+ * The backend does not have to finish seeking while in this function
+ * (i.e. the backend does not need to block the thread until the seek is
+ * finished; even worse it might lead to deadlocks when using a
+ * ByteStream which gets its data from the thread this function would
+ * block).
+ *
+ * As soon as the seek is done the currentTime() function and
+ * the tick() signal will report it.
+ *
+ * \param milliseconds The time where playback should seek to in
+ * milliseconds.
+ */
+ virtual void seek(qint64 milliseconds) = 0;
+
+ /**
+ * Return the time interval in milliseconds between two ticks.
+ *
+ * \returns Returns the tick interval that it was set to (might not
+ * be the same as you asked for).
+ */
+ virtual qint32 tickInterval() const = 0;
+ /**
+ * Change the interval the tick signal is emitted. If you set \p
+ * interval to 0 the signal gets disabled.
+ *
+ * \param interval tick interval in milliseconds
+ *
+ * \returns Returns the tick interval that it was set to (might not
+ * be the same as you asked for).
+ */
+ virtual void setTickInterval(qint32 interval) = 0;
+
+ /**
+ * Check whether the media data includes a video stream.
+ *
+ * \return returns \p true if the media contains video data
+ */
+ virtual bool hasVideo() const = 0;
+ /**
+ * If the current media may be seeked returns true.
+ *
+ * \returns whether the current media may be seeked.
+ */
+ virtual bool isSeekable() const = 0;
+ /**
+ * Get the current time (in milliseconds) of the file currently being played.
+ */
+ virtual qint64 currentTime() const = 0;
+ /**
+ * Get the current state.
+ */
+ virtual Phonon::State state() const = 0;
+
+ /**
+ * A translated string describing the error.
+ */
+ virtual QString errorString() const = 0;
+
+ /**
+ * Tells your program what to do about the error.
+ *
+ * \see Phonon::ErrorType
+ */
+ virtual Phonon::ErrorType errorType() const = 0;
+
+ /**
+ * Returns the total time of the media in milliseconds.
+ *
+ * If the total time is not know return -1. Do not block until it is
+ * known, instead emit the totalTimeChanged signal as soon as the total
+ * time is known or changes.
+ */
+ virtual qint64 totalTime() const = 0;
+
+ /**
+ * Returns the current source.
+ */
+ virtual MediaSource source() const = 0;
+
+ /**
+ * Sets the current source. When this function is called the MediaObject is
+ * expected to stop all current activity and start loading the new
+ * source (i.e. go into LoadingState).
+ *
+ * It is expected that the
+ * backend now starts preloading the media data, filling the audio
+ * and video buffers and making all media meta data available. It
+ * will also trigger the totalTimeChanged signal.
+ *
+ * If the backend does not know how to handle the source it needs to
+ * change state to Phonon::ErrorState. Don't bother about handling KIO
+ * URLs. It is enough to handle AbstractMediaStream sources correctly.
+ *
+ * \warning Keep the MediaSource object around as long as the backend
+ * uses the AbstractMediaStream returned by the MediaSource. In case
+ * that no other reference to the MediaSource exists and it is set to
+ * MediaSource::autoDelete, the AbstractMediaStream is deleted when the
+ * last MediaSource ref is deleted.
+ */
+ virtual void setSource(const MediaSource &) = 0;
+
+ /**
+ * Sets the next source to be used for transitions. When a next source
+ * is set playback should continue with the new source. In that case
+ * finished and prefinishMarkReached are not emitted.
+ *
+ * \param source The source to transition to (crossfade/gapless/gap). If
+ * \p source is an invalid MediaSource object then the queue is empty
+ * and the playback should stop normally.
+ *
+ * \warning Keep the MediaSource object around as long as the backend
+ * uses the AbstractMediaStream returned by the MediaSource. In case
+ * that no other reference to the MediaSource exists and it is set to
+ * MediaSource::autoDelete, the AbstractMediaStream is deleted when the
+ * last MediaSource ref is deleted.
+ */
+ virtual void setNextSource(const MediaSource &source) = 0;
+
+ virtual qint64 remainingTime() const { return totalTime() - currentTime(); }
+ virtual qint32 prefinishMark() const = 0;
+ virtual void setPrefinishMark(qint32) = 0;
+
+ virtual qint32 transitionTime() const = 0;
+ virtual void setTransitionTime(qint32) = 0;
+};
+}
+
+Q_DECLARE_INTERFACE(Phonon::MediaObjectInterface, "MediaObjectInterface3.phonon.kde.org")
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_MEDIAOBJECTINTERFACE_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/mediasource.cpp b/src/3rdparty/phonon/phonon/mediasource.cpp
new file mode 100644
index 0000000..d70b38b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediasource.cpp
@@ -0,0 +1,237 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "mediasource.h"
+#include "mediasource_p.h"
+#include "iodevicestream_p.h"
+#include "abstractmediastream_p.h"
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QFile>
+#include <QtCore/QFSFileEngine>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+MediaSource::MediaSource(MediaSourcePrivate &dd)
+ : d(&dd)
+{
+}
+
+MediaSource::MediaSource()
+ : d(new MediaSourcePrivate(Empty))
+{
+}
+
+MediaSource::MediaSource(const QString &filename)
+ : d(new MediaSourcePrivate(LocalFile))
+{
+ const QFileInfo fileInfo(filename);
+ if (fileInfo.exists()) {
+ bool localFs = QAbstractFileEngine::LocalDiskFlag & QFSFileEngine(filename).fileFlags(QAbstractFileEngine::LocalDiskFlag);
+ if (localFs && !filename.startsWith(QLatin1String(":/")) && !filename.startsWith(QLatin1String("qrc://"))) {
+ d->url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+ } else {
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ // it's a Qt resource -> use QFile
+ d->type = Stream;
+ d->ioDevice = new QFile(filename);
+ d->setStream(new IODeviceStream(d->ioDevice, d->ioDevice));
+ d->url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+#else
+ d->type = Invalid;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ }
+ } else {
+ d->url = filename;
+ if (d->url.isValid()) {
+ d->type = Url;
+ } else {
+ d->type = Invalid;
+ }
+ }
+}
+
+MediaSource::MediaSource(const QUrl &url)
+ : d(new MediaSourcePrivate(Url))
+{
+ if (url.isValid()) {
+ d->url = url;
+ } else {
+ d->type = Invalid;
+ }
+}
+
+MediaSource::MediaSource(Phonon::DiscType dt, const QString &deviceName)
+ : d(new MediaSourcePrivate(Disc))
+{
+ if (dt == NoDisc) {
+ d->type = Invalid;
+ return;
+ }
+ d->discType = dt;
+ d->deviceName = deviceName;
+}
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+MediaSource::MediaSource(AbstractMediaStream *stream)
+ : d(new MediaSourcePrivate(Stream))
+{
+ if (stream) {
+ d->setStream(stream);
+ } else {
+ d->type = Invalid;
+ }
+}
+
+MediaSource::MediaSource(QIODevice *ioDevice)
+ : d(new MediaSourcePrivate(Stream))
+{
+ if (ioDevice) {
+ d->setStream(new IODeviceStream(ioDevice, ioDevice));
+ d->ioDevice = ioDevice;
+ } else {
+ d->type = Invalid;
+ }
+}
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+/* post 4.0
+MediaSource::MediaSource(const QList<MediaSource> &mediaList)
+ : d(new MediaSourcePrivate(Link))
+{
+ d->linkedSources = mediaList;
+ foreach (MediaSource ms, mediaList) {
+ Q_ASSERT(ms.type() != Link);
+ }
+}
+
+QList<MediaSource> MediaSource::substreams() const
+{
+ return d->linkedSources;
+}
+*/
+
+MediaSource::~MediaSource()
+{
+}
+
+MediaSourcePrivate::~MediaSourcePrivate()
+{
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (autoDelete) {
+ //here we use deleteLater because this object
+ //might be destroyed from another thread
+ if (stream)
+ stream->deleteLater();
+ if (ioDevice)
+ ioDevice->deleteLater();
+ }
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+}
+
+MediaSource::MediaSource(const MediaSource &rhs)
+ : d(rhs.d)
+{
+}
+
+MediaSource &MediaSource::operator=(const MediaSource &rhs)
+{
+ d = rhs.d;
+ return *this;
+}
+
+bool MediaSource::operator==(const MediaSource &rhs) const
+{
+ return d == rhs.d;
+}
+
+void MediaSource::setAutoDelete(bool autoDelete)
+{
+ d->autoDelete = autoDelete;
+}
+
+bool MediaSource::autoDelete() const
+{
+ return d->autoDelete;
+}
+
+MediaSource::Type MediaSource::type() const
+{
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ if (d->type == Stream && d->stream == 0) {
+ return Invalid;
+ }
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ return d->type;
+}
+
+QString MediaSource::fileName() const
+{
+ return d->url.toLocalFile();
+}
+
+QUrl MediaSource::url() const
+{
+ return d->url;
+}
+
+Phonon::DiscType MediaSource::discType() const
+{
+ return d->discType;
+}
+
+QString MediaSource::deviceName() const
+{
+ return d->deviceName;
+}
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+AbstractMediaStream *MediaSource::stream() const
+{
+ return d->stream;
+}
+
+void MediaSourcePrivate::setStream(AbstractMediaStream *s)
+{
+ stream = s;
+}
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+
+//X AudioCaptureDevice MediaSource::audioCaptureDevice() const
+//X {
+//X return d->audioCaptureDevice;
+//X }
+//X
+//X VideoCaptureDevice MediaSource::videoCaptureDevice() const
+//X {
+//X return d->videoCaptureDevice;
+//X }
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/phonon/mediasource.h b/src/3rdparty/phonon/phonon/mediasource.h
new file mode 100644
index 0000000..4cddbad
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediasource.h
@@ -0,0 +1,279 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_MEDIASOURCE_H
+#define PHONON_MEDIASOURCE_H
+
+#include "phonon_export.h"
+#include "phononnamespace.h"
+#include "objectdescription.h"
+#include <QtCore/QSharedData>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QUrl;
+class QIODevice;
+
+namespace Phonon
+{
+
+class MediaSourcePrivate;
+class AbstractMediaStream;
+
+/** \class MediaSource mediasource.h Phonon/MediaSource
+ * Note that all constructors of this class are implicit, so that you can simply write
+ * \code
+ * MediaObject m;
+ * QString fileName("/home/foo/bar.ogg");
+ * QUrl url("http://www.example.com/stream.mp3");
+ * QBuffer *someBuffer;
+ * m.setCurrentSource(fileName);
+ * m.setCurrentSource(url);
+ * m.setCurrentSource(someBuffer);
+ * m.setCurrentSource(Phonon::Cd);
+ * \endcode
+ *
+ * \ingroup Playback
+ * \ingroup Recording
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class PHONON_EXPORT MediaSource
+{
+ friend class StreamInterface;
+ public:
+ /**
+ * Identifies the type of media described by the MediaSource object.
+ *
+ * \see MediaSource::type()
+ */
+ enum Type {
+ /**
+ * The MediaSource object does not describe any valid source.
+ */
+ Invalid = -1,
+ /**
+ * The MediaSource object describes a local file.
+ */
+ LocalFile,
+ /**
+ * The MediaSource object describes a URL, which can be both a local file and a file on
+ * the network.
+ */
+ Url,
+ /**
+ * The MediaSource object describes a disc.
+ */
+ Disc,
+ /**
+ * The MediaSource object describes a data stream.
+ *
+ * This is also the type used for QIODevices.
+ *
+ * \see AbstractMediaStream
+ */
+ Stream,
+ /**
+ * An empty MediaSource.
+ *
+ * It can be used to unload the current media from a MediaObject.
+ *
+ * \see MediaSource()
+ */
+ Empty
+/* post 4.0:
+ / **
+ * Links multiple MediaSource objects together.
+ * /
+ Link
+*/
+ };
+
+ /**
+ * Creates an empty MediaSource.
+ *
+ * An empty MediaSource is considered valid and can be set on a MediaObject to unload its
+ * current media.
+ *
+ * \see Empty
+ */
+ MediaSource();
+
+ /**
+ * Creates a MediaSource object for a local file or a Qt resource.
+ *
+ * \param fileName file name of a local media file or a Qt resource that was compiled in.
+ */
+ MediaSource(const QString &fileName); //krazy:exclude=explicit
+
+ /**
+ * Creates a MediaSource object for a URL.
+ *
+ * \param url URL to a media file or stream.
+ */
+ MediaSource(const QUrl &url); //krazy:exclude=explicit
+
+ /**
+ * Creates a MediaSource object for discs.
+ *
+ * \param discType See \ref DiscType
+ * \param deviceName A platform dependent device name. This can be useful if the computer
+ * has more than one CD drive. It is recommended to use Solid to retrieve the device name in
+ * a portable way.
+ */
+ MediaSource(Phonon::DiscType discType, const QString &deviceName = QString()); //krazy:exclude=explicit
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ /**
+ * Creates a MediaSource object for a data stream.
+ *
+ * Your application can provide the media data by subclassing AbstractMediaStream and
+ * passing a pointer to that object. %Phonon will never delete the \p stream.
+ *
+ * \param stream The AbstractMediaStream subclass to provide the media data.
+ *
+ * \see setAutoDelete
+ */
+ MediaSource(AbstractMediaStream *stream); //krazy:exclude=explicit
+
+ /**
+ * Creates a MediaSource object for a QIODevice.
+ *
+ * This constructor can be very handy in the combination of QByteArray and QBuffer.
+ *
+ * \param ioDevice An arbitrary readable QIODevice subclass. If the device is not opened
+ * MediaSource will open it as QIODevice::ReadOnly. Sequential I/O devices are possible,
+ * too. For those MediaObject::isSeekable() will have to return false obviously.
+ *
+ * \see setAutoDelete
+ */
+ MediaSource(QIODevice *ioDevice); //krazy:exclude=explicit
+#endif
+
+ /**
+ * Creates a MediaSource object for capture devices.
+ */
+ //MediaSource(const AudioCaptureDevice &, const VideoCaptureDevice &);
+
+ /**
+ * Destroys the MediaSource object.
+ */
+ ~MediaSource();
+
+ /**
+ * Constructs a copy of \p rhs.
+ *
+ * This constructor is fast thanks to explicit sharing.
+ */
+ MediaSource(const MediaSource &rhs);
+
+ /**
+ * Assigns \p rhs to this MediaSource and returns a reference to this MediaSource.
+ *
+ * This operation is fast thanks to explicit sharing.
+ */
+ MediaSource &operator=(const MediaSource &rhs);
+
+ /**
+ * Returns \p true if this MediaSource is equal to \p rhs; otherwise returns \p false.
+ */
+ bool operator==(const MediaSource &rhs) const;
+
+ /**
+ * Tell the MediaSource to take ownership of the AbstractMediaStream or QIODevice that was
+ * passed in the constructor.
+ *
+ * The default setting is \p false, for safety. If you turn it on, you should only access
+ * the AbstractMediaStream/QIODevice object as long as you yourself keep a MediaSource
+ * object around. As long as you keep the MediaSource object wrapping the stream/device
+ * the object will not get deleted.
+ *
+ * \see autoDelete
+ */
+ void setAutoDelete(bool enable);
+
+ /**
+ * Returns the setting of the auto-delete option. The default is \p false.
+ *
+ * \see setAutoDelete
+ */
+ bool autoDelete() const;
+
+ /**
+ * Returns the type of the MediaSource (depends on the constructor that was used).
+ *
+ * \see Type
+ */
+ Type type() const;
+
+ /**
+ * Returns the file name of the MediaSource if type() == LocalFile; otherwise returns
+ * QString().
+ */
+ QString fileName() const;
+
+ /**
+ * Returns the url of the MediaSource if type() == URL or type() == LocalFile; otherwise
+ * returns QUrl().
+ */
+ QUrl url() const;
+
+ /**
+ * Returns the disc type of the MediaSource if type() == Disc; otherwise returns \ref
+ * NoDisc.
+ */
+ Phonon::DiscType discType() const;
+
+ /**
+ * Returns the device name of the MediaSource if type() == Disc; otherwise returns
+ * QString().
+ */
+ QString deviceName() const;
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ /**
+ * Returns the media stream of the MediaSource if type() == Stream; otherwise returns 0.
+ * QIODevices are handled as streams, too.
+ */
+ AbstractMediaStream *stream() const;
+#endif
+
+ //AudioCaptureDevice audioCaptureDevice() const;
+ //VideoCaptureDevice videoCaptureDevice() const;
+
+/* post 4.0:
+ MediaSource(const QList<MediaSource> &mediaList);
+ QList<MediaSource> substreams() const;
+*/
+
+ protected:
+ QExplicitlySharedDataPointer<MediaSourcePrivate> d;
+ MediaSource(MediaSourcePrivate &);
+};
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_MEDIASOURCE_H
diff --git a/src/3rdparty/phonon/phonon/mediasource_p.h b/src/3rdparty/phonon/phonon/mediasource_p.h
new file mode 100644
index 0000000..46caef3
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/mediasource_p.h
@@ -0,0 +1,89 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MEDIASOURCE_P_H
+#define MEDIASOURCE_P_H
+
+#include "mediasource.h"
+#include "objectdescription.h"
+#include "abstractmediastream.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QString>
+#include <QtCore/QSharedData>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QFile;
+
+namespace Phonon
+{
+
+class PHONON_EXPORT MediaSourcePrivate : public QSharedData
+{
+ public:
+ MediaSourcePrivate(MediaSource::Type t)
+ : type(t), discType(NoDisc),
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ stream(0),
+ ioDevice(0),
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ autoDelete(false)
+ {
+ }
+
+ virtual ~MediaSourcePrivate();
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ void setStream(AbstractMediaStream *s);
+#endif
+
+ MediaSource::Type type;
+ QUrl url;
+ Phonon::DiscType discType;
+ QString deviceName;
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ // The AbstractMediaStream(2) may be deleted at any time by the application. If that happens
+ // stream will be 0 automatically, but streamEventQueue will stay valid as we hold a
+ // reference to it. This is necessary to avoid a races when setting the MediaSource while
+ // another thread deletes the AbstractMediaStream2. StreamInterface(2) will then just get a
+ // StreamEventQueue where nobody answers.
+ QPointer<AbstractMediaStream> stream;
+
+// AudioCaptureDevice audioCaptureDevice;
+// VideoCaptureDevice videoCaptureDevice;
+ QIODevice *ioDevice;
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+ //QList<MediaSource> linkedSources;
+ bool autoDelete;
+};
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // MEDIASOURCE_P_H
+// vim: sw=4 sts=4 et tw=100
+
+
diff --git a/src/3rdparty/phonon/phonon/objectdescription.cpp b/src/3rdparty/phonon/phonon/objectdescription.cpp
new file mode 100644
index 0000000..55e74b5
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/objectdescription.cpp
@@ -0,0 +1,152 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "objectdescription.h"
+#include "objectdescription_p.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QSet>
+#include "factory_p.h"
+#include <QtCore/QStringList>
+#include "backendinterface.h"
+#include "platformplugin.h"
+#include "pulsesupport.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+ObjectDescriptionData::ObjectDescriptionData(int index, const QHash<QByteArray, QVariant> &properties)
+ : d(new ObjectDescriptionPrivate(index, properties))
+{
+}
+
+ObjectDescriptionData::ObjectDescriptionData(ObjectDescriptionPrivate *dd)
+ : d(dd)
+{
+}
+
+ObjectDescriptionData::~ObjectDescriptionData()
+{
+ delete d;
+}
+
+bool ObjectDescriptionData::operator==(const ObjectDescriptionData &otherDescription) const
+{
+ if (!isValid()) {
+ return !otherDescription.isValid();
+ }
+ if (!otherDescription.isValid()) {
+ return false;
+ }
+ return *d == *otherDescription.d;
+}
+
+int ObjectDescriptionData::index() const
+{
+ if (!isValid()) {
+ return -1;
+ }
+ return d->index;
+}
+
+QString ObjectDescriptionData::name() const
+{
+ if (!isValid()) {
+ return QString();
+ }
+ return d->name;
+}
+
+QString ObjectDescriptionData::description() const
+{
+ if (!isValid()) {
+ return QString();
+ }
+ return d->description;
+}
+
+QVariant ObjectDescriptionData::property(const char *name) const
+{
+ if (!isValid()) {
+ return QVariant();
+ }
+ return d->properties.value(name);
+}
+
+QList<QByteArray> ObjectDescriptionData::propertyNames() const
+{
+ if (!isValid()) {
+ return QList<QByteArray>();
+ }
+ return d->properties.keys();
+}
+
+bool ObjectDescriptionData::isValid() const
+{
+ return d != 0;
+}
+
+ObjectDescriptionData *ObjectDescriptionData::fromIndex(ObjectDescriptionType type, int index)
+{
+ bool is_audio_device = (AudioOutputDeviceType == type || AudioCaptureDeviceType == type);
+
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (is_audio_device && pulse->isActive()) {
+ QList<int> indexes = pulse->objectDescriptionIndexes(type);
+ if (indexes.contains(index)) {
+ QHash<QByteArray, QVariant> properties = pulse->objectDescriptionProperties(type, index);
+ return new ObjectDescriptionData(index, properties);
+ }
+ } else {
+ BackendInterface *iface = qobject_cast<BackendInterface *>(Factory::backend());
+
+ // prefer to get the ObjectDescriptionData from the platform plugin for audio devices
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ if (is_audio_device) {
+ PlatformPlugin *platformPlugin = Factory::platformPlugin();
+ if (platformPlugin) {
+ QList<int> indexes = platformPlugin->objectDescriptionIndexes(type);
+ if (indexes.contains(index)) {
+ QHash<QByteArray, QVariant> properties = platformPlugin->objectDescriptionProperties(type, index);
+ return new ObjectDescriptionData(index, properties);
+ }
+ }
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+
+ if (iface) {
+ QList<int> indexes = iface->objectDescriptionIndexes(type);
+ if (indexes.contains(index)) {
+ QHash<QByteArray, QVariant> properties = iface->objectDescriptionProperties(type, index);
+ return new ObjectDescriptionData(index, properties);
+ }
+ }
+ }
+ return new ObjectDescriptionData(0); // invalid
+}
+
+} //namespace Phonon
+
+QT_END_NAMESPACE
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/objectdescription.h b/src/3rdparty/phonon/phonon/objectdescription.h
new file mode 100644
index 0000000..985cdcc
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/objectdescription.h
@@ -0,0 +1,342 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_OBJECTDESCRIPTION_H
+#define PHONON_OBJECTDESCRIPTION_H
+
+#include "phonon_export.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QtDebug>
+#include <QtCore/QList>
+#include <QtCore/QSharedData>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class ObjectDescriptionPrivate;
+
+ /**
+ * Defines the type of information that is contained in a ObjectDescription
+ * object.
+ *
+ * \ingroup Backend
+ */
+ enum ObjectDescriptionType
+ {
+ /**
+ * Audio output devices. This can be soundcards (with different drivers), soundservers or
+ * other virtual outputs like playback on a different computer on the
+ * network.
+ *
+ * For Hardware devices the backend should use libkaudiodevicelist
+ * (AudioDevice and AudioDeviceEnumerator) which will list removable
+ * devices even when they are unplugged and provide a unique identifier
+ * that can make backends use the same identifiers.
+ */
+ AudioOutputDeviceType,
+
+ /**
+ * Lists all processing effects the backend supports.
+ */
+ EffectType,
+ AudioChannelType,
+ SubtitleType,
+
+ /**
+ * Audio capture devices. This can be soundcards (with different drivers), soundservers or
+ * other virtual inputs like capture on a different computer on the
+ * network.
+ *
+ * For Hardware devices the backend should use libkaudiodevicelist
+ * (AudioDevice and AudioDeviceEnumerator) which will list removable
+ * devices even when they are unplugged and provide a unique identifier
+ * that can make backends use the same identifiers.
+ */
+ AudioCaptureDeviceType
+
+ //VideoOutputDeviceType,
+ //VideoCaptureDeviceType,
+ //AudioCodecType,
+ //VideoCodecType,
+ //ContainerFormatType,
+ //VisualizationType,
+ };
+
+/** \internal
+ * \class ObjectDescriptionData objectdescription.h Phonon/ObjectDescription
+ * \brief Data class for objects describing devices or features of the backend.
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ * \see BackendCapabilities
+ */
+class PHONON_EXPORT ObjectDescriptionData : public QSharedData //krazy:exclude=dpointer (it's protected, which should be fine for this type of class)
+{
+ public:
+ /**
+ * Returns \c true if this ObjectDescription describes the same
+ * as \p otherDescription; otherwise returns \c false.
+ */
+ bool operator==(const ObjectDescriptionData &otherDescription) const;
+
+ /**
+ * Returns the name of the capture source.
+ *
+ * \return A string that should be presented to the user to
+ * choose the capture source.
+ */
+ QString name() const;
+
+ /**
+ * Returns a description of the capture source. This text should
+ * make clear what sound source this is, which is sometimes hard
+ * to describe or understand from just the name.
+ *
+ * \return A string describing the capture source.
+ */
+ QString description() const;
+
+ /**
+ * Returns a named property.
+ *
+ * If the property is not set an invalid value is returned.
+ *
+ * \see propertyNames()
+ */
+ QVariant property(const char *name) const;
+
+ /**
+ * Returns all names that return valid data when property() is called.
+ *
+ * \see property()
+ */
+ QList<QByteArray> propertyNames() const;
+
+ /**
+ * Returns \c true if the Tuple is valid (index != -1); otherwise returns
+ * \c false.
+ */
+ bool isValid() const;
+
+ /**
+ * A unique identifier for this device/. Used internally
+ * to distinguish between the devices/.
+ *
+ * \return An integer that uniquely identifies every device/
+ */
+ int index() const;
+
+ static ObjectDescriptionData *fromIndex(ObjectDescriptionType type, int index);
+
+ ~ObjectDescriptionData();
+
+ ObjectDescriptionData(ObjectDescriptionPrivate * = 0);
+ ObjectDescriptionData(int index, const QHash<QByteArray, QVariant> &properties);
+
+ protected:
+ ObjectDescriptionPrivate *const d;
+
+ private:
+ ObjectDescriptionData &operator=(const ObjectDescriptionData &rhs);
+};
+
+template<ObjectDescriptionType T> class ObjectDescriptionModel;
+
+/** \class ObjectDescription objectdescription.h Phonon/ObjectDescription
+ * \short Provides a tuple of enduser visible name and description.
+ *
+ * Some parts give the enduser choices, e.g. what source to capture audio from.
+ * These choices are described by the name and description methods of this class
+ * and identified with the id method. Subclasses then define additional
+ * information like which audio and video choices belong together.
+ *
+ * \ingroup Frontend
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+template<ObjectDescriptionType T>
+class ObjectDescription
+{
+ public:
+ /**
+ * Returns a new description object that describes the
+ * device/effect/codec/... with the given \p index.
+ */
+ static inline ObjectDescription<T> fromIndex(int index) { //krazy:exclude=inline
+ return ObjectDescription<T>(QExplicitlySharedDataPointer<ObjectDescriptionData>(ObjectDescriptionData::fromIndex(T, index)));
+ }
+
+ /**
+ * Returns \c true if this ObjectDescription describes the same
+ * as \p otherDescription; otherwise returns \c false.
+ */
+ inline bool operator==(const ObjectDescription &otherDescription) const { //krazy:exclude=inline
+ return *d == *otherDescription.d;
+ }
+
+ /**
+ * Returns \c false if this ObjectDescription describes the same
+ * as \p otherDescription; otherwise returns \c true.
+ */
+ inline bool operator!=(const ObjectDescription &otherDescription) const { //krazy:exclude=inline
+ return !operator==(otherDescription);
+ }
+
+ /**
+ * Returns the name of the capture source.
+ *
+ * \return A string that should be presented to the user to
+ * choose the capture source.
+ */
+ inline QString name() const { return d->name(); } //krazy:exclude=inline
+
+ /**
+ * Returns a description of the capture source. This text should
+ * make clear what sound source this is, which is sometimes hard
+ * to describe or understand from just the name.
+ *
+ * \return A string describing the capture source.
+ */
+ inline QString description() const { return d->description(); } //krazy:exclude=inline
+
+ /**
+ * Returns a named property.
+ *
+ * If the property is not set an invalid value is returned.
+ *
+ * \see propertyNames()
+ */
+ inline QVariant property(const char *name) const { return d->property(name); } //krazy:exclude=inline
+
+ /**
+ * Returns all names that return valid data when property() is called.
+ *
+ * \see property()
+ */
+ inline QList<QByteArray> propertyNames() const { return d->propertyNames(); } //krazy:exclude=inline
+
+ /**
+ * Returns \c true if the Tuple is valid (index != -1); otherwise returns
+ * \c false.
+ */
+ inline bool isValid() const { return d->isValid(); } //krazy:exclude=inline
+
+ /**
+ * A unique identifier for this device/. Used internally
+ * to distinguish between the devices/.
+ *
+ * \return An integer that uniquely identifies every device/
+ */
+ inline int index() const { return d->index(); } //krazy:exclude=inline
+
+ ObjectDescription() : d(new ObjectDescriptionData(0)) {}
+ ObjectDescription(int index, const QHash<QByteArray, QVariant> &properties) : d(new ObjectDescriptionData(index, properties)) {}
+
+ protected:
+ friend class ObjectDescriptionModel<T>;
+ ObjectDescription(const QExplicitlySharedDataPointer<ObjectDescriptionData> &dd) : d(dd) {}
+ QExplicitlySharedDataPointer<ObjectDescriptionData> d;
+};
+
+template<ObjectDescriptionType T>
+inline QDebug operator<<(QDebug s, const ObjectDescription<T> &o) //krazy:exclude=inline
+{
+ return s << o.name();
+}
+
+/**
+ * \ingroup BackendInformation
+ */
+typedef ObjectDescription<AudioOutputDeviceType> AudioOutputDevice;
+/**
+ * \ingroup BackendInformation
+ */
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+typedef ObjectDescription<AudioCaptureDeviceType> AudioCaptureDevice;
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+/**
+ * \ingroup BackendInformation
+ */
+//typedef ObjectDescription<VideoOutputDeviceType> VideoOutputDevice;
+/**
+ * \ingroup BackendInformation
+ */
+//typedef ObjectDescription<VideoCaptureDeviceType> VideoCaptureDevice;
+/**
+ * \ingroup BackendInformation
+ */
+#ifndef QT_NO_PHONON_EFFECT
+typedef ObjectDescription<EffectType> EffectDescription;
+#endif //QT_NO_PHONON_EFFECT
+
+/**
+ * \ingroup BackendInformation
+ */
+//typedef ObjectDescription<AudioCodecType> AudioCodecDescription;
+/**
+ * \ingroup BackendInformation
+ */
+//typedef ObjectDescription<VideoCodecType> VideoCodecDescription;
+/**
+ * \ingroup BackendInformation
+ */
+//typedef ObjectDescription<ContainerFormatType> ContainerFormatDescription;
+/**
+ * \ingroup BackendInformation
+ */
+//typedef ObjectDescription<VisualizationType> VisualizationDescription;
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+typedef ObjectDescription<AudioChannelType> AudioChannelDescription;
+typedef ObjectDescription<SubtitleType> SubtitleDescription;
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+} //namespace Phonon
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Phonon::AudioOutputDevice)
+Q_DECLARE_METATYPE(QList<Phonon::AudioOutputDevice>)
+
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+Q_DECLARE_METATYPE(Phonon::AudioCaptureDevice)
+Q_DECLARE_METATYPE(QList<Phonon::AudioCaptureDevice>)
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+
+#ifndef QT_NO_PHONON_EFFECT
+Q_DECLARE_METATYPE(QList<Phonon::EffectDescription>)
+Q_DECLARE_METATYPE(Phonon::EffectDescription)
+#endif //QT_NO_PHONON_EFFECT
+
+
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+Q_DECLARE_METATYPE(Phonon::AudioChannelDescription)
+Q_DECLARE_METATYPE(Phonon::SubtitleDescription)
+Q_DECLARE_METATYPE(QList<Phonon::AudioChannelDescription>)
+Q_DECLARE_METATYPE(QList<Phonon::SubtitleDescription>)
+#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+QT_END_HEADER
+
+#endif // PHONON_OBJECTDESCRIPTION_H
diff --git a/src/3rdparty/phonon/phonon/objectdescription_p.h b/src/3rdparty/phonon/phonon/objectdescription_p.h
new file mode 100644
index 0000000..bcf56de
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/objectdescription_p.h
@@ -0,0 +1,64 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_OBJECTDESCRIPTION_P_H
+#define PHONON_OBJECTDESCRIPTION_P_H
+
+#include <QtCore/QByteRef>
+#include <QtCore/QHash>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include "phononnamespace_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class ObjectDescriptionPrivate
+ {
+ public:
+ ObjectDescriptionPrivate(int _index, const QHash<QByteArray, QVariant> &_properties)
+ : index(_index),
+ name(_properties["name"].toString()),
+ description(_properties["description"].toString()),
+ properties(_properties)
+ {
+ }
+
+ bool operator==(const ObjectDescriptionPrivate &rhs) const
+ {
+ if (index == rhs.index && (name != rhs.name || description != rhs.description))
+ pError() << "Same index (" << index <<
+ "), but different name/description. This is a bug in the Phonon backend.";
+ return index == rhs.index;// && name == rhs.name && description == rhs.description;
+ }
+
+ int index;
+ QString name, description;
+ QHash<QByteArray, QVariant> properties;
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // PHONON_OBJECTDESCRIPTION_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp
new file mode 100644
index 0000000..741a74c
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp
@@ -0,0 +1,387 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "objectdescriptionmodel.h"
+#include "objectdescriptionmodel_p.h"
+#include "phonondefs_p.h"
+#include "platform_p.h"
+#include <QtCore/QList>
+#include "objectdescription.h"
+#include "phononnamespace_p.h"
+#include <QtCore/QMimeData>
+#include <QtCore/QStringList>
+#include <QtGui/QIcon>
+#include "factory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+
+
+static const uint qt_meta_data_Phonon__ObjectDescriptionModel[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 0, 0, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioOutputDeviceType[] = { "Phonon::AudioOutputDevice\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCaptureDeviceType[] = { "Phonon::AudioCaptureDevice\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_EffectType[] = { "Phonon::EffectDescription\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioChannelType[] = { "Phonon::AudioChannelDescription\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_SubtitleType[] = { "Phonon::SubtitleDescription\0" };
+/*
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoOutputDeviceType[] = { "Phonon::VideoOutputDevice\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCaptureDeviceType[] = { "Phonon::VideoCaptureDevice\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCodecType[] = { "Phonon::AudioCodecDescription\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCodecType[] = { "Phonon::VideoCodecDescription\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_ContainerFormatType[] = { "Phonon::ContainerFormatDescription\0" };
+static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_VisualizationType[] = { "Phonon::VisualizationDescription\0" };
+*/
+
+namespace Phonon
+{
+
+template<> const QMetaObject ObjectDescriptionModel<AudioOutputDeviceType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioOutputDeviceType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<EffectType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_EffectType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<AudioChannelType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioChannelType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<SubtitleType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_SubtitleType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<AudioCaptureDeviceType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCaptureDeviceType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+/*template<> const QMetaObject ObjectDescriptionModel<VideoOutputDeviceType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoOutputDeviceType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<VideoCaptureDeviceType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCaptureDeviceType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<AudioCodecType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioCodecType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<VideoCodecType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VideoCodecType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<ContainerFormatType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_ContainerFormatType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};
+template<> const QMetaObject ObjectDescriptionModel<VisualizationType>::staticMetaObject = {
+ { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_VisualizationType,
+ qt_meta_data_Phonon__ObjectDescriptionModel, 0 }
+};*/
+
+template<ObjectDescriptionType type>
+const QMetaObject *ObjectDescriptionModel<type>::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+template<ObjectDescriptionType type>
+void *ObjectDescriptionModel<type>::qt_metacast(const char *_clname)
+{
+ if (!_clname) {
+ return 0;
+ }
+ if (!strcmp(_clname, ObjectDescriptionModel<type>::staticMetaObject.className())) {
+ return static_cast<void *>(const_cast<ObjectDescriptionModel<type> *>(this));
+ }
+ return QAbstractListModel::qt_metacast(_clname);
+}
+
+/*
+template<ObjectDescriptionType type>
+int ObjectDescriptionModel<type>::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ return QAbstractListModel::qt_metacall(_c, _id, _a);
+}
+*/
+
+int ObjectDescriptionModelData::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return d->data.size();
+}
+
+QVariant ObjectDescriptionModelData::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() >= d->data.size() || index.column() != 0)
+ return QVariant();
+
+ switch(role)
+ {
+ case Qt::EditRole:
+ case Qt::DisplayRole:
+ return d->data.at(index.row())->name();
+ break;
+ case Qt::ToolTipRole:
+ return d->data.at(index.row())->description();
+ break;
+ case Qt::DecorationRole:
+ {
+ QVariant icon = d->data.at(index.row())->property("icon");
+ if (icon.isValid()) {
+ if (icon.type() == QVariant::String) {
+ return Platform::icon(icon.toString());
+ } else if (icon.type() == QVariant::Icon) {
+ return icon;
+ }
+ }
+ }
+ return QVariant();
+ default:
+ return QVariant();
+}
+}
+
+Qt::ItemFlags ObjectDescriptionModelData::flags(const QModelIndex &index) const
+{
+ if(!index.isValid() || index.row() >= d->data.size() || index.column() != 0) {
+ return Qt::ItemIsDropEnabled;
+ }
+
+ QVariant available = d->data.at(index.row())->property("available");
+ if (available.isValid() && available.type() == QVariant::Bool && !available.toBool()) {
+ return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
+ }
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
+}
+
+QList<int> ObjectDescriptionModelData::tupleIndexOrder() const
+{
+ QList<int> ret;
+ for (int i = 0; i < d->data.size(); ++i) {
+ ret.append(d->data.at(i)->index());
+ }
+ return ret;
+}
+
+int ObjectDescriptionModelData::tupleIndexAtPositionIndex(int positionIndex) const
+{
+ return d->data.at(positionIndex)->index();
+}
+
+QMimeData *ObjectDescriptionModelData::mimeData(ObjectDescriptionType type, const QModelIndexList &indexes) const
+{
+ QMimeData *mimeData = new QMimeData;
+ QByteArray encodedData;
+ QDataStream stream(&encodedData, QIODevice::WriteOnly);
+ QModelIndexList::const_iterator end = indexes.constEnd();
+ QModelIndexList::const_iterator index = indexes.constBegin();
+ for(; index!=end; ++index) {
+ if ((*index).isValid()) {
+ stream << d->data.at((*index).row())->index();
+ }
+ }
+ //pDebug() << Q_FUNC_INFO << "setting mimeData to" << mimeTypes(type).first() << "=>" << encodedData.toHex();
+ mimeData->setData(mimeTypes(type).first(), encodedData);
+ return mimeData;
+}
+
+void ObjectDescriptionModelData::moveUp(const QModelIndex &index)
+{
+ if (!index.isValid() || index.row() >= d->data.size() || index.row() < 1 || index.column() != 0)
+ return;
+
+ emit d->model->layoutAboutToBeChanged();
+ QModelIndex above = index.sibling(index.row() - 1, index.column());
+ d->data.swap(index.row(), above.row());
+ QModelIndexList from, to;
+ from << index << above;
+ to << above << index;
+ d->model->changePersistentIndexList(from, to);
+ emit d->model->layoutChanged();
+}
+
+void ObjectDescriptionModelData::moveDown(const QModelIndex &index)
+{
+ if (!index.isValid() || index.row() >= d->data.size() - 1 || index.column() != 0)
+ return;
+
+ emit d->model->layoutAboutToBeChanged();
+ QModelIndex below = index.sibling(index.row() + 1, index.column());
+ d->data.swap(index.row(), below.row());
+ QModelIndexList from, to;
+ from << index << below;
+ to << below << index;
+ d->model->changePersistentIndexList(from, to);
+ emit d->model->layoutChanged();
+}
+
+ObjectDescriptionModelData::ObjectDescriptionModelData(QAbstractListModel *model)
+ : d(new ObjectDescriptionModelDataPrivate(model))
+{
+}
+
+ObjectDescriptionModelData::~ObjectDescriptionModelData()
+{
+ delete d;
+}
+
+void ObjectDescriptionModelData::setModelData(const QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > &newData)
+{
+ d->data = newData;
+ d->model->reset();
+}
+
+QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > ObjectDescriptionModelData::modelData() const
+{
+ return d->data;
+}
+
+QExplicitlySharedDataPointer<ObjectDescriptionData> ObjectDescriptionModelData::modelData(const QModelIndex &index) const
+{
+ if (!index.isValid() || index.row() >= d->data.size() || index.column() != 0) {
+ return QExplicitlySharedDataPointer<ObjectDescriptionData>(new ObjectDescriptionData(0));
+ }
+ return d->data.at(index.row());
+}
+
+Qt::DropActions ObjectDescriptionModelData::supportedDropActions() const
+{
+ //pDebug() << Q_FUNC_INFO;
+ return Qt::MoveAction;
+}
+
+bool ObjectDescriptionModelData::dropMimeData(ObjectDescriptionType type, const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ Q_UNUSED(action);
+ Q_UNUSED(column);
+ Q_UNUSED(parent);
+ //pDebug() << Q_FUNC_INFO << data << action << row << column << parent;
+
+ QString format = mimeTypes(type).first();
+ if (!data->hasFormat(format)) {
+ return false;
+ }
+
+ if (row == -1) {
+ row = d->data.size();
+ }
+
+ QByteArray encodedData = data->data(format);
+ QDataStream stream(&encodedData, QIODevice::ReadOnly);
+ QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > toInsert;
+ while (!stream.atEnd()) {
+ int otherIndex;
+ stream >> otherIndex;
+ ObjectDescriptionData *obj = ObjectDescriptionData::fromIndex(type, otherIndex);
+
+ if (obj->isValid()) {
+ toInsert << QExplicitlySharedDataPointer<ObjectDescriptionData>(obj);
+ } else {
+ delete obj;
+ }
+ }
+ d->model->beginInsertRows(QModelIndex(), row, row + toInsert.size() - 1);
+ for (int i = 0 ; i < toInsert.count(); ++i) {
+ d->data.insert(row, toInsert.at(i));
+ }
+ d->model->endInsertRows();
+ return true;
+}
+
+
+bool ObjectDescriptionModelData::removeRows(int row, int count, const QModelIndex &parent)
+{
+ //pDebug() << Q_FUNC_INFO << row << count << parent;
+ if (parent.isValid() || row + count > d->data.size()) {
+ return false;
+ }
+ d->model->beginRemoveRows(parent, row, row + count - 1);
+ for (;count > 0; --count) {
+ d->data.removeAt(row);
+ }
+ d->model->endRemoveRows();
+ return true;
+}
+
+/*
+template<ObjectDescriptionType type>
+bool ObjectDescriptionModel<type>::insertRows(int row, int count, const QModelIndex &parent)
+{
+ pDebug() << Q_FUNC_INFO << row << count << parent;
+ if (parent.isValid() || row < 0 || row > d->data.size()) {
+ return false;
+ }
+ beginInsertRows(parent, row, row + count - 1);
+ for (;count > 0; --count) {
+ d->data.insert(row, ObjectDescription<type>());
+ }
+ endInsertRows();
+ return true;
+}
+*/
+
+QStringList ObjectDescriptionModelData::mimeTypes(ObjectDescriptionType type) const
+{
+ return QStringList(QLatin1String("application/x-phonon-objectdescription") + QString::number(static_cast<int>(type)));
+}
+
+#if !defined(Q_CC_MSVC) || _MSC_VER > 1300 || defined(Q_CC_INTEL) || defined(Q_CC_MINGW)
+#define INSTANTIATE_META_FUNCTIONS(type) \
+template const QMetaObject *ObjectDescriptionModel<type>::metaObject() const; \
+template void *ObjectDescriptionModel<type>::qt_metacast(const char *)
+
+INSTANTIATE_META_FUNCTIONS(AudioOutputDeviceType);
+INSTANTIATE_META_FUNCTIONS(AudioCaptureDeviceType);
+INSTANTIATE_META_FUNCTIONS(EffectType);
+INSTANTIATE_META_FUNCTIONS(AudioChannelType);
+INSTANTIATE_META_FUNCTIONS(SubtitleType);
+#endif
+/*INSTANTIATE_META_FUNCTIONS(VideoOutputDeviceType);
+INSTANTIATE_META_FUNCTIONS(VideoCaptureDeviceType);
+INSTANTIATE_META_FUNCTIONS(AudioCodecType);
+INSTANTIATE_META_FUNCTIONS(VideoCodecType);
+INSTANTIATE_META_FUNCTIONS(ContainerFormatType);
+INSTANTIATE_META_FUNCTIONS(VisualizationType);
+*/
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h
new file mode 100644
index 0000000..d994600
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h
@@ -0,0 +1,388 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_OBJECTDESCRIPTIONMODEL_H
+#define PHONON_OBJECTDESCRIPTIONMODEL_H
+
+#include "phonon_export.h"
+#include "phonondefs.h"
+#include "objectdescription.h"
+#include <QtCore/QList>
+#include <QtCore/QModelIndex>
+#include <QtCore/QStringList>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+
+namespace Phonon
+{
+ class ObjectDescriptionModelDataPrivate;
+
+ /** \internal
+ * \class ObjectDescriptionModelData objectdescriptionmodel.h Phonon/ObjectDescriptionModelData
+ * \brief Data class for models for ObjectDescription objects.
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class PHONON_EXPORT ObjectDescriptionModelData
+ {
+ public:
+ /**
+ * Returns the number of rows in the model. This value corresponds
+ * to the size of the list passed through setModelData.
+ *
+ * \param parent The optional \p parent argument is used in most models to specify
+ * the parent of the rows to be counted. Because this is a list if a
+ * valid parent is specified the result will always be 0.
+ *
+ * Reimplemented from QAbstractItemModel.
+ *
+ * \see QAbstractItemModel::rowCount
+ */
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+
+ /**
+ * Returns data from the item with the given \p index for the specified
+ * \p role.
+ * If the view requests an invalid index, an invalid variant is
+ * returned.
+ *
+ * Reimplemented from QAbstractItemModel.
+ *
+ * \see QAbstractItemModel::data
+ * \see Qt::ItemDataRole
+ */
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ /**
+ * Reimplemented to show unavailable devices as disabled (but still
+ * selectable).
+ */
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ /**
+ * Returns a list of indexes in the same order as they are in the
+ * model. The indexes come from the ObjectDescription::index
+ * method.
+ *
+ * This is useful to let the user define a list of preference.
+ */
+ QList<int> tupleIndexOrder() const;
+
+ /**
+ * Returns the ObjectDescription::index for the tuple
+ * at the given position \p positionIndex. For example a
+ * QComboBox will give you the currentIndex as the
+ * position in the list. But to select the according
+ * AudioOutputDevice using AudioOutputDevice::fromIndex
+ * you can use this method.
+ *
+ * \param positionIndex The position in the list.
+ */
+ int tupleIndexAtPositionIndex(int positionIndex) const;
+
+ /**
+ * Returns the MIME data that dropMimeData() can use to create new
+ * items.
+ */
+ QMimeData *mimeData(ObjectDescriptionType type, const QModelIndexList &indexes) const;
+
+ /**
+ * Moves the item at the given \p index up. In the resulting list
+ * the items at index.row() and index.row() - 1 are swapped.
+ *
+ * Connected views are updated automatically.
+ */
+ void moveUp(const QModelIndex &index);
+
+ /**
+ * Moves the item at the given \p index down. In the resulting list
+ * the items at index.row() and index.row() + 1 are swapped.
+ *
+ * Connected views are updated automatically.
+ */
+ void moveDown(const QModelIndex &index);
+
+ void setModelData(const QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > &data);
+ QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > modelData() const;
+ QExplicitlySharedDataPointer<ObjectDescriptionData> modelData(const QModelIndex &index) const;
+ Qt::DropActions supportedDropActions() const;
+ bool dropMimeData(ObjectDescriptionType type, const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ QStringList mimeTypes(ObjectDescriptionType type) const;
+
+ ObjectDescriptionModelData(QAbstractListModel *);
+ protected:
+ ~ObjectDescriptionModelData();
+ //ObjectDescriptionModelData(ObjectDescriptionModelDataPrivate *dd);
+ ObjectDescriptionModelDataPrivate *const d;
+ };
+
+/* Required to ensure template class vtables are exported on both symbian
+and existing builds. */
+#if (defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT)) || defined(Q_CC_CLANG)
+// RVCT compiler (2.2.686) requires the export declaration to be on the class to export vtables
+// MWC compiler works both ways
+// GCCE compiler is unknown (it can't compile QtCore yet)
+// Clang also requires the export declaration to be on the class to export vtables
+#define PHONON_TEMPLATE_CLASS_EXPORT PHONON_EXPORT
+#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT
+#else
+// Windows builds (at least) do not support export declaration on templated class
+// But if you export a member function, the vtable is implicitly exported
+#define PHONON_TEMPLATE_CLASS_EXPORT
+#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT PHONON_EXPORT
+#endif
+
+ /** \class ObjectDescriptionModel objectdescriptionmodel.h Phonon/ObjectDescriptionModel
+ * \short The ObjectDescriptionModel class provides a model from
+ * a list of ObjectDescription objects.
+ *
+ * ObjectDescriptionModel is a readonly model that supplies a list
+ * using ObjectDescription::name() for the text and
+ * ObjectDescription::description() for the tooltip. If set the properties
+ * "icon" and "available" are used to set the decoration and disable the
+ * item (disabled only visually, you can still select and drag it).
+ *
+ * It also provides the methods moveUp() and moveDown() to order the list.
+ * Additionally drag and drop is possible so that
+ * QAbstractItemView::InternalMove can be used.
+ * The resulting order of the ObjectDescription::index() values can then be
+ * retrieved using tupleIndexOrder().
+ *
+ * An example use case would be to give the user a QComboBox to select
+ * the output device:
+ * \code
+ * QComboBox *cb = new QComboBox(parentWidget);
+ * ObjectDescriptionModel *model = new ObjectDescriptionModel(cb);
+ * model->setModelData(BackendCapabilities::availableAudioOutputDevices());
+ * cb->setModel(model);
+ * cb->setCurrentIndex(0); // select first entry
+ * \endcode
+ *
+ * And to retrieve the selected AudioOutputDevice:
+ * \code
+ * int cbIndex = cb->currentIndex();
+ * AudioOutputDevice selectedDevice = model->modelData(cbIndex);
+ * \endcode
+ *
+ * \ingroup Frontend
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ template<ObjectDescriptionType type>
+ class PHONON_TEMPLATE_CLASS_EXPORT ObjectDescriptionModel : public QAbstractListModel
+ {
+ public:
+ Q_OBJECT_CHECK
+
+ /** \internal */
+ static PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject staticMetaObject;
+ /** \internal */
+ PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject *metaObject() const;
+ /** \internal */
+ PHONON_TEMPLATE_CLASS_MEMBER_EXPORT void *qt_metacast(const char *_clname);
+ //int qt_metacall(QMetaObject::Call _c, int _id, void **_a);
+
+ /**
+ * Returns the number of rows in the model. This value corresponds
+ * to the size of the list passed through setModelData.
+ *
+ * \param parent The optional \p parent argument is used in most models to specify
+ * the parent of the rows to be counted. Because this is a list if a
+ * valid parent is specified the result will always be 0.
+ *
+ * Reimplemented from QAbstractItemModel.
+ *
+ * \see QAbstractItemModel::rowCount
+ */
+ inline int rowCount(const QModelIndex &parent = QModelIndex()) const { return d->rowCount(parent); } //krazy:exclude=inline
+
+ /**
+ * Returns data from the item with the given \p index for the specified
+ * \p role.
+ * If the view requests an invalid index, an invalid variant is
+ * returned.
+ *
+ * Reimplemented from QAbstractItemModel.
+ *
+ * \see QAbstractItemModel::data
+ * \see Qt::ItemDataRole
+ */
+ inline QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const { return d->data(index, role); } //krazy:exclude=inline
+
+ /**
+ * Reimplemented to show unavailable devices as disabled (but still
+ * selectable).
+ */
+ inline Qt::ItemFlags flags(const QModelIndex &index) const { return d->flags(index); } //krazy:exclude=inline
+
+ /**
+ * Returns a list of indexes in the same order as they are in the
+ * model. The indexes come from the ObjectDescription::index
+ * method.
+ *
+ * This is useful to let the user define a list of preference.
+ */
+ inline QList<int> tupleIndexOrder() const { return d->tupleIndexOrder(); } //krazy:exclude=inline
+
+ /**
+ * Returns the ObjectDescription::index for the tuple
+ * at the given position \p positionIndex. For example a
+ * QComboBox will give you the currentIndex as the
+ * position in the list. But to select the according
+ * AudioOutputDevice using AudioOutputDevice::fromIndex
+ * you can use this method.
+ *
+ * \param positionIndex The position in the list.
+ */
+ inline int tupleIndexAtPositionIndex(int positionIndex) const { return d->tupleIndexAtPositionIndex(positionIndex); } //krazy:exclude=inline
+
+ /**
+ * Returns the MIME data that dropMimeData() can use to create new
+ * items.
+ */
+ inline QMimeData *mimeData(const QModelIndexList &indexes) const { return d->mimeData(type, indexes); } //krazy:exclude=inline
+
+ /**
+ * Moves the item at the given \p index up. In the resulting list
+ * the items at index.row() and index.row() - 1 are swapped.
+ *
+ * Connected views are updated automatically.
+ */
+ inline void moveUp(const QModelIndex &index) { d->moveUp(index); } //krazy:exclude=inline
+
+ /**
+ * Moves the item at the given \p index down. In the resulting list
+ * the items at index.row() and index.row() + 1 are swapped.
+ *
+ * Connected views are updated automatically.
+ */
+ inline void moveDown(const QModelIndex &index) { d->moveDown(index); } //krazy:exclude=inline
+
+ /**
+ * Constructs a ObjectDescription model with the
+ * given \p parent.
+ */
+ explicit inline ObjectDescriptionModel(QObject *parent = 0) : QAbstractListModel(parent), d(new ObjectDescriptionModelData(this)) {} //krazy:exclude=inline
+
+ /**
+ * Constructs a ObjectDescription model with the
+ * given \p parent and the given \p data.
+ */
+ explicit inline ObjectDescriptionModel(const QList<ObjectDescription<type> > &data, QObject *parent = 0) //krazy:exclude=inline
+ : QAbstractListModel(parent), d(new ObjectDescriptionModelData(this)) { setModelData(data); }
+
+ /**
+ * Sets the model data using the list provided by \p data.
+ *
+ * All previous model data is cleared.
+ */
+ inline void setModelData(const QList<ObjectDescription<type> > &data) { //krazy:exclude=inline
+ QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > list;
+ for (int i = 0; i < data.count(); ++i) {
+ list += data.at(i).d;
+ }
+ d->setModelData(list);
+ }
+
+ /**
+ * Returns the model data.
+ *
+ * As the order of the list might have changed this can be different
+ * to what was set using setModelData().
+ */
+ inline QList<ObjectDescription<type> > modelData() const { //krazy:exclude=inline
+ QList<ObjectDescription<type> > ret;
+ QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > list = d->modelData();
+ for (int i = 0; i < list.count(); ++i) {
+ ret << ObjectDescription<type>(list.at(i));
+ }
+ return ret;
+ }
+
+ /**
+ * Returns one ObjectDescription of the model data for the given \p index.
+ */
+ inline ObjectDescription<type> modelData(const QModelIndex &index) const { return ObjectDescription<type>(d->modelData(index)); } //krazy:exclude=inline
+
+ /**
+ * This model supports drag and drop to copy or move
+ * items.
+ */
+ inline Qt::DropActions supportedDropActions() const { return d->supportedDropActions(); } //krazy:exclude=inline
+
+ /**
+ * Accept drops from other models of the same ObjectDescriptionType.
+ *
+ * If a valid \p parent is given the dropped items will be inserted
+ * above that item.
+ */
+ inline bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { //krazy:exclude=inline
+ return d->dropMimeData(type, data, action, row, column, parent);
+ }
+
+ /**
+ * Removes count rows starting with the given row.
+ *
+ * If a valid \p parent is given no rows are removed since this is a
+ * list model.
+ *
+ * Returns true if the rows were successfully removed; otherwise returns false.
+ */
+ inline bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) { //krazy:exclude=inline
+ return d->removeRows(row, count, parent);
+ }
+
+ /**
+ * Returns a list of supported drag and drop MIME types. Currently
+ * it only supports one type used internally.
+ */
+ inline QStringList mimeTypes() const { return d->mimeTypes(type); } //krazy:exclude=inline
+
+ protected:
+ ObjectDescriptionModelData *const d;
+ };
+
+ typedef ObjectDescriptionModel<AudioOutputDeviceType> AudioOutputDeviceModel;
+ typedef ObjectDescriptionModel<AudioCaptureDeviceType> AudioCaptureDeviceModel;
+ typedef ObjectDescriptionModel<EffectType> EffectDescriptionModel;
+ typedef ObjectDescriptionModel<AudioChannelType> AudioChannelDescriptionModel;
+ typedef ObjectDescriptionModel<SubtitleType> SubtitleDescriptionModel;
+/*
+ typedef ObjectDescriptionModel<VideoOutputDeviceType> VideoOutputDeviceModel;
+ typedef ObjectDescriptionModel<VideoCaptureDeviceType> VideoCaptureDeviceModel;
+ typedef ObjectDescriptionModel<AudioCodecType> AudioCodecDescriptionModel;
+ typedef ObjectDescriptionModel<VideoCodecType> VideoCodecDescriptionModel;
+ typedef ObjectDescriptionModel<ContainerFormatType> ContainerFormatDescriptionModel;
+ typedef ObjectDescriptionModel<VisualizationType> VisualizationDescriptionModel;*/
+
+}
+
+#endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_OBJECTDESCRIPTIONMODEL_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h
new file mode 100644
index 0000000..2200c8d
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_OBJECTDESCRIPTIONMODEL_P_H
+#define PHONON_OBJECTDESCRIPTIONMODEL_P_H
+
+#include "objectdescriptionmodel.h"
+#include <QtCore/QList>
+#include "objectdescription.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+
+namespace Phonon
+{
+
+class ListModelHelper : public QAbstractListModel
+{
+ public:
+ using QAbstractListModel::layoutAboutToBeChanged;
+ using QAbstractListModel::changePersistentIndexList;
+ using QAbstractListModel::layoutChanged;
+ using QAbstractListModel::reset;
+ using QAbstractListModel::beginInsertRows;
+ using QAbstractListModel::endInsertRows;
+ using QAbstractListModel::beginRemoveRows;
+ using QAbstractListModel::endRemoveRows;
+};
+
+class ObjectDescriptionModelDataPrivate
+{
+ public:
+ ObjectDescriptionModelDataPrivate(QAbstractListModel *m) : model(reinterpret_cast<ListModelHelper *>(m)) {}
+ QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > data;
+ ListModelHelper *model;
+};
+
+}
+
+#endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+
+QT_END_NAMESPACE
+
+#endif // PHONON_OBJECTDESCRIPTIONMODEL_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/org.kde.Phonon.AudioOutput.xml b/src/3rdparty/phonon/phonon/org.kde.Phonon.AudioOutput.xml
new file mode 100644
index 0000000..2498337
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/org.kde.Phonon.AudioOutput.xml
@@ -0,0 +1,32 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.kde.Phonon.AudioOutput">
+ <property name="volume" type="d" access="readwrite"/>
+ <property name="muted" type="b" access="readwrite"/>
+ <property name="outputDeviceIndex" type="i" access="readwrite"/>
+ <signal name="volumeChanged">
+ <arg type="d" direction="out"/>
+ </signal>
+ <signal name="mutedChanged">
+ <arg type="b" direction="out"/>
+ </signal>
+ <signal name="outputDeviceIndexChanged">
+ <arg type="i" direction="out"/>
+ </signal>
+ <signal name="nameChanged">
+ <arg name="newName" type="s" direction="out"/>
+ </signal>
+ <signal name="newOutputAvailable">
+ <arg name="service" type="s" direction="out"/>
+ <arg name="path" type="s" direction="out"/>
+ </signal>
+ <signal name="outputDestroyed">
+ </signal>
+ <method name="category">
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="name">
+ <arg type="s" direction="out"/>
+ </method>
+ </interface>
+</node>
diff --git a/src/3rdparty/phonon/phonon/path.cpp b/src/3rdparty/phonon/phonon/path.cpp
new file mode 100644
index 0000000..1c25b89
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/path.cpp
@@ -0,0 +1,476 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "path.h"
+#include "path_p.h"
+
+#include "phononnamespace_p.h"
+#include "backendinterface.h"
+#include "factory_p.h"
+#include "medianode.h"
+#include "medianode_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+class ConnectionTransaction
+{
+ public:
+ ConnectionTransaction(BackendInterface *b, const QSet<QObject*> &x) : backend(b), list(x)
+ {
+ success = backend->startConnectionChange(list);
+ }
+ ~ConnectionTransaction()
+ {
+ backend->endConnectionChange(list);
+ }
+ operator bool()
+ {
+ return success;
+ }
+ private:
+ bool success;
+ BackendInterface *const backend;
+ const QSet<QObject*> list;
+};
+
+PathPrivate::~PathPrivate()
+{
+#ifndef QT_NO_PHONON_EFFECT
+ for (int i = 0; i < effects.count(); ++i) {
+ effects.at(i)->k_ptr->removeDestructionHandler(this);
+ }
+ delete effectsParent;
+#endif
+}
+
+Path::~Path()
+{
+}
+
+Path::Path()
+ : d(new PathPrivate)
+{
+}
+
+Path::Path(const Path &rhs)
+ : d(rhs.d)
+{
+}
+
+bool Path::isValid() const
+{
+ return d->sourceNode != 0 && d->sinkNode != 0;
+}
+
+#ifndef QT_NO_PHONON_EFFECT
+Effect *Path::insertEffect(const EffectDescription &desc, Effect *insertBefore)
+{
+ if (!d->effectsParent) {
+ d->effectsParent = new QObject;
+ }
+ Effect *e = new Effect(desc, d->effectsParent);
+ if (!e->isValid()) {
+ delete e;
+ return 0;
+ }
+ bool success = insertEffect(e, insertBefore);
+ if (!success) {
+ delete e;
+ return 0;
+ }
+ return e;
+}
+
+bool Path::insertEffect(Effect *newEffect, Effect *insertBefore)
+{
+ QObject *newEffectBackend = newEffect ? newEffect->k_ptr->backendObject() : 0;
+ if (!isValid() || !newEffectBackend || d->effects.contains(newEffect) ||
+ (insertBefore && (!d->effects.contains(insertBefore) || !insertBefore->k_ptr->backendObject()))) {
+ return false;
+ }
+ QObject *leftNode = 0;
+ QObject *rightNode = 0;
+ const int insertIndex = insertBefore ? d->effects.indexOf(insertBefore) : d->effects.size();
+ if (insertIndex == 0) {
+ //prepend
+ leftNode = d->sourceNode->k_ptr->backendObject();
+ } else {
+ leftNode = d->effects[insertIndex - 1]->k_ptr->backendObject();
+ }
+
+ if (insertIndex == d->effects.size()) {
+ //append
+ rightNode = d->sinkNode->k_ptr->backendObject();
+ } else {
+ Q_ASSERT(insertBefore);
+ rightNode = insertBefore->k_ptr->backendObject();
+ }
+
+ QList<QObjectPair> disconnections, connections;
+ disconnections << QObjectPair(leftNode, rightNode);
+ connections << QObjectPair(leftNode, newEffectBackend)
+ << QObjectPair(newEffectBackend, rightNode);
+
+ if (d->executeTransaction(disconnections, connections)) {
+ newEffect->k_ptr->addDestructionHandler(d.data());
+ d->effects.insert(insertIndex, newEffect);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Path::removeEffect(Effect *effect)
+{
+ return d->removeEffect(effect);
+}
+
+QList<Effect *> Path::effects() const
+{
+ return d->effects;
+}
+#endif //QT_NO_PHONON_EFFECT
+
+bool Path::reconnect(MediaNode *source, MediaNode *sink)
+{
+ if (!source || !sink || !source->k_ptr->backendObject() || !sink->k_ptr->backendObject()) {
+ return false;
+ }
+
+ QList<QObjectPair> disconnections, connections;
+
+ //backend objects
+ QObject *bnewSource = source->k_ptr->backendObject();
+ QObject *bnewSink = sink->k_ptr->backendObject();
+ QObject *bcurrentSource = d->sourceNode ? d->sourceNode->k_ptr->backendObject() : 0;
+ QObject *bcurrentSink = d->sinkNode ? d->sinkNode->k_ptr->backendObject() : 0;
+
+ if (bnewSource != bcurrentSource) {
+ //we need to change the source
+#ifndef QT_NO_PHONON_EFFECT
+ MediaNode *next = d->effects.isEmpty() ? sink : d->effects.first();
+#else
+ MediaNode *next = sink;
+#endif //QT_NO_PHONON_EFFECT
+ QObject *bnext = next->k_ptr->backendObject();
+ if (bcurrentSource)
+ disconnections << QObjectPair(bcurrentSource, bnext);
+ connections << QObjectPair(bnewSource, bnext);
+ }
+
+ if (bnewSink != bcurrentSink) {
+#ifndef QT_NO_PHONON_EFFECT
+ MediaNode *previous = d->effects.isEmpty() ? source : d->effects.last();
+#else
+ MediaNode *previous = source;
+#endif //QT_NO_PHONON_EFFECT
+ QObject *bprevious = previous->k_ptr->backendObject();
+ if (bcurrentSink)
+ disconnections << QObjectPair(bprevious, bcurrentSink);
+ QObjectPair pair(bprevious, bnewSink);
+ if (!connections.contains(pair)) //avoid connecting twice
+ connections << pair;
+ }
+
+ if (d->executeTransaction(disconnections, connections)) {
+
+ //everything went well: let's update the path and the sink node
+ if (d->sinkNode != sink) {
+ if (d->sinkNode) {
+ d->sinkNode->k_ptr->removeInputPath(*this);
+ d->sinkNode->k_ptr->removeDestructionHandler(d.data());
+ }
+ sink->k_ptr->addInputPath(*this);
+ d->sinkNode = sink;
+ d->sinkNode->k_ptr->addDestructionHandler(d.data());
+ }
+
+ //everything went well: let's update the path and the source node
+ if (d->sourceNode != source) {
+ source->k_ptr->addOutputPath(*this);
+ if (d->sourceNode) {
+ d->sourceNode->k_ptr->removeOutputPath(*this);
+ d->sourceNode->k_ptr->removeDestructionHandler(d.data());
+ }
+ d->sourceNode = source;
+ d->sourceNode->k_ptr->addDestructionHandler(d.data());
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Path::disconnect()
+{
+ if (!isValid()) {
+ return false;
+ }
+
+ QObjectList list;
+ if (d->sourceNode)
+ list << d->sourceNode->k_ptr->backendObject();
+#ifndef QT_NO_PHONON_EFFECT
+ for (int i = 0; i < d->effects.count(); ++i) {
+ list << d->effects.at(i)->k_ptr->backendObject();
+ }
+#endif
+ if (d->sinkNode) {
+ list << d->sinkNode->k_ptr->backendObject();
+ }
+
+ //lets build the disconnection list
+ QList<QObjectPair> disco;
+ if (list.count() >=2 ) {
+ QObjectList::const_iterator it = list.constBegin();
+ for(;it+1 != list.constEnd();++it) {
+ disco << QObjectPair(*it, *(it+1));
+ }
+ }
+
+ if (d->executeTransaction(disco, QList<QObjectPair>())) {
+ //everything went well, let's remove the reference
+ //to the paths from the source and sink
+ if (d->sourceNode) {
+ d->sourceNode->k_ptr->removeOutputPath(*this);
+ d->sourceNode->k_ptr->removeDestructionHandler(d.data());
+ }
+ d->sourceNode = 0;
+
+#ifndef QT_NO_PHONON_EFFECT
+ for (int i = 0; i < d->effects.count(); ++i) {
+ d->effects.at(i)->k_ptr->removeDestructionHandler(d.data());
+ }
+ d->effects.clear();
+#endif
+
+ if (d->sinkNode) {
+ d->sinkNode->k_ptr->removeInputPath(*this);
+ d->sinkNode->k_ptr->removeDestructionHandler(d.data());
+ }
+ d->sinkNode = 0;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+MediaNode *Path::source() const
+{
+ return d->sourceNode;
+}
+
+MediaNode *Path::sink() const
+{
+ return d->sinkNode;
+}
+
+
+
+bool PathPrivate::executeTransaction( const QList<QObjectPair> &disconnections, const QList<QObjectPair> &connections)
+{
+ QSet<QObject*> nodesForTransaction;
+ for (int i = 0; i < disconnections.count(); ++i) {
+ const QObjectPair &pair = disconnections.at(i);
+ nodesForTransaction << pair.first;
+ nodesForTransaction << pair.second;
+ }
+ for (int i = 0; i < connections.count(); ++i) {
+ const QObjectPair &pair = connections.at(i);
+ nodesForTransaction << pair.first;
+ nodesForTransaction << pair.second;
+ }
+ BackendInterface *backend = qobject_cast<BackendInterface *>(Factory::backend());
+ if (!backend)
+ return false;
+
+ ConnectionTransaction transaction(backend, nodesForTransaction);
+ if (!transaction)
+ return false;
+
+ QList<QObjectPair>::const_iterator it = disconnections.begin();
+ for(;it != disconnections.end();++it) {
+ const QObjectPair &pair = *it;
+ if (!backend->disconnectNodes(pair.first, pair.second)) {
+
+ //Error: a disconnection failed
+ QList<QObjectPair>::const_iterator it2 = disconnections.begin();
+ for(; it2 != it; ++it2) {
+ const QObjectPair &pair = *it2;
+ bool success = backend->connectNodes(pair.first, pair.second);
+ Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection
+ Q_UNUSED(success);
+ }
+ return false;
+ }
+ }
+
+ for(it = connections.begin(); it != connections.end();++it) {
+ const QObjectPair &pair = *it;
+ if (!backend->connectNodes(pair.first, pair.second)) {
+ //Error: a connection failed
+ QList<QObjectPair>::const_iterator it2 = connections.begin();
+ for(; it2 != it; ++it2) {
+ const QObjectPair &pair = *it2;
+ bool success = backend->disconnectNodes(pair.first, pair.second);
+ Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection
+ Q_UNUSED(success);
+ }
+
+ //and now let's reconnect the nodes that were disconnected: rollback
+ for (int i = 0; i < disconnections.count(); ++i) {
+ const QObjectPair &pair = disconnections.at(i);
+ bool success = backend->connectNodes(pair.first, pair.second);
+ Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection
+ Q_UNUSED(success);
+ }
+
+ return false;
+
+ }
+ }
+ return true;
+}
+
+#ifndef QT_NO_PHONON_EFFECT
+bool PathPrivate::removeEffect(Effect *effect)
+{
+ if (!effects.contains(effect))
+ return false;
+
+ QObject *leftNode = 0;
+ QObject *rightNode = 0;
+ const int index = effects.indexOf(effect);
+ if (index == 0) {
+ leftNode = sourceNode->k_ptr->backendObject(); //append
+ } else {
+ leftNode = effects[index - 1]->k_ptr->backendObject();
+ }
+ if (index == effects.size()-1) {
+ rightNode = sinkNode->k_ptr->backendObject(); //prepend
+ } else {
+ rightNode = effects[index + 1]->k_ptr->backendObject();
+ }
+
+ QList<QObjectPair> disconnections, connections;
+ QObject *beffect = effect->k_ptr->backendObject();
+ disconnections << QObjectPair(leftNode, beffect) << QObjectPair(beffect, rightNode);
+ connections << QObjectPair(leftNode, rightNode);
+
+ if (executeTransaction(disconnections, connections)) {
+ effect->k_ptr->removeDestructionHandler(this);
+ effects.removeAt(index);
+ return true;
+ }
+ return false;
+}
+#endif //QT_NO_PHONON_EFFECT
+
+
+void PathPrivate::phononObjectDestroyed(MediaNodePrivate *mediaNodePrivate)
+{
+ Q_ASSERT(mediaNodePrivate);
+ if (mediaNodePrivate == sinkNode->k_ptr || mediaNodePrivate == sourceNode->k_ptr) {
+ //let's first disconnectq the path from its source and sink
+ QObject *bsink = sinkNode->k_ptr->backendObject();
+ QObject *bsource = sourceNode->k_ptr->backendObject();
+ QList<QObjectPair> disconnections;
+#ifndef QT_NO_PHONON_EFFECT
+ disconnections << QObjectPair(bsource, effects.isEmpty() ? bsink : effects.first()->k_ptr->backendObject());
+ if (!effects.isEmpty())
+ disconnections << QObjectPair(effects.last()->k_ptr->backendObject(), bsink);
+#else
+ disconnections << QObjectPair(bsource, bsink);
+#endif //QT_NO_PHONON_EFFECT
+
+ executeTransaction(disconnections, QList<QObjectPair>());
+
+ Path p; //temporary path
+ p.d = this;
+ if (mediaNodePrivate == sinkNode->k_ptr) {
+ sourceNode->k_ptr->removeOutputPath(p);
+ sourceNode->k_ptr->removeDestructionHandler(this);
+ } else {
+ sinkNode->k_ptr->removeInputPath(p);
+ sinkNode->k_ptr->removeDestructionHandler(this);
+ }
+ sourceNode = 0;
+ sinkNode = 0;
+ } else {
+#ifndef QT_NO_PHONON_EFFECT
+ for (int i = 0; i < effects.count(); ++i) {
+ Effect *e = effects.at(i);
+ if (e->k_ptr == mediaNodePrivate) {
+ removeEffect(e);
+ }
+ }
+#endif //QT_NO_PHONON_EFFECT
+ }
+}
+
+Path createPath(MediaNode *source, MediaNode *sink)
+{
+ Path p;
+ if (!p.reconnect(source, sink)) {
+ const QObject *const src = source ? (source->k_ptr->qObject()
+#ifndef QT_NO_DYNAMIC_CAST
+ ? source->k_ptr->qObject() : dynamic_cast<QObject *>(source)
+#endif
+ ) : 0;
+ const QObject *const snk = sink ? (sink->k_ptr->qObject()
+#ifndef QT_NO_DYNAMIC_CAST
+ ? sink->k_ptr->qObject() : dynamic_cast<QObject *>(sink)
+#endif
+ ) : 0;
+ pWarning() << "Phonon::createPath: Cannot connect "
+ << (src ? src->metaObject()->className() : "")
+ << '(' << (src ? (src->objectName().isEmpty() ? "no objectName" : qPrintable(src->objectName())) : "null") << ") to "
+ << (snk ? snk->metaObject()->className() : "")
+ << '(' << (snk ? (snk->objectName().isEmpty() ? "no objectName" : qPrintable(snk->objectName())) : "null")
+ << ").";
+ }
+ return p;
+}
+
+
+Path & Path::operator=(const Path &other)
+{
+ d = other.d;
+ return *this;
+}
+
+bool Path::operator==(const Path &other) const
+{
+ return d == other.d;
+}
+
+bool Path::operator!=(const Path &other) const
+{
+ return !operator==(other);
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/path.h b/src/3rdparty/phonon/phonon/path.h
new file mode 100644
index 0000000..6193054
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/path.h
@@ -0,0 +1,243 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_PATH_H
+#define PHONON_PATH_H
+
+#include "phonon_export.h"
+#include "objectdescription.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+template<class T> class QList;
+
+namespace Phonon
+{
+
+class PathPrivate;
+class Effect;
+class MediaNode;
+
+/** \class Path path.h Phonon/Path
+ * \short Connection object providing convenient effect insertion
+ *
+ * \code
+MediaObject *media = new MediaObject;
+AudioOutput *output = new AudioOutput(Phonon::MusicCategory);
+Path path = Phonon::createPath(media, output);
+Q_ASSERT(path.isValid()); // for this simple case the path should always be
+ //valid - there are unit tests to ensure it
+// insert an effect
+QList<EffectDescription> effectList = BackendCapabilities::availableAudioEffects();
+if (!effectList.isEmpty()) {
+ Effect *effect = path.insertEffect(effectList.first());
+}
+ * \endcode
+ * \ingroup Playback
+ * \ingroup Recording
+ * \author Matthias Kretz <kretz@kde.org>
+ * \author Thierry Bastian <thierry.bastian@trolltech.com>
+ */
+class PHONON_EXPORT Path
+{
+ friend class FactoryPrivate;
+ public:
+ /**
+ * Destroys this reference to the Path. If the path was valid the connection is not broken
+ * as both the source and the sink MediaNodes still keep a reference to the Path.
+ *
+ * \see disconnect
+ */
+ ~Path();
+
+ /**
+ * Creates an invalid path.
+ *
+ * You can still make it a valid path by calling reconnect. To create a path you should use
+ * createPath, though.
+ *
+ * \see createPath
+ * \see isValid
+ */
+ Path();
+
+ /**
+ * Constructs a copy of the given path.
+ *
+ * This constructor is fast thanks to explicit sharing.
+ */
+ Path(const Path &);
+
+ /**
+ * Returns whether the path object connects two MediaNodes or not.
+ *
+ * \return \p true when the path connects two MediaNodes
+ * \return \p false when the path is disconnected
+ */
+ bool isValid() const;
+ //MediaStreamTypes mediaStreamTypes() const;
+
+#ifndef QT_NO_PHONON_EFFECT
+ /**
+ * Creates and inserts an effect into the path.
+ *
+ * You may insert effects of the same class as often as you like,
+ * but if you insert the same object, the call will fail.
+ *
+ * \param desc The EffectDescription object for the effect to be inserted.
+ *
+ * \param insertBefore If you already inserted an effect you can
+ * tell with this parameter in which order the data gets
+ * processed. If this is \c 0 the effect is appended at the end of
+ * the processing list. If the effect has not been inserted before
+ * the method will do nothing and return \c false.
+ *
+ * \return Returns a pointer to the effect object if it could be inserted
+ * at the specified position. If \c 0 is returned the effect was not
+ * inserted.
+ *
+ * \see removeEffect
+ * \see effects
+ */
+ Effect *insertEffect(const EffectDescription &desc, Effect *insertBefore = 0);
+
+ /**
+ * Inserts an effect into the path.
+ *
+ * You may insert effects of the same class as often as you like,
+ * but if you insert the same object, the call will fail.
+ *
+ * \param newEffect An Effect object.
+ *
+ * \param insertBefore If you already inserted an effect you can
+ * tell with this parameter in which order the data gets
+ * processed. If this is \c 0 the effect is appended at the end of
+ * the processing list. If the effect has not been inserted before
+ * the method will do nothing and return \c false.
+ *
+ * \return Returns whether the effect could be inserted at the
+ * specified position. If \c false is returned the effect was not
+ * inserted.
+ *
+ * \see removeEffect
+ * \see effects
+ */
+ bool insertEffect(Effect *newEffect, Effect *insertBefore = 0);
+
+ /**
+ * Removes an effect from the path.
+ *
+ * If the effect gets deleted while it is still connected the effect
+ * will be removed automatically.
+ *
+ * \param effect The effect to be removed.
+ *
+ * \return Returns whether the call was successful. If it returns
+ * \c false the effect could not be found in the path, meaning it
+ * has not been inserted before.
+ *
+ * \see insertEffect
+ * \see effects
+ */
+ bool removeEffect(Effect *effect);
+
+ /**
+ * Returns a list of Effect objects that are currently
+ * used as effects. The order in the list determines the order the
+ * signal is sent through the effects.
+ *
+ * \return A list with all current effects.
+ *
+ * \see insertEffect
+ * \see removeEffect
+ */
+ QList<Effect *> effects() const;
+#endif //QT_NO_PHONON_EFFECT
+
+ /**
+ * Tries to change the MediaNodes the path is connected to.
+ *
+ * If reconnect fails the old connection is kept.
+ */
+ bool reconnect(MediaNode *source, MediaNode *sink);
+
+ /**
+ * Disconnects the path from the MediaNodes it was connected to. This invalidates the path
+ * (isValid returns \p false then).
+ */
+ bool disconnect();
+
+ /**
+ * Assigns \p p to this Path and returns a reference to this Path.
+ *
+ * This operation is fast thanks to explicit sharing.
+ */
+ Path &operator=(const Path &p);
+
+ /**
+ * Returns \p true if this Path is equal to \p p; otherwise returns \p false;
+ */
+ bool operator==(const Path &p) const;
+
+ /**
+ * Returns \p true if this Path is not equal to \p p; otherwise returns \p false;
+ */
+ bool operator!=(const Path &p) const;
+
+ /**
+ * Returns the source MediaNode used by the path.
+ */
+ MediaNode *source() const;
+
+ /**
+ * Returns the sink MediaNode used by the path.
+ */
+ MediaNode *sink() const;
+
+
+ protected:
+ friend class PathPrivate;
+ QExplicitlySharedDataPointer<PathPrivate> d;
+};
+
+/**
+ * \relates Path
+ * Creates a new Path connecting two MediaNodes.
+ *
+ * The implementation will automatically select the right format and media type. E.g. connecting a
+ * MediaObject and AudioOutput will create a Path object connecting the audio. This might be
+ * represented as PCM or perhaps even AC3 depending on the AudioOutput object.
+ *
+ * \param source The MediaNode to connect an output from
+ * \param sink The MediaNode to connect to.
+ */
+PHONON_EXPORT Path createPath(MediaNode *source, MediaNode *sink);
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_PATH_H
diff --git a/src/3rdparty/phonon/phonon/path_p.h b/src/3rdparty/phonon/phonon/path_p.h
new file mode 100644
index 0000000..51b7e83
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/path_p.h
@@ -0,0 +1,79 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PATH_P_H
+#define PATH_P_H
+
+#include "path.h"
+#include <QtCore/QPair>
+#include <QtCore/QList>
+#include <QtCore/QSharedData>
+#include "effect.h"
+#include "medianodedestructionhandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+
+namespace Phonon
+{
+
+class MediaNode;
+typedef QPair<QObject*, QObject*> QObjectPair;
+
+
+class PathPrivate : public QSharedData, private MediaNodeDestructionHandler
+{
+ friend class Path;
+ public:
+ PathPrivate()
+ : sourceNode(0), sinkNode(0)
+#ifndef QT_NO_PHONON_EFFECT
+ , effectsParent(0)
+#endif //QT_NO_PHONON_EFFECT
+ {
+ }
+
+ ~PathPrivate();
+
+ MediaNode *sourceNode;
+ MediaNode *sinkNode;
+
+ protected:
+ void phononObjectDestroyed(MediaNodePrivate *);
+
+#ifndef QT_NO_PHONON_EFFECT
+ QObject *effectsParent; // used as parent for Effects created in insertEffect
+ QList<Effect *> effects;
+#endif
+ private:
+ bool executeTransaction( const QList<QObjectPair> &disconnections, const QList<QObjectPair> &connections);
+#ifndef QT_NO_PHONON_EFFECT
+ bool removeEffect(Effect *effect);
+#endif
+};
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // PATH_P_H
diff --git a/src/3rdparty/phonon/phonon/phonon_export.h b/src/3rdparty/phonon/phonon/phonon_export.h
new file mode 100644
index 0000000..96b5159
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/phonon_export.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_EXPORT_H
+#define PHONON_EXPORT_H
+
+#include <QtCore/QtGlobal>
+
+#ifndef PHONON_EXPORT
+# if defined Q_WS_WIN
+# ifdef MAKE_PHONON_LIB /* We are building this library */
+# define PHONON_EXPORT Q_DECL_EXPORT
+# else /* We are using this library */
+# define PHONON_EXPORT Q_DECL_IMPORT
+# endif
+# else /* UNIX */
+# ifdef MAKE_PHONON_LIB /* We are building this library */
+# define PHONON_EXPORT Q_DECL_EXPORT
+# else /* We are using this library */
+# define PHONON_EXPORT Q_DECL_IMPORT
+# endif
+# endif
+#endif
+
+#ifndef PHONON_EXPORT_DEPRECATED
+# define PHONON_EXPORT_DEPRECATED Q_DECL_DEPRECATED PHONON_EXPORT
+#endif
+
+// QT_(BEGIN|END)_NAMESPACE appeared in 4.4
+#ifndef QT_BEGIN_NAMESPACE
+# define QT_BEGIN_NAMESPACE
+#endif
+#ifndef QT_END_NAMESPACE
+# define QT_END_NAMESPACE
+#endif
+
+// silence syncqt
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif
diff --git a/src/3rdparty/phonon/phonon/phonondefs.h b/src/3rdparty/phonon/phonon/phonondefs.h
new file mode 100644
index 0000000..765eb1c
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/phonondefs.h
@@ -0,0 +1,149 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONONDEFS_H
+#define PHONONDEFS_H
+
+#include <QtCore/QtGlobal>
+#include "phonon_export.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifdef PHONON_BACKEND_VERSION_4_4
+# ifndef PHONON_BACKEND_VERSION_4_3
+# define PHONON_BACKEND_VERSION_4_3
+# endif
+#endif
+#ifdef PHONON_BACKEND_VERSION_4_3
+# ifndef PHONON_BACKEND_VERSION_4_2
+# define PHONON_BACKEND_VERSION_4_2
+# endif
+#endif
+
+// the following inlines are correct - exclude per line doesn't work for multiline-macros so exclude
+// the whole file for inline checks
+//krazy:excludeall=inline
+#define K_DECLARE_PRIVATE(Class) \
+ inline Class##Private* k_func() { return reinterpret_cast<Class##Private *>(k_ptr); } \
+ inline const Class##Private* k_func() const { return reinterpret_cast<const Class##Private *>(k_ptr); } \
+ friend class Class##Private;
+
+/**
+ * \internal
+ * Used in class declarations to provide the needed functions. This is used for
+ * abstract base classes.
+ *
+ * \param classname The Name of the class this macro is used for.
+ *
+ * Example:
+ * \code
+ * class AbstractEffect : public QObject
+ * {
+ * Q _OBJECT
+ * Q_PROPERTY(int propertyA READ propertyA WRITE setPropertyA)
+ * PHONON_ABSTRACTBASE(AbstractEffect)
+ * public:
+ * int propertyA() const;
+ * void setPropertyA(int);
+ * };
+ * \endcode
+ *
+ * \see PHONON_OBJECT
+ * \see PHONON_HEIR
+ */
+#define PHONON_ABSTRACTBASE(classname) \
+protected: \
+ /**
+ * \internal
+ * Constructor that is called from derived classes.
+ *
+ * \param parent Standard QObject parent.
+ */ \
+ classname(classname ## Private &dd, QObject *parent); \
+private:
+
+/**
+ * \internal
+ * Used in class declarations to provide the needed functions. This is used for
+ * classes that inherit QObject directly.
+ *
+ * \param classname The Name of the class this macro is used for.
+ *
+ * Example:
+ * \code
+ * class EffectSettings : public QObject
+ * {
+ * Q _OBJECT
+ * Q_PROPERTY(int propertyA READ propertyA WRITE setPropertyA)
+ * PHONON_OBJECT(EffectSettings)
+ * public:
+ * int propertyA() const;
+ * void setPropertyA(int);
+ * };
+ * \endcode
+ *
+ * \see PHONON_ABSTRACTBASE
+ * \see PHONON_HEIR
+ */
+#define PHONON_OBJECT(classname) \
+public: \
+ /**
+ * Constructs an object with the given \p parent.
+ */ \
+ classname(QObject *parent = 0); \
+private:
+
+/**
+ * \internal
+ * Used in class declarations to provide the needed functions. This is used for
+ * classes that inherit another Phonon object.
+ *
+ * \param classname The Name of the class this macro is used for.
+ *
+ * Example:
+ * \code
+ * class ConcreteEffect : public AbstractEffect
+ * {
+ * Q _OBJECT
+ * Q_PROPERTY(int propertyB READ propertyB WRITE setPropertyB)
+ * PHONON_HEIR(ConcreteEffect)
+ * public:
+ * int propertyB() const;
+ * void setPropertyB(int);
+ * };
+ * \endcode
+ *
+ * \see PHONON_ABSTRACTBASE
+ * \see PHONON_OBJECT
+ */
+#define PHONON_HEIR(classname) \
+public: \
+ /**
+ * Constructs an object with the given \p parent.
+ */ \
+ classname(QObject *parent = 0); \
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONONDEFS_H
diff --git a/src/3rdparty/phonon/phonon/phonondefs_p.h b/src/3rdparty/phonon/phonon/phonondefs_p.h
new file mode 100644
index 0000000..778d7f6
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/phonondefs_p.h
@@ -0,0 +1,369 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONONDEFS_P_H
+#define PHONONDEFS_P_H
+
+#include <QtCore/QMetaType>
+#include "medianode_p.h"
+
+#define K_D(Class) Class##Private *const d = k_func()
+
+#define PHONON_CONCAT_HELPER_INTERNAL(x, y) x ## y
+#define PHONON_CONCAT_HELPER(x, y) PHONON_CONCAT_HELPER_INTERNAL(x, y)
+
+#define PHONON_PRIVATECLASS \
+protected: \
+ virtual bool aboutToDeleteBackendObject(); \
+ virtual void createBackendObject(); \
+ /**
+ * \internal
+ * After construction of the Iface object this method is called
+ * throughout the complete class hierarchy in order to set up the
+ * properties that were already set on the public interface.
+ *
+ * An example implementation could look like this:
+ * \code
+ * ParentClassPrivate::setupBackendObject();
+ * m_iface->setPropertyA(d->propertyA);
+ * m_iface->setPropertyB(d->propertyB);
+ * \endcode
+ */ \
+ void setupBackendObject();
+
+#define PHONON_PRIVATEABSTRACTCLASS \
+protected: \
+ virtual bool aboutToDeleteBackendObject(); \
+ /**
+ * \internal
+ * After construction of the Iface object this method is called
+ * throughout the complete class hierarchy in order to set up the
+ * properties that were already set on the public interface.
+ *
+ * An example implementation could look like this:
+ * \code
+ * ParentClassPrivate::setupBackendObject();
+ * m_iface->setPropertyA(d->propertyA);
+ * m_iface->setPropertyB(d->propertyB);
+ * \endcode
+ */ \
+ void setupBackendObject();
+
+#define PHONON_ABSTRACTBASE_IMPL \
+PHONON_CLASSNAME::PHONON_CLASSNAME(PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) &dd, QObject *parent) \
+ : QObject(parent), \
+ MediaNode(dd) \
+{ \
+}
+
+#define PHONON_OBJECT_IMPL \
+PHONON_CLASSNAME::PHONON_CLASSNAME(QObject *parent) \
+ : QObject(parent), \
+ MediaNode(*new PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)()) \
+{ \
+} \
+void PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)::createBackendObject() \
+{ \
+ if (m_backendObject) \
+ return; \
+ Q_Q(PHONON_CLASSNAME); \
+ m_backendObject = Factory::PHONON_CONCAT_HELPER(create, PHONON_CLASSNAME)(q); \
+ if (m_backendObject) { \
+ setupBackendObject(); \
+ } \
+}
+
+#define PHONON_HEIR_IMPL(parentclass) \
+PHONON_CLASSNAME::PHONON_CLASSNAME(QObject *parent) \
+ : parentclass(*new PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private), parent) \
+{ \
+} \
+void PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private)::createBackendObject() \
+{ \
+ if (m_backendObject) \
+ return; \
+ Q_Q(PHONON_CLASSNAME); \
+ m_backendObject = Factory::PHONON_CONCAT_HELPER(create, PHONON_CLASSNAME)(q); \
+ if (m_backendObject) { \
+ setupBackendObject(); \
+ } \
+}
+
+#define BACKEND_GET(returnType, returnVar, methodName) \
+QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar))
+#define BACKEND_GET1(returnType, returnVar, methodName, varType1, var1) \
+QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1))
+#define BACKEND_GET2(returnType, returnVar, methodName, varType1, var1, varType2, var2) \
+QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1), Q_ARG(varType2, var2))
+#define BACKEND_CALL(methodName) \
+QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection)
+#define BACKEND_CALL1(methodName, varType1, var1) \
+QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1))
+#define BACKEND_CALL2(methodName, varType1, var1, varType2, var2) \
+QMetaObject::invokeMethod(d->m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1), Q_ARG(varType2, var2))
+
+#define pBACKEND_GET(returnType, returnVar, methodName) \
+QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar))
+#define pBACKEND_GET1(returnType, returnVar, methodName, varType1, var1) \
+QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1))
+#define pBACKEND_GET2(returnType, returnVar, methodName, varType1, var1, varType2, var2) \
+QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_RETURN_ARG(returnType, returnVar), Q_ARG(varType1, var1), Q_ARG(varType2, var2))
+#define pBACKEND_CALL(methodName) \
+QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection)
+#define pBACKEND_CALL1(methodName, varType1, var1) \
+QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1))
+#define pBACKEND_CALL2(methodName, varType1, var1, varType2, var2) \
+QMetaObject::invokeMethod(m_backendObject, methodName, Qt::DirectConnection, Q_ARG(varType1, var1), Q_ARG(varType2, var2))
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace
+ {
+ class NoIface;
+
+ /// All template arguments are valid
+ template<typename T> struct IsValid { enum { Result = true }; };
+ /// except NoIface
+ template<> struct IsValid<NoIface> { enum { Result = false }; };
+
+ template<class T> inline T my_cast(QObject *o) { return qobject_cast<T>(o); }
+ template<class T> inline T my_cast(const QObject *o) { return qobject_cast<T>(o); }
+
+ template<> inline NoIface *my_cast<NoIface *>(QObject *) { return 0; }
+ template<> inline NoIface *my_cast<NoIface *>(const QObject *) { return 0; }
+ } // anonymous namespace
+
+ /**
+ * \internal
+ *
+ * \brief Helper class to cast the backend object to the correct version of the interface.
+ *
+ * Additions to the backend interfaces cannot be done by adding virtual methods as that would
+ * break the binary interface. So the old class is renamed and a new class with the old name
+ * inheriting the old class is added, containing all the new virtual methods.
+ * Example:
+ * \code
+ class FooInterface
+ {
+ public:
+ virtual ~FooInterface() {}
+ virtual oldMethod() = 0;
+ };
+ Q_DECLARE_INTERFACE(FooInterface, "FooInterface0.phonon.kde.org")
+ * \endcode
+ * becomes
+ * \code
+ class FooInterface0
+ {
+ public:
+ virtual ~FooInterface0() {}
+ virtual oldMethod() = 0;
+ };
+ class FooInterface : public FooInterface0
+ {
+ public:
+ virtual newMethod() = 0;
+ };
+ Q_DECLARE_INTERFACE(FooInterface0, "FooInterface0.phonon.kde.org")
+ Q_DECLARE_INTERFACE(FooInterface, "FooInterface1.phonon.kde.org")
+ * \endcode
+ *
+ * With this, backends compiled against the old header can be qobject_casted to FooInterface0,
+ * but not to FooInterface. On the other hand backends compiled against the new header (they first
+ * need to implement newMethod) can only be qobject_casted to FooInterface but not to
+ * FooInterface0. (The qobject_cast relies on the string in Q_DECLARE_INTERFACE and not the
+ * class name which is why it behaves that way.)
+ *
+ * Now, in order to call oldMethod, the code needs to try to cast to both FooInterface and
+ * FooInterface0 (new backends will work with the former, old backends with the latter) and then
+ * if one of them in non-zero call oldMethod on it.
+ *
+ * To call newMethod only a cast to FooInterface needs to be done.
+ *
+ * The Iface class does all this for you for up to three (for now) interface revisions. Just
+ * create an object like this:
+ * \code
+ Iface<FooInterface0, FooInterface> iface0(d);
+ if (iface0) {
+ iface0->oldMethod();
+ }
+ Iface<FooInterface> iface(d);
+ if (iface) {
+ iface->newMethod();
+ }
+ * \endcode
+ *
+ * This becomes a bit more convenient if you add macros like this:
+ * \code
+ #define IFACES1 FooInterface
+ #define IFACES0 FooInterface0, IFACES1
+ * \endcode
+ * which you can use like this:
+ * \code
+ Iface<IFACES0> iface0(d);
+ if (iface0) {
+ iface0->oldMethod();
+ }
+ Iface<IFACES1> iface(d);
+ if (iface) {
+ iface->newMethod();
+ }
+ * \endcode
+ * With the next revision you can then change the macros to
+ * \code
+ #define IFACES2 FooInterface
+ #define IFACES1 FooInterface1, IFACES2
+ #define IFACES0 FooInterface0, IFACES1
+ * \endcode
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ template<class T0, class T1 = NoIface, class T2 = NoIface>
+ class Iface
+ {
+ public:
+ static inline T0 *cast(MediaNodePrivate *const d)
+ {
+ if (IsValid<T1>::Result) {
+ T0 *ret;
+ if (IsValid<T2>::Result) {
+ ret = reinterpret_cast<T0 *>(my_cast<T2 *>(d->m_backendObject));
+ if (ret) return ret;
+ }
+ ret = reinterpret_cast<T0 *>(my_cast<T1 *>(d->m_backendObject));
+ if (ret) return ret;
+ }
+ return qobject_cast<T0 *>(d->m_backendObject);
+ }
+
+ static inline const T0 *cast(const MediaNodePrivate *const d)
+ {
+ if (IsValid<T1>::Result) {
+ const T0 *ret;
+ if (IsValid<T2>::Result) {
+ ret = reinterpret_cast<const T0 *>(my_cast<T2 *>(d->m_backendObject));
+ if (ret) return ret;
+ }
+ ret = reinterpret_cast<const T0 *>(my_cast<T1 *>(d->m_backendObject));
+ if (ret) return ret;
+ }
+ return qobject_cast<T0 *>(d->m_backendObject);
+ }
+
+ inline Iface(MediaNodePrivate *const d) : iface(cast(d)) {}
+ inline operator T0 *() { return iface; }
+ inline operator const T0 *() const { return iface; }
+ inline T0 *operator->() { Q_ASSERT(iface); return iface; }
+ inline const T0 *operator->() const { Q_ASSERT(iface); return iface; }
+ private:
+ T0 *const iface;
+ };
+
+ template<class T0, class T1 = NoIface, class T2 = NoIface>
+ class ConstIface
+ {
+ public:
+ inline ConstIface(const MediaNodePrivate *const d) : iface(Iface<T0, T1, T2>::cast(d)) {}
+ inline operator const T0 *() const { return iface; }
+ inline const T0 *operator->() const { Q_ASSERT(iface); return iface; }
+ private:
+ const T0 *const iface;
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#define INTERFACE_CALL(function) \
+Iface<PHONON_INTERFACENAME >::cast(d)->function
+
+#define pINTERFACE_CALL(function) \
+Iface<PHONON_INTERFACENAME >::cast(this)->function
+
+#define PHONON_GETTER(rettype, name, retdefault) \
+rettype PHONON_CLASSNAME::name() const \
+{ \
+ const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
+ if (!d->m_backendObject) \
+ return retdefault; \
+ rettype ret; \
+ BACKEND_GET(rettype, ret, #name); \
+ return ret; \
+}
+
+#define PHONON_INTERFACE_GETTER(rettype, name, retdefault) \
+rettype PHONON_CLASSNAME::name() const \
+{ \
+ const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
+ if (!d->m_backendObject) \
+ return retdefault; \
+ return Iface<PHONON_INTERFACENAME >::cast(d)->name(); \
+}
+
+#define PHONON_GETTER1(rettype, name, retdefault, argtype1, argvar1) \
+rettype PHONON_CLASSNAME::name(argtype1 argvar1) const \
+{ \
+ const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
+ if (!d->m_backendObject) \
+ return retdefault; \
+ rettype ret; \
+ BACKEND_GET1(rettype, ret, #name, const QObject *, argvar1->k_ptr->backendObject()); \
+ return ret; \
+}
+
+#define PHONON_INTERFACE_GETTER1(rettype, name, retdefault, argtype1, argvar1) \
+rettype PHONON_CLASSNAME::name(argtype1 argvar1) const \
+{ \
+ const PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
+ if (!d->m_backendObject) \
+ return retdefault; \
+ return Iface<PHONON_INTERFACENAME >::cast(d)->name(argvar1->k_ptr->backendObject()); \
+}
+
+#define PHONON_SETTER(functionname, privatevar, argtype1) \
+void PHONON_CLASSNAME::functionname(argtype1 x) \
+{ \
+ PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
+ d->privatevar = x; \
+ if (k_ptr->backendObject()) { \
+ BACKEND_CALL1(#functionname, argtype1, x); \
+ } \
+}
+
+#define PHONON_INTERFACE_SETTER(functionname, privatevar, argtype1) \
+void PHONON_CLASSNAME::functionname(argtype1 x) \
+{ \
+ PHONON_CONCAT_HELPER(PHONON_CLASSNAME, Private) *d = k_func(); \
+ d->privatevar = x; \
+ if (k_ptr->backendObject()) { \
+ Iface<PHONON_INTERFACENAME >::cast(d)->functionname(x); \
+ } \
+}
+
+#ifndef METATYPE_QLIST_INT_DEFINED
+#define METATYPE_QLIST_INT_DEFINED
+// Want this exactly once, see phonondefs_p.h kcm/outputdevicechoice.cpp
+Q_DECLARE_METATYPE(QList<int>)
+#endif
+
+#endif // PHONONDEFS_P_H
diff --git a/src/3rdparty/phonon/phonon/phononnamespace.cpp b/src/3rdparty/phonon/phonon/phononnamespace.cpp
new file mode 100644
index 0000000..ba20aa5
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/phononnamespace.cpp
@@ -0,0 +1,92 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "phononnamespace.h"
+#include "phononnamespace_p.h"
+#include "phonondefs_p.h"
+
+#include "factory_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ /*!
+ Returns the version number of Phonon at run-time as a string (for
+ example, "4.0.0"). This may be a different version than the
+ version the application was compiled against.
+
+ \sa PHONON_VERSION_STR
+ */
+ const char *phononVersion()
+ {
+ return PHONON_VERSION_STR;
+ }
+
+ QString categoryToString(Category c)
+ {
+ switch(c)
+ {
+ case Phonon::NoCategory:
+ break;
+ case Phonon::NotificationCategory:
+ return QCoreApplication::translate("Phonon::", "Notifications");
+ case Phonon::MusicCategory:
+ return QCoreApplication::translate("Phonon::", "Music");
+ case Phonon::VideoCategory:
+ return QCoreApplication::translate("Phonon::", "Video");
+ case Phonon::CommunicationCategory:
+ return QCoreApplication::translate("Phonon::", "Communication");
+ case Phonon::GameCategory:
+ return QCoreApplication::translate("Phonon::", "Games");
+ case Phonon::AccessibilityCategory:
+ return QCoreApplication::translate("Phonon::", "Accessibility");
+ }
+ return QString();
+ }
+}
+
+static int registerPhononMetaTypes()
+{
+ qRegisterMetaType<Phonon::State>();
+ qRegisterMetaType<Phonon::ErrorType>();
+ qRegisterMetaType<Phonon::Category>();
+
+ // need those for QSettings
+ qRegisterMetaType<QList<int> >();
+ qRegisterMetaTypeStreamOperators<QList<int> >("QList<int>");
+
+ return 0; // something
+}
+
+#ifdef Q_CONSTRUCTOR_FUNCTION
+Q_CONSTRUCTOR_FUNCTION(registerPhononMetaTypes)
+#else
+static const int _Phonon_registerMetaTypes = registerPhononMetaTypes();
+#endif
+
+QT_END_NAMESPACE
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/phononnamespace.h b/src/3rdparty/phonon/phonon/phononnamespace.h
new file mode 100644
index 0000000..eb899de
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/phononnamespace.h
@@ -0,0 +1,311 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONONNAMESPACE_H
+#define PHONONNAMESPACE_H
+
+#include "phonon_export.h"
+
+#ifdef __QT_SYNCQT__
+// Tell syncqt to create a "Global" header here
+#pragma qt_class(Phonon::Global)
+#endif
+
+/**
+ * Helper macro that can be used like
+ * \code
+ * #if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 4, 0))
+ * \endcode
+ */
+#define PHONON_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+
+/**
+ * PHONON_VERSION is (major << 16) + (minor << 8) + patch.
+ */
+#define PHONON_VERSION PHONON_VERSION_CHECK(4, 4, 0)
+
+/**
+ * PHONON_VERSION_STR is "major.minor.patch". E.g. "4.2.1"
+ */
+#define PHONON_VERSION_STR "4.4.0"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+/**
+ * \brief The %KDE Multimedia classes
+ *
+ * In this Namespace you find the classes to access Multimedia functions for
+ * audio and video playback. Those classes are not dependent
+ * on any specific framework (like they were in pre KDE4 times) but rather use
+ * exchangeable backends to do the work.
+ *
+ * If you want to write a new backend take a look at \ref phonon_backend_development_page.
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+namespace Phonon
+{
+ PHONON_EXPORT const char *phononVersion();
+
+ /**
+ * Enum to identify the media discs supported by MediaObject.
+ *
+ * \see MediaSource(Phonon::DiscType, const QString &deviceName)
+ */
+ enum DiscType {
+ /**
+ * No disc was selected. This is only useful as a return value from
+ * MediaSource::distType();
+ */
+ NoDisc = -1,
+ /**
+ * Identifies Audio CDs.
+ */
+ Cd = 0,
+ /**
+ * Identifies DVDs (not arbitrary data DVDs, only movie DVDs).
+ */
+ Dvd = 1,
+ /**
+ * Identifies Video CDs.
+ */
+ Vcd = 2
+ };
+
+ /**
+ * Provided as keys for \ref MediaObject::metaData for convenience, in addition to the strings defined in
+ * the Ogg Vorbis specification.
+ */
+ enum MetaData {
+ /**
+ * The artist generally considered responsible for the work. In popular
+ * music this is usually the performing band or singer. For classical
+ * music it would be the composer. For an audio book it would be the
+ * author of the original text.
+ */
+ ArtistMetaData,
+ /**
+ * The collection name to which this track belongs.
+ */
+ AlbumMetaData,
+ /**
+ * Track/Work name
+ */
+ TitleMetaData,
+ /**
+ * Date the track was recorded
+ */
+ DateMetaData,
+ /**
+ * A short text indication of music genre
+ */
+ GenreMetaData,
+ /**
+ * The track number of this piece if part of a specific larger
+ * collection or album
+ */
+ TracknumberMetaData,
+ /**
+ * A short text description of the contents
+ */
+ DescriptionMetaData,
+ MusicBrainzDiscIdMetaData
+ };
+
+ /**
+ * The state the media producing object is in at the moment.
+ *
+ * \see MediaObject
+ */
+ enum State
+ {
+ /**
+ * After construction it might take a while before the Player is
+ * ready to play(). Normally this doesn't happen for local
+ * files, but can happen for remote files where the asynchronous
+ * mimetype detection and prebuffering can take a while.
+ */
+ LoadingState,
+ /**
+ * The Player has a valid media file loaded and is ready for
+ * playing.
+ */
+ StoppedState,
+ /**
+ * The Player is playing a media file.
+ */
+ PlayingState,
+ /**
+ * The Player is waiting for data to be able to continue
+ * playing.
+ */
+ BufferingState,
+ /**
+ * The Player is currently paused.
+ */
+ PausedState,
+ /**
+ * An unrecoverable error occurred. The Object is unusable in this state.
+ */
+ ErrorState
+ };
+
+ /**
+ * Set's the category your program should be listed in in the mixer.
+ *
+ * A Jukebox will set this to Music, a VoIP program to Communication, a
+ * DVD player to video, and so on.
+ *
+ * \note These categories can also become useful for an application that
+ * controls the volumes automatically, like turning down the music when a call
+ * comes in, or turning down the notifications when the media player knows
+ * it's playing classical music.
+ *
+ * \see AudioOutput::setCategory
+ */
+ enum Category
+ {
+ /**
+ * Will make use of the default device.
+ */
+ NoCategory = -1,
+ /**
+ * If the sounds produced are notifications (bing, beep and such) you
+ * should use this category.
+ */
+ NotificationCategory = 0,
+ /**
+ * If your application is a music player (like a jukebox or media player
+ * playing an audio file).
+ */
+ MusicCategory = 1,
+ /**
+ * If the sound is the audio channel of a video.
+ */
+ VideoCategory = 2,
+ /**
+ * If your applications produces sounds from communication with somebody
+ * else (VoIP, voice chat).
+ */
+ CommunicationCategory = 3,
+ /**
+ * Sound produced by a computer game should go into this category.
+ */
+ GameCategory = 4,
+ /**
+ * Sounds produced for accessibility (e.g. Text-To-Speech)
+ */
+ AccessibilityCategory = 5,
+ /**
+ * \internal
+ * Holds the largest value of categories.
+ */
+ LastCategory = AccessibilityCategory
+ };
+
+ /**
+ * Tells your program how to recover from an error.
+ *
+ * \see MediaObject::errorType()
+ */
+ enum ErrorType {
+ /**
+ * No error. MediaObject::errorType() returns this if
+ * MediaObject::state() != Phonon::ErrorState.
+ */
+ NoError = 0,
+ /**
+ * Playback should work, and trying with another URL should work.
+ */
+ NormalError = 1,
+ /**
+ * Something important does not work. Your program cannot continue
+ * playback or capture or whatever it was trying to do
+ * without help from the user.
+ */
+ FatalError = 2
+ };
+
+ /**
+ * Returns a (translated) string to show to the user identifying the given
+ * Category.
+ */
+ PHONON_EXPORT QString categoryToString(Category c);
+
+ // TODO: naming
+ /*enum MediaStreamType {
+ Audio = 1,
+ Video = 2,
+ StillImage = 4,
+ Subtitle = 8,
+ AllMedia = 0xFFFFFFFF
+ };
+ Q_DECLARE_FLAGS(MediaStreamTypes, MediaStreamType)*/
+} // namespace Phonon
+//Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::MediaStreamTypes)
+
+QT_END_NAMESPACE
+
+//X class kdbgstream;
+//X #include <kdebug.h>
+//X /**
+//X * Implements needed operator to use Phonon::State with kDebug
+//X */
+//X inline PHONON_EXPORT kdbgstream &operator<<(kdbgstream & stream, const Phonon::State state)
+//X {
+//X switch(state)
+//X {
+//X case Phonon::ErrorState:
+//X stream << "ErrorState";
+//X break;
+//X case Phonon::LoadingState:
+//X stream << "LoadingState";
+//X break;
+//X case Phonon::StoppedState:
+//X stream << "StoppedState";
+//X break;
+//X case Phonon::PlayingState:
+//X stream << "PlayingState";
+//X break;
+//X case Phonon::BufferingState:
+//X stream << "BufferingState";
+//X break;
+//X case Phonon::PausedState:
+//X stream << "PausedState";
+//X break;
+//X }
+//X return stream;
+//X }
+
+#include <QtCore/QMetaType>
+
+Q_DECLARE_METATYPE(Phonon::State)
+Q_DECLARE_METATYPE(Phonon::ErrorType)
+Q_DECLARE_METATYPE(Phonon::Category)
+
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // PHONONNAMESPACE_H
diff --git a/src/3rdparty/phonon/phonon/phononnamespace.h.in b/src/3rdparty/phonon/phonon/phononnamespace.h.in
new file mode 100644
index 0000000..c65c121
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/phononnamespace.h.in
@@ -0,0 +1,306 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONONNAMESPACE_H
+#define PHONONNAMESPACE_H
+
+#include "phonon_export.h"
+
+/**
+ * Helper macro that can be used like
+ * \code
+ * #if (PHONON_VERSION >= PHONON_VERSION_CHECK(4, 4, 0))
+ * \endcode
+ */
+#define PHONON_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
+
+/**
+ * PHONON_VERSION is (major << 16) + (minor << 8) + patch.
+ */
+#define PHONON_VERSION PHONON_VERSION_CHECK(@PHONON_LIB_MAJOR_VERSION@, @PHONON_LIB_MINOR_VERSION@, @PHONON_LIB_PATCH_VERSION@)
+
+/**
+ * PHONON_VERSION_STR is "major.minor.patch". E.g. "4.2.1"
+ */
+#define PHONON_VERSION_STR "@PHONON_LIB_MAJOR_VERSION@.@PHONON_LIB_MINOR_VERSION@.@PHONON_LIB_PATCH_VERSION@"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+/**
+ * \brief The %KDE Multimedia classes
+ *
+ * In this Namespace you find the classes to access Multimedia functions for
+ * audio and video playback. Those classes are not dependent
+ * on any specific framework (like they were in pre KDE4 times) but rather use
+ * exchangeable backends to do the work.
+ *
+ * If you want to write a new backend take a look at \ref phonon_backend_development_page.
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+namespace Phonon
+{
+ PHONON_EXPORT const char *phononVersion();
+
+ /**
+ * Enum to identify the media discs supported by MediaObject.
+ *
+ * \see MediaSource(Phonon::DiscType, const QString &deviceName)
+ */
+ enum DiscType {
+ /**
+ * No disc was selected. This is only useful as a return value from
+ * MediaSource::distType();
+ */
+ NoDisc = -1,
+ /**
+ * Identifies Audio CDs.
+ */
+ Cd = 0,
+ /**
+ * Identifies DVDs (not arbitrary data DVDs, only movie DVDs).
+ */
+ Dvd = 1,
+ /**
+ * Identifies Video CDs.
+ */
+ Vcd = 2
+ };
+
+ /**
+ * Provided as keys for MediaObject::metaData for convenience, in addition to the strings defined in
+ * the Ogg Vorbis specification.
+ */
+ enum MetaData {
+ /**
+ * The artist generally considered responsible for the work. In popular
+ * music this is usually the performing band or singer. For classical
+ * music it would be the composer. For an audio book it would be the
+ * author of the original text.
+ */
+ ArtistMetaData,
+ /**
+ * The collection name to which this track belongs.
+ */
+ AlbumMetaData,
+ /**
+ * Track/Work name
+ */
+ TitleMetaData,
+ /**
+ * Date the track was recorded
+ */
+ DateMetaData,
+ /**
+ * A short text indication of music genre
+ */
+ GenreMetaData,
+ /**
+ * The track number of this piece if part of a specific larger
+ * collection or album
+ */
+ TracknumberMetaData,
+ /**
+ * A short text description of the contents
+ */
+ DescriptionMetaData,
+ MusicBrainzDiscIdMetaData
+ };
+
+ /**
+ * The state the media producing object is in at the moment.
+ *
+ * \see MediaObject
+ */
+ enum State
+ {
+ /**
+ * After construction it might take a while before the Player is
+ * ready to play(). Normally this doesn't happen for local
+ * files, but can happen for remote files where the asynchronous
+ * mimetype detection and prebuffering can take a while.
+ */
+ LoadingState,
+ /**
+ * The Player has a valid media file loaded and is ready for
+ * playing.
+ */
+ StoppedState,
+ /**
+ * The Player is playing a media file.
+ */
+ PlayingState,
+ /**
+ * The Player is waiting for data to be able to continue
+ * playing.
+ */
+ BufferingState,
+ /**
+ * The Player is currently paused.
+ */
+ PausedState,
+ /**
+ * An unrecoverable error occurred. The Object is unusable in this state.
+ */
+ ErrorState
+ };
+
+ /**
+ * Set's the category your program should be listed in in the mixer.
+ *
+ * A Jukebox will set this to Music, a VoIP program to Communication, a
+ * DVD player to video, and so on.
+ *
+ * \note These categories can also become useful for an application that
+ * controls the volumes automatically, like turning down the music when a call
+ * comes in, or turning down the notifications when the media player knows
+ * it's playing classical music.
+ *
+ * \see AudioOutput::setCategory
+ */
+ enum Category
+ {
+ /**
+ * Will make use of the default device.
+ */
+ NoCategory = -1,
+ /**
+ * If the sounds produced are notifications (bing, beep and such) you
+ * should use this category.
+ */
+ NotificationCategory = 0,
+ /**
+ * If your application is a music player (like a jukebox or media player
+ * playing an audio file).
+ */
+ MusicCategory = 1,
+ /**
+ * If the sound is the audio channel of a video.
+ */
+ VideoCategory = 2,
+ /**
+ * If your applications produces sounds from communication with somebody
+ * else (VoIP, voice chat).
+ */
+ CommunicationCategory = 3,
+ /**
+ * Sound produced by a computer game should go into this category.
+ */
+ GameCategory = 4,
+ /**
+ * Sounds produced for accessibility (e.g. Text-To-Speech)
+ */
+ AccessibilityCategory = 5,
+ /**
+ * \internal
+ * Holds the largest value of categories.
+ */
+ LastCategory = AccessibilityCategory
+ };
+
+ /**
+ * Tells your program how to recover from an error.
+ *
+ * \see MediaObject::errorType()
+ */
+ enum ErrorType {
+ /**
+ * No error. MediaObject::errorType() returns this if
+ * MediaObject::state() != Phonon::ErrorState.
+ */
+ NoError = 0,
+ /**
+ * Playback should work, and trying with another URL should work.
+ */
+ NormalError = 1,
+ /**
+ * Something important does not work. Your program cannot continue
+ * playback or capture or whatever it was trying to do
+ * without help from the user.
+ */
+ FatalError = 2
+ };
+
+ /**
+ * Returns a (translated) string to show to the user identifying the given
+ * Category.
+ */
+ PHONON_EXPORT QString categoryToString(Category c);
+
+ // TODO: naming
+ /*enum MediaStreamType {
+ Audio = 1,
+ Video = 2,
+ StillImage = 4,
+ Subtitle = 8,
+ AllMedia = 0xFFFFFFFF
+ };
+ Q_DECLARE_FLAGS(MediaStreamTypes, MediaStreamType)*/
+} // namespace Phonon
+//Q_DECLARE_OPERATORS_FOR_FLAGS(Phonon::MediaStreamTypes)
+
+QT_END_NAMESPACE
+
+//X class kdbgstream;
+//X #include <kdebug.h>
+//X /**
+//X * Implements needed operator to use Phonon::State with kDebug
+//X */
+//X inline PHONON_EXPORT kdbgstream &operator<<(kdbgstream & stream, const Phonon::State state)
+//X {
+//X switch(state)
+//X {
+//X case Phonon::ErrorState:
+//X stream << "ErrorState";
+//X break;
+//X case Phonon::LoadingState:
+//X stream << "LoadingState";
+//X break;
+//X case Phonon::StoppedState:
+//X stream << "StoppedState";
+//X break;
+//X case Phonon::PlayingState:
+//X stream << "PlayingState";
+//X break;
+//X case Phonon::BufferingState:
+//X stream << "BufferingState";
+//X break;
+//X case Phonon::PausedState:
+//X stream << "PausedState";
+//X break;
+//X }
+//X return stream;
+//X }
+
+#include <QtCore/QMetaType>
+
+Q_DECLARE_METATYPE(Phonon::State)
+Q_DECLARE_METATYPE(Phonon::ErrorType)
+Q_DECLARE_METATYPE(Phonon::Category)
+
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // PHONONNAMESPACE_H
diff --git a/src/3rdparty/phonon/phonon/phononnamespace_p.h b/src/3rdparty/phonon/phonon/phononnamespace_p.h
new file mode 100644
index 0000000..2fa520a
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/phononnamespace_p.h
@@ -0,0 +1,38 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONONNAMESPACE_P_H
+#define PHONONNAMESPACE_P_H
+
+#include <QtCore/QDebug>
+
+#if defined(QT_NO_DEBUG)
+#define pDebug if (true) {} else qDebug
+#else
+#define pDebug if (qgetenv("PHONON_DEBUG").isEmpty()) {} else qDebug
+#endif
+#define pWarning() qDebug() << "WARNING:"
+#define pError() qDebug() << "ERROR:"
+#define pFatal(message) qDebug() << "FATAL ERROR:" << message; ::abort()
+
+// vim: sw=4 ts=4 tw=80
+#endif // PHONONNAMESPACE_P_H
diff --git a/src/3rdparty/phonon/phonon/platform.cpp b/src/3rdparty/phonon/phonon/platform.cpp
new file mode 100644
index 0000000..49c4561
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/platform.cpp
@@ -0,0 +1,144 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "platform_p.h"
+#include "platformplugin.h"
+#include "factory_p.h"
+#include <QtCore/QCoreApplication>
+#include <QtCore/QUrl>
+#include <QtGui/QIcon>
+#include <QtGui/QStyle>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+void Platform::saveVolume(const QString &outputName, qreal volume)
+{
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ PlatformPlugin *f = Factory::platformPlugin();
+ if (f) {
+ f->saveVolume(outputName, volume);
+ }
+#else
+ Q_UNUSED(outputName);
+ Q_UNUSED(volume);
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+}
+
+qreal Platform::loadVolume(const QString &outputName)
+{
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ const PlatformPlugin *f = Factory::platformPlugin();
+ if (f) {
+ return f->loadVolume(outputName);
+ }
+#else
+ Q_UNUSED(outputName);
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ return 1.0;
+}
+
+AbstractMediaStream *Platform::createMediaStream(const QUrl &url, QObject *parent)
+{
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ PlatformPlugin *f = Factory::platformPlugin();
+ if (f) {
+ return f->createMediaStream(url, parent);
+ }
+#else
+ Q_UNUSED(url);
+ Q_UNUSED(parent);
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ return 0;
+}
+
+QIcon Platform::icon(const QString &name, QStyle *style)
+{
+ QIcon ret;
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ if (const PlatformPlugin *f = Factory::platformPlugin()) {
+ ret = f->icon(name);
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ if (ret.isNull()) {
+ if (!style) {
+ style = QApplication::style();
+ }
+ if (name == QLatin1String("player-volume")) {
+ ret = style->standardPixmap(QStyle::SP_MediaVolume);
+ } else if (name == QLatin1String("player-volume-muted")) {
+ ret = style->standardPixmap(QStyle::SP_MediaVolumeMuted);
+ }
+ }
+
+ return ret;
+}
+
+void Platform::notification(const char *notificationName, const QString &text,
+ const QStringList &actions, QObject *receiver,
+ const char *actionSlot)
+{
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ const PlatformPlugin *f = Factory::platformPlugin();
+ if (f) {
+ f->notification(notificationName, text, actions, receiver, actionSlot);
+ }
+#else
+ Q_UNUSED(notificationName);
+ Q_UNUSED(text);
+ Q_UNUSED(actions);
+ Q_UNUSED(receiver);
+ Q_UNUSED(actionSlot);
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+}
+
+QString Platform::applicationName()
+{
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ const PlatformPlugin *f = Factory::platformPlugin();
+ if (f) {
+ return f->applicationName();
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ QString ret = QCoreApplication::applicationName();
+ if (ret.isEmpty())
+ ret = QCoreApplication::applicationFilePath();
+ return ret;
+}
+
+QList<QPair<QByteArray, QString> > Platform::deviceAccessListFor(const Phonon::AudioOutputDevice &deviceDesc)
+{
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ const PlatformPlugin *f = Factory::platformPlugin();
+ if (f) {
+ return f->deviceAccessListFor(deviceDesc);
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ return QList<QPair<QByteArray, QString> >();
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/phonon/platform_p.h b/src/3rdparty/phonon/phonon/platform_p.h
new file mode 100644
index 0000000..c4edb2f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/platform_p.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_PLATFORM_P_H
+#define PHONON_PLATFORM_P_H
+
+
+#include <QtCore/QStringList>
+#include <QtCore/QtGlobal>
+#include <QtCore/QPair>
+#include "phonon_export.h"
+#include "objectdescription.h"
+
+QT_BEGIN_NAMESPACE
+
+class QIcon;
+class QObject;
+class QUrl;
+class QStyle;
+
+namespace Phonon
+{
+class AbstractMediaStream;
+
+namespace Platform
+{
+
+void saveVolume(const QString &outputName, qreal volume);
+qreal loadVolume(const QString &outputName);
+AbstractMediaStream *createMediaStream(const QUrl &url, QObject *parent);
+QIcon icon(const QString &name, QStyle *style = 0);
+void notification(const char *notificationName, const QString &text,
+ const QStringList &actions = QStringList(), QObject *receiver = 0,
+ const char *actionSlot = 0);
+QString applicationName();
+QList<QPair<QByteArray, QString> > deviceAccessListFor(const Phonon::AudioOutputDevice &deviceDesc);
+
+} // namespace Platform
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#endif // PHONON_PLATFORM_P_H
diff --git a/src/3rdparty/phonon/phonon/platformplugin.h b/src/3rdparty/phonon/phonon/platformplugin.h
new file mode 100644
index 0000000..c75bc96
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/platformplugin.h
@@ -0,0 +1,118 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007-2008 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_PLATFORMPLUGIN_H
+#define PHONON_PLATFORMPLUGIN_H
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QPair>
+#include "phonon_export.h"
+#include "objectdescription.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+
+class QUrl;
+class QObject;
+class QIcon;
+
+namespace Phonon
+{
+class AbstractMediaStream;
+
+class PlatformPlugin
+{
+ public:
+ virtual ~PlatformPlugin() {}
+
+ /**
+ * Creates a AbstractMediaStream object that provides the data for the given \p url. On KDE
+ * this uses KIO.
+ */
+ virtual AbstractMediaStream *createMediaStream(const QUrl &url, QObject *parent) = 0;
+
+ /**
+ * Returns the icon for the given icon name.
+ */
+ virtual QIcon icon(const QString &name) const = 0;
+
+ /**
+ * Shows a notification popup
+ */
+ virtual void notification(const char *notificationName, const QString &text,
+ const QStringList &actions = QStringList(), QObject *receiver = 0,
+ const char *actionSlot = 0) const = 0;
+
+ /**
+ * Returns the name of the application. For most Qt application this is
+ * QCoreApplication::applicationName(), but for KDE this is overridden by KAboutData.
+ */
+ virtual QString applicationName() const = 0;
+
+ /**
+ * Creates a backend object. This way the platform can decide the backend preference.
+ */
+ virtual QObject *createBackend() = 0;
+
+ /**
+ * Using the library loader of the platform, loads a given backend.
+ */
+ virtual QObject *createBackend(const QString &library, const QString &version) = 0;
+
+ /**
+ * Tries to check whether the default backend supports a given MIME type without loading the
+ * actual backend library. On KDE this reads the MIME type list from the .desktop file of
+ * the backend.
+ */
+ virtual bool isMimeTypeAvailable(const QString &mimeType) const = 0;
+
+ /**
+ * Saves the volume for the given output.
+ */
+ virtual void saveVolume(const QString &outputName, qreal volume) = 0;
+
+ /**
+ * Loads the volume for the given output.
+ */
+ virtual qreal loadVolume(const QString &outputName) const = 0;
+
+ virtual QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const = 0;
+ virtual QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const = 0;
+
+ /**
+ * Returns a list of (driver, handle) pairs for the given AudioOutputDevice description.
+ */
+ virtual QList<QPair<QByteArray, QString> > deviceAccessListFor(const Phonon::AudioOutputDevice &) const { return QList<QPair<QByteArray, QString> >(); }
+};
+} // namespace Phonon
+
+Q_DECLARE_INTERFACE(Phonon::PlatformPlugin, "3PlatformPlugin.phonon.kde.org")
+
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_PLATFORMPLUGIN_H
diff --git a/src/3rdparty/phonon/phonon/preprocessandextract.sh b/src/3rdparty/phonon/phonon/preprocessandextract.sh
new file mode 100755
index 0000000..13b1704
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/preprocessandextract.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+EXTRACT="`dirname $0`/extractmethodcalls.rb"
+IGNORE="^\(streameventqueue\|abstractmediastream2\|lockfreequeue\|path\|platform\|iodevicestream\|medianode\|streaminterface\|mediasource\|abstractmediastream\|audioplayer\|globalconfig\|objectdescriptionmodel\|audiooutputadaptor\|effectwidget\|videoplayer\|seekslider\|volumeslider\).cpp$"
+
+if test -n "$1" -a -f "$1"; then
+ echo "preprocessing $1"
+ cpp $1 2>/dev/null > tmp
+ echo "extracting backend calls from $1"
+ $EXTRACT tmp > tests/methods/$1
+ rm tmp
+else
+ for i in *.cpp; do
+ if echo $i | grep -q "$IGNORE"; then
+ printf "%-30s ignored.\n" "$i:"
+ elif echo $i | grep -q '_p\.cpp$'; then
+ printf "%-30s postponed.\n" "$i:"
+ else
+ printf "%-30s preprocessing" "$i:"
+ cpp $i 2>/dev/null > tmp
+ echo -n ", extracting backend calls"
+ $EXTRACT tmp > tests/methods/$i
+ rm tmp
+ echo "."
+ fi
+ done
+ for i in *_p.cpp; do
+ cpp=`echo $i | sed 's,_p\.cpp$,\.cpp,'`
+ if echo $cpp | grep -q "$IGNORE"; then
+ printf "%-30s ignored.\n" "$i:"
+ elif test "$i" != "*_p.cpp"; then
+ printf "%-30s preprocessing" "$i:"
+ cpp $i 2>/dev/null > tmp
+ echo -n ", extracting backend calls"
+ $EXTRACT tmp >> tests/methods/$cpp
+ rm tmp
+ echo "."
+ fi
+ done
+fi
diff --git a/src/3rdparty/phonon/phonon/pulsesupport.cpp b/src/3rdparty/phonon/phonon/pulsesupport.cpp
new file mode 100644
index 0000000..b1ba196
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/pulsesupport.cpp
@@ -0,0 +1,1038 @@
+/* This file is part of the KDE project
+ Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/QEventLoop>
+#include <QtCore/QDebug>
+#include <QtCore/QStringList>
+
+#ifdef HAVE_PULSEAUDIO
+#include <glib.h>
+#include <pulse/pulseaudio.h>
+#include <pulse/xmalloc.h>
+#include <pulse/glib-mainloop.h>
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+# include <pulse/ext-device-manager.h>
+#endif
+#endif // HAVE_PULSEAUDIO
+
+#include "pulsesupport.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+static PulseSupport* s_instance = NULL;
+
+#ifdef HAVE_PULSEAUDIO
+/***
+* Prints a conditional debug message based on the current debug level
+* If obj is provided, classname and objectname will be printed as well
+*
+* see debugLevel()
+*/
+
+static int debugLevel() {
+ static int level = -1;
+ if (level < 1) {
+ level = 0;
+ QByteArray pulseenv = qgetenv("PHONON_PULSEAUDIO_DEBUG");
+ int l = pulseenv.toInt();
+ if (l > 0)
+ level = (l > 2 ? 2 : l);
+ }
+ return level;
+}
+
+static void logMessage(const QString &message, int priority = 2, QObject *obj=0);
+static void logMessage(const QString &message, int priority, QObject *obj)
+{
+ if (debugLevel() > 0) {
+ QString output;
+ if (obj) {
+ // Strip away namespace from className
+ QByteArray className(obj->metaObject()->className());
+ int nameLength = className.length() - className.lastIndexOf(':') - 1;
+ className = className.right(nameLength);
+ output.sprintf("%s %s (%s %p)", message.toLatin1().constData(),
+ obj->objectName().toLatin1().constData(),
+ className.constData(), obj);
+ }
+ else {
+ output = message;
+ }
+ if (priority <= debugLevel()) {
+ qDebug() << QString::fromLatin1("PulseSupport(%1): %2").arg(priority).arg(output);
+ }
+ }
+}
+
+
+class AudioDevice
+{
+ public:
+ inline
+ AudioDevice(QString name, QString desc, QString icon, uint32_t index)
+ : pulseName(name), pulseIndex(index)
+ {
+ properties["name"] = desc;
+ properties["description"] = QLatin1String(""); // We don't have descriptions (well we do, but we use them as the name!)
+ properties["icon"] = icon;
+ properties["available"] = (index != PA_INVALID_INDEX);
+ properties["isAdvanced"] = false; // Nothing is advanced!
+ }
+
+ // Needed for QMap
+ inline AudioDevice() {}
+
+ QString pulseName;
+ uint32_t pulseIndex;
+ QHash<QByteArray, QVariant> properties;
+};
+bool operator!=(const AudioDevice &a, const AudioDevice &b)
+{
+ return !(a.pulseName == b.pulseName && a.properties == b.properties);
+}
+
+class PulseUserData
+{
+ public:
+ inline
+ PulseUserData()
+ {
+ }
+
+ QMap<QString, AudioDevice> newOutputDevices;
+ QMap<Phonon::Category, QMap<int, int> > newOutputDevicePriorities; // prio, device
+
+ QMap<QString, AudioDevice> newCaptureDevices;
+ QMap<Phonon::Category, QMap<int, int> > newCaptureDevicePriorities; // prio, device
+};
+
+static QMap<QString, Phonon::Category> s_roleCategoryMap;
+
+static bool s_pulseActive = false;
+
+static pa_glib_mainloop *s_mainloop = NULL;
+static pa_context *s_context = NULL;
+
+
+
+static int s_deviceIndexCounter = 0;
+
+static QMap<QString, int> s_outputDeviceIndexes;
+static QMap<int, AudioDevice> s_outputDevices;
+static QMap<Phonon::Category, QMap<int, int> > s_outputDevicePriorities; // prio, device
+static QMap<QString, uint32_t> s_outputStreamIndexMap;
+
+static QMap<QString, int> s_captureDeviceIndexes;
+static QMap<int, AudioDevice> s_captureDevices;
+static QMap<Phonon::Category, QMap<int, int> > s_captureDevicePriorities; // prio, device
+static QMap<QString, uint32_t> s_captureStreamIndexMap;
+
+static void createGenericDevices()
+{
+ // OK so we don't have the device manager extension, but we can show a single device and fake it.
+ int index;
+ s_outputDeviceIndexes.clear();
+ s_outputDevices.clear();
+ s_outputDevicePriorities.clear();
+ index = s_deviceIndexCounter++;
+ s_outputDeviceIndexes.insert(QLatin1String("sink:default"), index);
+ s_outputDevices.insert(index, AudioDevice(QLatin1String("sink:default"), QObject::tr("PulseAudio Sound Server"), QLatin1String("audio-backend-pulseaudio"), 0));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ s_outputDevicePriorities[cat].insert(0, index);
+ }
+
+ s_captureDeviceIndexes.clear();
+ s_captureDevices.clear();
+ s_captureDevicePriorities.clear();
+ index = s_deviceIndexCounter++;
+ s_captureDeviceIndexes.insert(QLatin1String("source:default"), index);
+ s_captureDevices.insert(index, AudioDevice(QLatin1String("source:default"), QObject::tr("PulseAudio Sound Server"), QLatin1String("audio-backend-pulseaudio"), 0));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ s_captureDevicePriorities[cat].insert(0, index);
+ }
+}
+
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manager_info *info, int eol, void *userdata) {
+ Q_ASSERT(c);
+ Q_ASSERT(userdata);
+
+ PulseUserData *u = reinterpret_cast<PulseUserData*>(userdata);
+
+ if (eol < 0) {
+ logMessage(QString("Failed to initialize device manager extension: %1").arg(pa_strerror(pa_context_errno(c))));
+ logMessage("Falling back to single device mode");
+ createGenericDevices();
+ delete u;
+
+ // If this is our probe phase, exit now
+ if (s_context != c)
+ pa_context_disconnect(c);
+
+ return;
+ }
+
+ if (eol) {
+ // We're done reading the data, so order it by priority and copy it into the
+ // static variables where it can then be accessed by those classes that need it.
+
+ QMap<QString, AudioDevice>::iterator newdev_it;
+
+ // Check for new output devices or things changing about known output devices.
+ bool output_changed = false;
+ for (newdev_it = u->newOutputDevices.begin(); newdev_it != u->newOutputDevices.end(); ++newdev_it) {
+ QString name = newdev_it.key();
+
+ // The name + index map is always written when a new device is added.
+ Q_ASSERT(s_outputDeviceIndexes.contains(name));
+
+ int index = s_outputDeviceIndexes[name];
+ if (!s_outputDevices.contains(index)) {
+ // This is a totally new device
+ output_changed = true;
+ logMessage(QString("Brand New Output Device Found."));
+ s_outputDevices.insert(index, *newdev_it);
+ } else if (s_outputDevices[index] != *newdev_it) {
+ // We have this device already, but is it different?
+ output_changed = true;
+ logMessage(QString("Change to Existing Output Device (may be Added/Removed or something else)"));
+ s_outputDevices.remove(index);
+ s_outputDevices.insert(index, *newdev_it);
+ }
+ }
+ // Go through the output devices we know about and see if any are no longer mentioned in the list.
+ QMutableMapIterator<QString, int> output_existing_it(s_outputDeviceIndexes);
+ while (output_existing_it.hasNext()) {
+ output_existing_it.next();
+ if (!u->newOutputDevices.contains(output_existing_it.key())) {
+ output_changed = true;
+ logMessage(QString("Output Device Completely Removed"));
+ s_outputDevices.remove(output_existing_it.value());
+ output_existing_it.remove();
+ }
+ }
+
+ // Check for new capture devices or things changing about known capture devices.
+ bool capture_changed = false;
+ for (newdev_it = u->newCaptureDevices.begin(); newdev_it != u->newCaptureDevices.end(); ++newdev_it) {
+ QString name = newdev_it.key();
+
+ // The name + index map is always written when a new device is added.
+ Q_ASSERT(s_captureDeviceIndexes.contains(name));
+
+ int index = s_captureDeviceIndexes[name];
+ if (!s_captureDevices.contains(index)) {
+ // This is a totally new device
+ capture_changed = true;
+ logMessage(QString("Brand New Capture Device Found."));
+ s_captureDevices.insert(index, *newdev_it);
+ } else if (s_captureDevices[index] != *newdev_it) {
+ // We have this device already, but is it different?
+ capture_changed = true;
+ logMessage(QString("Change to Existing Capture Device (may be Added/Removed or something else)"));
+ s_captureDevices.remove(index);
+ s_captureDevices.insert(index, *newdev_it);
+ }
+ }
+ // Go through the capture devices we know about and see if any are no longer mentioned in the list.
+ QMutableMapIterator<QString, int> capture_existing_it(s_captureDeviceIndexes);
+ while (capture_existing_it.hasNext()) {
+ capture_existing_it.next();
+ if (!u->newCaptureDevices.contains(capture_existing_it.key())) {
+ capture_changed = true;
+ logMessage(QString("Capture Device Completely Removed"));
+ s_captureDevices.remove(capture_existing_it.value());
+ capture_existing_it.remove();
+ }
+ }
+
+ // Just copy accross the new priority lists as we know they are valid
+ if (s_outputDevicePriorities != u->newOutputDevicePriorities) {
+ output_changed = true;
+ s_outputDevicePriorities = u->newOutputDevicePriorities;
+ }
+ if (s_captureDevicePriorities != u->newCaptureDevicePriorities) {
+ capture_changed = true;
+ s_captureDevicePriorities = u->newCaptureDevicePriorities;
+ }
+
+ if (s_instance) {
+ // This wont be emitted durring the connection probe phase
+ // which is intensional
+ if (output_changed)
+ s_instance->emitObjectDescriptionChanged(AudioOutputDeviceType);
+ if (capture_changed)
+ s_instance->emitObjectDescriptionChanged(AudioCaptureDeviceType);
+ }
+
+ // We can free the user data as we will not be called again.
+ delete u;
+
+ // Some debug
+ logMessage(QString("Output Device Priority List:"));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ if (s_outputDevicePriorities.contains(cat)) {
+ logMessage(QString(" Phonon Category %1").arg(cat));
+ int count = 0;
+ foreach (int j, s_outputDevicePriorities[cat]) {
+ QHash<QByteArray, QVariant> &props = s_outputDevices[j].properties;
+ logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool()));
+ }
+ }
+ }
+ logMessage(QString("Capture Device Priority List:"));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ if (s_captureDevicePriorities.contains(cat)) {
+ logMessage(QString(" Phonon Category %1").arg(cat));
+ int count = 0;
+ foreach (int j, s_captureDevicePriorities[cat]) {
+ QHash<QByteArray, QVariant> &props = s_captureDevices[j].properties;
+ logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool()));
+ }
+ }
+ }
+
+ // If this is our probe phase, exit now as we're finished reading
+ // our device info and can exit and reconnect
+ if (s_context != c)
+ pa_context_disconnect(c);
+ }
+
+ if (!info)
+ return;
+
+ Q_ASSERT(info->name);
+ Q_ASSERT(info->description);
+ Q_ASSERT(info->icon);
+
+ // QString wrapper
+ QString name(info->name);
+ int index;
+ QMap<Phonon::Category, QMap<int, int> > *new_prio_map_cats; // prio, device
+ QMap<QString, AudioDevice> *new_devices;
+
+ if (name.startsWith("sink:")) {
+ new_devices = &u->newOutputDevices;
+ new_prio_map_cats = &u->newOutputDevicePriorities;
+
+ if (s_outputDeviceIndexes.contains(name))
+ index = s_outputDeviceIndexes[name];
+ else
+ index = s_outputDeviceIndexes[name] = s_deviceIndexCounter++;
+ } else if (name.startsWith("source:")) {
+ new_devices = &u->newCaptureDevices;
+ new_prio_map_cats = &u->newCaptureDevicePriorities;
+
+ if (s_captureDeviceIndexes.contains(name))
+ index = s_captureDeviceIndexes[name];
+ else
+ index = s_captureDeviceIndexes[name] = s_deviceIndexCounter++;
+ } else {
+ // This indicates a bug in pulseaudio.
+ return;
+ }
+
+ // Add the new device itself.
+ new_devices->insert(name, AudioDevice(name, info->description, info->icon, info->index));
+
+ // For each role in the priority, map it to a phonon category and store the order.
+ for (uint32_t i = 0; i < info->n_role_priorities; ++i) {
+ pa_ext_device_manager_role_priority_info* role_prio = &info->role_priorities[i];
+ Q_ASSERT(role_prio->role);
+
+ if (s_roleCategoryMap.contains(role_prio->role)) {
+ Phonon::Category cat = s_roleCategoryMap[role_prio->role];
+
+ (*new_prio_map_cats)[cat].insert(role_prio->priority, index);
+ }
+ }
+}
+
+static void ext_device_manager_subscribe_cb(pa_context *c, void *) {
+ Q_ASSERT(c);
+
+ pa_operation *o;
+ PulseUserData *u = new PulseUserData;
+ if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) {
+ logMessage(QString("pa_ext_device_manager_read() failed."));
+ delete u;
+ return;
+ }
+ pa_operation_unref(o);
+}
+#endif
+
+void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) {
+ Q_UNUSED(userdata);
+ Q_ASSERT(c);
+
+ if (eol < 0) {
+ if (pa_context_errno(c) == PA_ERR_NOENTITY)
+ return;
+
+ logMessage(QLatin1String("Sink input callback failure"));
+ return;
+ }
+
+ if (eol > 0)
+ return;
+
+ Q_ASSERT(i);
+
+ // loop through (*i) and extract phonon->streamindex...
+ const char *t;
+ if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) {
+ logMessage(QString::fromLatin1("Found PulseAudio stream index %1 for Phonon Output Stream %2").arg(i->index).arg(QLatin1String(t)));
+ s_outputStreamIndexMap[QLatin1String(t)] = i->index;
+
+ // Find the sink's phonon index and notify whoever cares...
+ if (PA_INVALID_INDEX != i->sink) {
+ bool found = false;
+ int device;
+ QMap<int, AudioDevice>::iterator it;
+ for (it = s_outputDevices.begin(); it != s_outputDevices.end(); ++it) {
+ if ((*it).pulseIndex == i->sink) {
+ found = true;
+ device = it.key();
+ break;
+ }
+ }
+ if (found) {
+ // OK so we just emit our signal
+ logMessage(QLatin1String("Letting the rest of phonon know about this"));
+ s_instance->emitUsingDevice(QLatin1String(t), device);
+ }
+ }
+ }
+}
+
+void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, void *userdata) {
+ Q_UNUSED(userdata);
+ Q_ASSERT(c);
+
+ if (eol < 0) {
+ if (pa_context_errno(c) == PA_ERR_NOENTITY)
+ return;
+
+ logMessage(QLatin1String("Source output callback failure"));
+ return;
+ }
+
+ if (eol > 0)
+ return;
+
+ Q_ASSERT(i);
+
+ // loop through (*i) and extract phonon->streamindex...
+ const char *t;
+ if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) {
+ logMessage(QString::fromLatin1("Found PulseAudio stream index %1 for Phonon Capture Stream %2").arg(i->index).arg(QLatin1String(t)));
+ s_captureStreamIndexMap[QLatin1String(t)] = i->index;
+
+ // Find the source's phonon index and notify whoever cares...
+ if (PA_INVALID_INDEX != i->source) {
+ bool found = false;
+ int device;
+ QMap<int, AudioDevice>::iterator it;
+ for (it = s_captureDevices.begin(); it != s_captureDevices.end(); ++it) {
+ if ((*it).pulseIndex == i->source) {
+ found = true;
+ device = it.key();
+ break;
+ }
+ }
+ if (found) {
+ // OK so we just emit our signal
+ logMessage(QLatin1String("Letting the rest of phonon know about this"));
+ s_instance->emitUsingDevice(QLatin1String(t), device);
+ }
+ }
+ }
+}
+
+static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) {
+ Q_UNUSED(userdata);
+
+ switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
+ case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ QString phononid = s_outputStreamIndexMap.key(index);
+ if (!phononid.isEmpty()) {
+ if (s_outputStreamIndexMap.contains(phononid)) {
+ logMessage(QString::fromLatin1("Phonon Output Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid));
+ s_outputStreamIndexMap[phononid] = PA_INVALID_INDEX;
+ } else {
+ logMessage(QString::fromLatin1("Removing Phonon Output Stream %1 (it's gone!)").arg(phononid));
+ s_outputStreamIndexMap.remove(phononid);
+ }
+ }
+ } else {
+ pa_operation *o;
+ if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, NULL))) {
+ logMessage(QLatin1String("pa_context_get_sink_input_info() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ QString phononid = s_captureStreamIndexMap.key(index);
+ if (!phononid.isEmpty()) {
+ if (s_captureStreamIndexMap.contains(phononid)) {
+ logMessage(QString::fromLatin1("Phonon Capture Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid));
+ s_captureStreamIndexMap[phononid] = PA_INVALID_INDEX;
+ } else {
+ logMessage(QString::fromLatin1("Removing Phonon Capture Stream %1 (it's gone!)").arg(phononid));
+ s_captureStreamIndexMap.remove(phononid);
+ }
+ }
+ } else {
+ pa_operation *o;
+ if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, NULL))) {
+ logMessage(QLatin1String("pa_context_get_sink_input_info() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+ break;
+ }
+}
+
+
+static QString statename(pa_context_state_t state)
+{
+ switch (state)
+ {
+ case PA_CONTEXT_UNCONNECTED: return QLatin1String("Unconnected");
+ case PA_CONTEXT_CONNECTING: return QLatin1String("Connecting");
+ case PA_CONTEXT_AUTHORIZING: return QLatin1String("Authorizing");
+ case PA_CONTEXT_SETTING_NAME: return QLatin1String("Setting Name");
+ case PA_CONTEXT_READY: return QLatin1String("Ready");
+ case PA_CONTEXT_FAILED: return QLatin1String("Failed");
+ case PA_CONTEXT_TERMINATED: return QLatin1String("Terminated");
+ }
+
+ return QString::fromLatin1("Unknown state: %0").arg(state);
+}
+
+static void context_state_callback(pa_context *c, void *)
+{
+ Q_ASSERT(c);
+
+ logMessage(QString::fromLatin1("context_state_callback %1").arg(statename(pa_context_get_state(c))));
+ pa_context_state_t state = pa_context_get_state(c);
+ if (state == PA_CONTEXT_READY) {
+ // We've connected to PA, so it is active
+ s_pulseActive = true;
+
+ // Attempt to load things up
+ pa_operation *o;
+
+ // 1. Register for the stream changes (except during probe)
+ if (s_context == c) {
+ pa_context_set_subscribe_callback(c, subscribe_cb, NULL);
+
+ if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
+ (PA_SUBSCRIPTION_MASK_SINK_INPUT|
+ PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) {
+ logMessage(QLatin1String("pa_context_subscribe() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+ // 2a. Attempt to initialise Device Manager info (except during probe)
+ if (s_context == c) {
+ pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, NULL);
+ if (!(o = pa_ext_device_manager_subscribe(c, 1, NULL, NULL))) {
+ logMessage(QString("pa_ext_device_manager_subscribe() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+
+ // 3. Attempt to read info from Device Manager
+ PulseUserData *u = new PulseUserData;
+ if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) {
+ logMessage(QString("pa_ext_device_manager_read() failed. Attempting to continue without device manager support"));
+ createGenericDevices();
+ delete u;
+
+ // If this is our probe phase, exit immediately
+ if (s_context != c)
+ pa_context_disconnect(c);
+
+ return;
+ }
+ pa_operation_unref(o);
+
+#else
+ // If we know do not have Device Manager support, we just create our dummy devices now
+ createGenericDevices();
+
+ // If this is our probe phase, exit immediately
+ if (s_context != c)
+ pa_context_disconnect(c);
+#endif
+ } else if (!PA_CONTEXT_IS_GOOD(state)) {
+ /// @todo Deal with reconnection...
+ //logMessage("Connection to PulseAudio lost");
+
+ // If this is our probe phase, exit our context immediately
+ if (s_context != c)
+ pa_context_disconnect(c);
+ }
+}
+#endif // HAVE_PULSEAUDIO
+
+
+PulseSupport* PulseSupport::getInstance()
+{
+ if (NULL == s_instance) {
+ s_instance = new PulseSupport();
+ }
+ return s_instance;
+}
+
+void PulseSupport::shutdown()
+{
+ if (NULL != s_instance) {
+ delete s_instance;
+ s_instance = NULL;
+ }
+}
+
+PulseSupport::PulseSupport()
+ : QObject(), mEnabled(false)
+{
+#ifdef HAVE_PULSEAUDIO
+ // Initialise our map (is there a better way to do this?)
+ s_roleCategoryMap[QLatin1String("none")] = Phonon::NoCategory;
+ s_roleCategoryMap[QLatin1String("video")] = Phonon::VideoCategory;
+ s_roleCategoryMap[QLatin1String("music")] = Phonon::MusicCategory;
+ s_roleCategoryMap[QLatin1String("game")] = Phonon::GameCategory;
+ s_roleCategoryMap[QLatin1String("event")] = Phonon::NotificationCategory;
+ s_roleCategoryMap[QLatin1String("phone")] = Phonon::CommunicationCategory;
+ //s_roleCategoryMap[QLatin1String("animation")]; // No Mapping
+ //s_roleCategoryMap[QLatin1String("production")]; // No Mapping
+ s_roleCategoryMap[QLatin1String("a11y")] = Phonon::AccessibilityCategory;
+
+ // To allow for easy debugging, give an easy way to disable this pulseaudio check
+ QByteArray pulseenv = qgetenv("PHONON_PULSEAUDIO_DISABLE");
+ if (pulseenv.toInt()) {
+ logMessage(QLatin1String("PulseAudio support disabled: PHONON_PULSEAUDIO_DISABLE is set"));
+ return;
+ }
+
+ // We require a glib event loop
+ if (strcmp(QAbstractEventDispatcher::instance()->metaObject()->className(),
+ "QGuiEventDispatcherGlib") != 0) {
+ logMessage(QLatin1String("Disabling PulseAudio integration for lack of GLib event loop."));
+ return;
+ }
+
+ // First of all conenct to PA via simple/blocking means and if that succeeds,
+ // use a fully async integrated mainloop method to connect and get proper support.
+ pa_mainloop *p_test_mainloop;
+ if (!(p_test_mainloop = pa_mainloop_new())) {
+ logMessage(QLatin1String("PulseAudio support disabled: Unable to create mainloop"));
+ return;
+ }
+
+ pa_context *p_test_context;
+ if (!(p_test_context = pa_context_new(pa_mainloop_get_api(p_test_mainloop), "libphonon-probe"))) {
+ logMessage(QLatin1String("PulseAudio support disabled: Unable to create context"));
+ pa_mainloop_free(p_test_mainloop);
+ return;
+ }
+
+ logMessage(QLatin1String("Probing for PulseAudio..."));
+ // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required
+ if (pa_context_connect(p_test_context, NULL, static_cast<pa_context_flags_t>(0), NULL) < 0) {
+ logMessage(QString::fromLatin1("PulseAudio support disabled: %1").arg(QString::fromLocal8Bit(pa_strerror(pa_context_errno(p_test_context)))));
+ pa_context_disconnect(p_test_context);
+ pa_context_unref(p_test_context);
+ pa_mainloop_free(p_test_mainloop);
+ return;
+ }
+
+ pa_context_set_state_callback(p_test_context, &context_state_callback, NULL);
+ for (;;) {
+ pa_mainloop_iterate(p_test_mainloop, 1, NULL);
+
+ if (!PA_CONTEXT_IS_GOOD(pa_context_get_state(p_test_context))) {
+ logMessage(QLatin1String("PulseAudio probe complete."));
+ break;
+ }
+ }
+ pa_context_disconnect(p_test_context);
+ pa_context_unref(p_test_context);
+ pa_mainloop_free(p_test_mainloop);
+
+ if (!s_pulseActive) {
+ logMessage(QLatin1String("PulseAudio support is not available."));
+ return;
+ }
+
+ // If we're still here, PA is available.
+ logMessage(QLatin1String("PulseAudio support enabled"));
+
+ // Now we connect for real using a proper main loop that we can forget
+ // all about processing.
+ s_mainloop = pa_glib_mainloop_new(NULL);
+ Q_ASSERT(s_mainloop);
+ pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop);
+
+ s_context = pa_context_new(api, "libphonon");
+ // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required
+ if (pa_context_connect(s_context, NULL, static_cast<pa_context_flags_t>(0), 0) >= 0)
+ pa_context_set_state_callback(s_context, &context_state_callback, NULL);
+#endif
+}
+
+PulseSupport::~PulseSupport()
+{
+#ifdef HAVE_PULSEAUDIO
+ if (s_context) {
+ pa_context_disconnect(s_context);
+ s_context = NULL;
+ }
+
+ if (s_mainloop) {
+ pa_glib_mainloop_free(s_mainloop);
+ s_mainloop = NULL;
+ }
+#endif
+}
+
+bool PulseSupport::isActive()
+{
+#ifdef HAVE_PULSEAUDIO
+ return mEnabled && s_pulseActive;
+#else
+ return false;
+#endif
+}
+
+void PulseSupport::enable(bool enabled)
+{
+ mEnabled = enabled;
+}
+
+QList<int> PulseSupport::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+ QList<int> list;
+
+ if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType)
+ return list;
+
+#ifdef HAVE_PULSEAUDIO
+ if (s_pulseActive) {
+ switch (type) {
+
+ case AudioOutputDeviceType: {
+ QMap<QString, int>::iterator it;
+ for (it = s_outputDeviceIndexes.begin(); it != s_outputDeviceIndexes.end(); ++it) {
+ list.append(*it);
+ }
+ break;
+ }
+ case AudioCaptureDeviceType: {
+ QMap<QString, int>::iterator it;
+ for (it = s_captureDeviceIndexes.begin(); it != s_captureDeviceIndexes.end(); ++it) {
+ list.append(*it);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+#endif
+
+ return list;
+}
+
+QHash<QByteArray, QVariant> PulseSupport::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+ QHash<QByteArray, QVariant> ret;
+
+ if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType)
+ return ret;
+
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(index);
+#else
+ if (s_pulseActive) {
+ switch (type) {
+
+ case AudioOutputDeviceType:
+ Q_ASSERT(s_outputDevices.contains(index));
+ ret = s_outputDevices[index].properties;
+ break;
+
+ case AudioCaptureDeviceType:
+ Q_ASSERT(s_captureDevices.contains(index));
+ ret = s_captureDevices[index].properties;
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+QList<int> PulseSupport::objectIndexesByCategory(ObjectDescriptionType type, Category category) const
+{
+ QList<int> ret;
+
+ if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType)
+ return ret;
+
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+#else
+ if (s_pulseActive) {
+ switch (type) {
+
+ case AudioOutputDeviceType:
+ if (s_outputDevicePriorities.contains(category))
+ ret = s_outputDevicePriorities[category].values();
+ break;
+
+ case AudioCaptureDeviceType:
+ if (s_captureDevicePriorities.contains(category))
+ ret = s_captureDevicePriorities[category].values();
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+#ifdef HAVE_PULSEAUDIO
+static void setDevicePriority(Category category, QStringList list)
+{
+ QString role = s_roleCategoryMap.key(category);
+ if (role.isEmpty())
+ return;
+
+ logMessage(QString::fromLatin1("Reindexing %1: %2").arg(role).arg(list.join(QLatin1String(", "))));
+
+ char **devices;
+ devices = pa_xnew(char *, list.size()+1);
+ int i = 0;
+ foreach (QString str, list) {
+ devices[i++] = pa_xstrdup(str.toUtf8().constData());
+ }
+ devices[list.size()] = NULL;
+
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+ pa_operation *o;
+ if (!(o = pa_ext_device_manager_reorder_devices_for_role(s_context, role.toUtf8().constData(), (const char**)devices, NULL, NULL)))
+ logMessage(QString("pa_ext_device_manager_reorder_devices_for_role() failed"));
+ else
+ pa_operation_unref(o);
+#endif
+
+ for (i = 0; i < list.size(); ++i)
+ pa_xfree(devices[i]);
+ pa_xfree(devices);
+}
+#endif
+
+void PulseSupport::setOutputDevicePriorityForCategory(Category category, QList<int> order)
+{
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+ Q_UNUSED(order);
+#else
+ QStringList list;
+ QList<int>::iterator it;
+
+ for (it = order.begin(); it != order.end(); ++it) {
+ if (s_outputDevices.contains(*it)) {
+ list << s_outputDeviceIndexes.key(*it);
+ }
+ }
+ setDevicePriority(category, list);
+#endif
+}
+
+void PulseSupport::setCaptureDevicePriorityForCategory(Category category, QList<int> order)
+{
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+ Q_UNUSED(order);
+#else
+ QStringList list;
+ QList<int>::iterator it;
+
+ for (it = order.begin(); it != order.end(); ++it) {
+ if (s_captureDevices.contains(*it)) {
+ list << s_captureDeviceIndexes.key(*it);
+ }
+ }
+ setDevicePriority(category, list);
+#endif
+}
+
+void PulseSupport::setStreamPropList(Category category, QString streamUuid)
+{
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+ Q_UNUSED(streamUuid);
+#else
+ QString role = s_roleCategoryMap.key(category);
+ if (role.isEmpty())
+ return;
+
+ logMessage(QString::fromLatin1("Setting role to %1 for streamindex %2").arg(role).arg(streamUuid));
+ setenv("PULSE_PROP_media.role", role.toLatin1().constData(), 1);
+ setenv("PULSE_PROP_phonon.streamid", streamUuid.toLatin1().constData(), 1);
+#endif
+}
+
+void PulseSupport::emitObjectDescriptionChanged(ObjectDescriptionType type)
+{
+ emit objectDescriptionChanged(type);
+}
+
+void PulseSupport::emitUsingDevice(QString streamUuid, int device)
+{
+ emit usingDevice(streamUuid, device);
+}
+
+bool PulseSupport::setOutputDevice(QString streamUuid, int device) {
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(streamUuid);
+ Q_UNUSED(device);
+ return false;
+#else
+ if (s_outputDevices.size() < 2)
+ return true;
+
+ if (!s_outputDevices.contains(device)) {
+ logMessage(QString::fromLatin1("Attempting to set Output Device for invalid device id %1.").arg(device));
+ return false;
+ }
+ const QVariant var = s_outputDevices[device].properties["name"];
+ logMessage(QString::fromLatin1("Attempting to set Output Device to '%1' for Output Stream %2").arg(var.toString()).arg(streamUuid));
+
+ // Attempt to look up the pulse stream index.
+ if (s_outputStreamIndexMap.contains(streamUuid) && s_outputStreamIndexMap[streamUuid] != PA_INVALID_INDEX) {
+ logMessage(QLatin1String("... Found in map. Moving now"));
+
+ uint32_t pulse_device_index = s_outputDevices[device].pulseIndex;
+ uint32_t pulse_stream_index = s_outputStreamIndexMap[streamUuid];
+
+ logMessage(QString::fromLatin1("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index));
+
+ /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db.
+ pa_operation* o;
+ if (!(o = pa_context_move_sink_input_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) {
+ logMessage(QLatin1String("pa_context_move_sink_input_by_index() failed"));
+ return false;
+ }
+ pa_operation_unref(o);
+ } else {
+ logMessage(QLatin1String("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then"));
+ }
+ return true;
+#endif
+}
+
+bool PulseSupport::setCaptureDevice(QString streamUuid, int device) {
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(streamUuid);
+ Q_UNUSED(device);
+ return false;
+#else
+ if (s_captureDevices.size() < 2)
+ return true;
+
+ if (!s_captureDevices.contains(device)) {
+ logMessage(QString::fromLatin1("Attempting to set Capture Device for invalid device id %1.").arg(device));
+ return false;
+ }
+ const QVariant var = s_captureDevices[device].properties["name"];
+ logMessage(QString::fromLatin1("Attempting to set Capture Device to '%1' for Capture Stream %2").arg(var.toString()).arg(streamUuid));
+
+ // Attempt to look up the pulse stream index.
+ if (s_captureStreamIndexMap.contains(streamUuid) && s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) {
+ logMessage(QString::fromLatin1("... Found in map. Moving now"));
+
+ uint32_t pulse_device_index = s_captureDevices[device].pulseIndex;
+ uint32_t pulse_stream_index = s_captureStreamIndexMap[streamUuid];
+
+ logMessage(QString::fromLatin1("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index));
+
+ /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db.
+ pa_operation* o;
+ if (!(o = pa_context_move_source_output_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) {
+ logMessage(QString::fromLatin1("pa_context_move_source_output_by_index() failed"));
+ return false;
+ }
+ pa_operation_unref(o);
+ } else {
+ logMessage(QString::fromLatin1("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then"));
+ }
+ return true;
+#endif
+}
+
+void PulseSupport::clearStreamCache(QString streamUuid) {
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(streamUuid);
+ return;
+#else
+ logMessage(QString::fromLatin1("Clearing stream cache for stream %1").arg(streamUuid));
+ s_outputStreamIndexMap.remove(streamUuid);
+ s_captureStreamIndexMap.remove(streamUuid);
+#endif
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_pulsesupport.cpp"
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/pulsesupport.h b/src/3rdparty/phonon/phonon/pulsesupport.h
new file mode 100644
index 0000000..c38bece
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/pulsesupport.h
@@ -0,0 +1,78 @@
+/* This file is part of the KDE project
+ Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_PULSESUPPORT_H
+#define PHONON_PULSESUPPORT_H
+
+#include "phonon_export.h"
+#include "phononnamespace.h"
+#include "objectdescription.h"
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class PHONON_EXPORT PulseSupport : public QObject
+ {
+ Q_OBJECT
+ public:
+ static PulseSupport* getInstance();
+ static void shutdown();
+
+ bool isActive();
+ void enable(bool enabled = true);
+
+ QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+ QList<int> objectIndexesByCategory(ObjectDescriptionType type, Category category) const;
+
+ void setOutputDevicePriorityForCategory(Category category, QList<int> order);
+ void setCaptureDevicePriorityForCategory(Category category, QList<int> order);
+
+ void setStreamPropList(Category category, QString streamUuid);
+ void emitObjectDescriptionChanged(ObjectDescriptionType);
+ void emitUsingDevice(QString streamUuid, int device);
+
+ bool setOutputDevice(QString streamUuid, int device);
+ bool setCaptureDevice(QString streamUuid, int device);
+ void clearStreamCache(QString streamUuid);
+
+ signals:
+ void objectDescriptionChanged(ObjectDescriptionType);
+ void usingDevice(QString streamUuid, int device);
+
+ private:
+ PulseSupport();
+ ~PulseSupport();
+
+ bool mEnabled;
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_PULSESUPPORT_H
diff --git a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h
new file mode 100644
index 0000000..f25b15e
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h
@@ -0,0 +1,94 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_QSETTINGSGROUP_P_H
+#define PHONON_QSETTINGSGROUP_P_H
+
+#include <QtCore/QSettings>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+class QSettingsGroup
+{
+ public:
+ inline QSettingsGroup(QSettings *settings, const QString &name)
+ : m_mutableSettings(settings),
+ m_settings(settings),
+ m_group(name + QLatin1Char('/'))
+ {
+ }
+
+ inline QSettingsGroup(const QSettings *settings, const QString &name)
+ : m_mutableSettings(0),
+ m_settings(settings),
+ m_group(name + QLatin1Char('/'))
+ {
+ }
+
+ template<typename T>
+ inline T value(const QString &key, const T &def) const
+ {
+ return qvariant_cast<T>(value(key, QVariant::fromValue(def)));
+ }
+
+ inline QVariant value(const QString &key, const QVariant &def) const
+ {
+ return m_settings->value(m_group + key, def);
+ }
+
+ template<typename T>
+ inline void setValue(const QString &key, const T &value)
+ {
+ Q_ASSERT(m_mutableSettings);
+ m_mutableSettings->setValue(m_group + key, QVariant::fromValue(value));
+ }
+
+ inline void removeEntry(const QString &key)
+ {
+ Q_ASSERT(m_mutableSettings);
+ m_mutableSettings->remove(m_group + key);
+ }
+
+ inline bool hasKey(const QString &key) const
+ {
+ return m_settings->contains(m_group + key);
+ }
+
+ private:
+ QSettings *const m_mutableSettings;
+ const QSettings *const m_settings;
+ QString m_group;
+};
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif //QT_NO_PHONON_SETTINGSGROUP
+
+#endif // PHONON_QSETTINGSGROUP_P_H
diff --git a/src/3rdparty/phonon/phonon/seekslider.cpp b/src/3rdparty/phonon/phonon/seekslider.cpp
new file mode 100644
index 0000000..b5b25f0
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/seekslider.cpp
@@ -0,0 +1,263 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "seekslider.h"
+#include "seekslider_p.h"
+#include "mediaobject.h"
+#include "phonondefs_p.h"
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_SEEKSLIDER
+
+namespace Phonon
+{
+
+SeekSlider::SeekSlider(QWidget *parent)
+ : QWidget(parent)
+ , k_ptr(new SeekSliderPrivate(this))
+{
+ K_D(SeekSlider);
+ connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_seek(int)));
+}
+
+SeekSlider::SeekSlider(MediaObject *mo, QWidget *parent)
+ : QWidget(parent)
+ , k_ptr(new SeekSliderPrivate(this))
+{
+ K_D(SeekSlider);
+ connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_seek(int)));
+ setMediaObject(mo);
+}
+
+/*SeekSlider::SeekSlider(SeekSliderPrivate &_d, QWidget *parent)
+ : QWidget(parent)
+ , k_ptr(&_d)
+{
+} */
+
+SeekSlider::~SeekSlider()
+{
+ delete k_ptr;
+}
+
+void SeekSlider::setMediaObject(MediaObject *media)
+{
+ K_D(SeekSlider);
+ if (d->media) {
+ disconnect(d->media, 0, this, 0);
+ }
+ d->media = media;
+
+ if (media) {
+ connect(media, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
+ SLOT(_k_stateChanged(Phonon::State)));
+ connect(media, SIGNAL(totalTimeChanged(qint64)), SLOT(_k_length(qint64)));
+ connect(media, SIGNAL(tick(qint64)), SLOT(_k_tick(qint64)));
+ connect(media, SIGNAL(seekableChanged(bool)), SLOT(_k_seekableChanged(bool)));
+ connect(media, SIGNAL(currentSourceChanged(const Phonon::MediaSource&)), SLOT(_k_currentSourceChanged()));
+ d->_k_stateChanged(media->state());
+ d->_k_seekableChanged(media->isSeekable());
+ d->_k_length(media->totalTime());
+ } else {
+ d->_k_stateChanged(Phonon::StoppedState);
+ d->_k_seekableChanged(false);
+ }
+}
+
+MediaObject *SeekSlider::mediaObject() const
+{
+ K_D(const SeekSlider);
+ return d->media;
+}
+
+void SeekSliderPrivate::_k_seek(int msec)
+{
+ if (!ticking && media) {
+ media->seek(msec);
+ }
+}
+
+void SeekSliderPrivate::_k_tick(qint64 msec)
+{
+ ticking = true;
+ slider.setValue(msec);
+ ticking = false;
+}
+
+void SeekSliderPrivate::_k_length(qint64 msec)
+{
+ ticking = true;
+ slider.setRange(0, msec);
+ ticking = false;
+}
+
+void SeekSliderPrivate::_k_seekableChanged(bool isSeekable)
+{
+ if (!isSeekable || !media) {
+ setEnabled(false);
+ } else {
+ switch (media->state()) {
+ case Phonon::PlayingState:
+ if (media->tickInterval() == 0) {
+ // if the tick signal is not enabled the slider is useless
+ // set the tickInterval to some common value
+ media->setTickInterval(350);
+ }
+ case Phonon::BufferingState:
+ case Phonon::PausedState:
+ setEnabled(true);
+ break;
+ case Phonon::StoppedState:
+ case Phonon::LoadingState:
+ case Phonon::ErrorState:
+ setEnabled(false);
+ ticking = true;
+ slider.setValue(0);
+ ticking = false;
+ break;
+ }
+ }
+}
+
+void SeekSliderPrivate::_k_currentSourceChanged()
+{
+ //this releases the mouse and makes the seek slider stop seeking if the current source has changed
+ QMouseEvent event(QEvent::MouseButtonRelease, QPoint(), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(&slider, &event);
+}
+
+void SeekSliderPrivate::setEnabled(bool x)
+{
+ slider.setEnabled(x);
+ iconLabel.setPixmap(icon.pixmap(iconSize, x ? QIcon::Normal : QIcon::Disabled));
+}
+
+void SeekSliderPrivate::_k_stateChanged(State newstate)
+{
+ if (!media || !media->isSeekable()) {
+ setEnabled(false);
+ return;
+ }
+ switch (newstate) {
+ case Phonon::PlayingState:
+ if (media->tickInterval() == 0) {
+ // if the tick signal is not enabled the slider is useless
+ // set the tickInterval to some common value
+ media->setTickInterval(350);
+ }
+ case Phonon::BufferingState:
+ case Phonon::PausedState:
+ setEnabled(true);
+ break;
+ case Phonon::StoppedState:
+ case Phonon::LoadingState:
+ case Phonon::ErrorState:
+ setEnabled(false);
+ ticking = true;
+ slider.setValue(0);
+ ticking = false;
+ break;
+ }
+}
+
+bool SeekSlider::hasTracking() const
+{
+ return k_ptr->slider.hasTracking();
+}
+
+void SeekSlider::setTracking(bool tracking)
+{
+ k_ptr->slider.setTracking(tracking);
+}
+
+int SeekSlider::pageStep() const
+{
+ return k_ptr->slider.pageStep();
+}
+
+void SeekSlider::setPageStep(int milliseconds)
+{
+ k_ptr->slider.setPageStep(milliseconds);
+}
+
+int SeekSlider::singleStep() const
+{
+ return k_ptr->slider.singleStep();
+}
+
+void SeekSlider::setSingleStep(int milliseconds)
+{
+ k_ptr->slider.setSingleStep(milliseconds);
+}
+
+bool SeekSlider::isIconVisible() const
+{
+ K_D(const SeekSlider);
+ return d->iconLabel.isVisible();
+}
+
+void SeekSlider::setIconVisible(bool vis)
+{
+ K_D(SeekSlider);
+ d->iconLabel.setVisible(vis);
+}
+
+Qt::Orientation SeekSlider::orientation() const
+{
+ return k_ptr->slider.orientation();
+}
+
+void SeekSlider::setOrientation(Qt::Orientation o)
+{
+ K_D(SeekSlider);
+ Qt::Alignment align = (o == Qt::Horizontal ? Qt::AlignVCenter : Qt::AlignHCenter);
+ d->layout.setAlignment(&d->iconLabel, align);
+ d->layout.setAlignment(&d->slider, align);
+ d->layout.setDirection(o == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
+ d->slider.setOrientation(o);
+}
+
+QSize SeekSlider::iconSize() const
+{
+ return k_ptr->iconSize;
+}
+
+void SeekSlider::setIconSize(const QSize &iconSize)
+{
+ K_D(SeekSlider);
+ d->iconSize = iconSize;
+ d->iconLabel.setPixmap(d->icon.pixmap(d->iconSize, d->slider.isEnabled() ? QIcon::Normal : QIcon::Disabled));
+}
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_SEEKSLIDER
+
+QT_END_NAMESPACE
+
+#include "moc_seekslider.cpp"
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/seekslider.h b/src/3rdparty/phonon/phonon/seekslider.h
new file mode 100644
index 0000000..0005029
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/seekslider.h
@@ -0,0 +1,157 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_UI_SEEKSLIDER_H
+#define PHONON_UI_SEEKSLIDER_H
+
+#include "phonon_export.h"
+#include "phonondefs.h"
+#include "phononnamespace.h"
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_SEEKSLIDER
+
+namespace Phonon
+{
+class MediaObject;
+
+class SeekSliderPrivate;
+
+/** \class SeekSlider seekslider.h Phonon/SeekSlider
+ * \short Widget providing a slider for seeking in MediaObject objects.
+ *
+ * \ingroup PhononWidgets
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class PHONON_EXPORT SeekSlider : public QWidget
+{
+ Q_OBJECT
+ K_DECLARE_PRIVATE(SeekSlider)
+ /**
+ * This property holds whether the icon next to the slider is visible.
+ *
+ * By default the icon is visible if the platform provides an icon; else
+ * it's hidden.
+ */
+ Q_PROPERTY(bool iconVisible READ isIconVisible WRITE setIconVisible)
+
+ /**
+ * This property holds whether slider tracking is enabled.
+ *
+ * If tracking is enabled (the default), the media seeks
+ * while the slider is being dragged. If tracking is
+ * disabled, the media seeks only when the user
+ * releases the slider.
+ */
+ Q_PROPERTY(bool tracking READ hasTracking WRITE setTracking)
+
+ /**
+ * This property holds the page step.
+ *
+ * The larger of two natural steps that a slider provides and
+ * typically corresponds to the user pressing PageUp or PageDown.
+ *
+ * Defaults to 5 seconds.
+ */
+ Q_PROPERTY(int pageStep READ pageStep WRITE setPageStep)
+
+ /**
+ * This property holds the single step.
+ *
+ * The smaller of two natural steps that a slider provides and
+ * typically corresponds to the user pressing an arrow key.
+ *
+ * Defaults to 0.5 seconds.
+ */
+ Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep)
+
+ /**
+ * This property holds the orientation of the slider.
+ *
+ * The orientation must be Qt::Vertical or Qt::Horizontal (the default).
+ */
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+
+ /**
+ * \brief the icon size used for the mute button/icon.
+ *
+ * The default size is defined by the GUI style.
+ */
+ Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
+
+ public:
+ /**
+ * Constructs a seek slider widget with the given \p parent.
+ */
+ explicit SeekSlider(QWidget *parent = 0);
+ explicit SeekSlider(MediaObject *media, QWidget *parent = 0);
+
+ /**
+ * Destroys the seek slider.
+ */
+ ~SeekSlider();
+
+ bool hasTracking() const;
+ void setTracking(bool tracking);
+ int pageStep() const;
+ void setPageStep(int milliseconds);
+ int singleStep() const;
+ void setSingleStep(int milliseconds);
+ Qt::Orientation orientation() const;
+ bool isIconVisible() const;
+ QSize iconSize() const;
+ MediaObject *mediaObject() const;
+
+ public Q_SLOTS:
+ void setOrientation(Qt::Orientation);
+ void setIconVisible(bool);
+ void setIconSize(const QSize &size);
+
+ /**
+ * Sets the media object to be controlled by this slider.
+ */
+ void setMediaObject(MediaObject *);
+
+ protected:
+ SeekSliderPrivate *const k_ptr;
+
+ private:
+ Q_PRIVATE_SLOT(k_func(), void _k_stateChanged(Phonon::State))
+ Q_PRIVATE_SLOT(k_func(), void _k_seek(int))
+ Q_PRIVATE_SLOT(k_func(), void _k_tick(qint64))
+ Q_PRIVATE_SLOT(k_func(), void _k_length(qint64))
+ Q_PRIVATE_SLOT(k_func(), void _k_seekableChanged(bool))
+ Q_PRIVATE_SLOT(k_func(), void _k_currentSourceChanged())
+};
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_SEEKSLIDER
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // PHONON_UI_SEEKSLIDER_H
diff --git a/src/3rdparty/phonon/phonon/seekslider_p.h b/src/3rdparty/phonon/phonon/seekslider_p.h
new file mode 100644
index 0000000..911ab25
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/seekslider_p.h
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef SEEKSLIDER_P_H
+#define SEEKSLIDER_P_H
+
+#include "seekslider.h"
+#include "swiftslider_p.h"
+#include <QtGui/QBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QPixmap>
+#include <QtGui/QIcon>
+#include <QtGui/QStyle>
+#include "factory_p.h"
+#include <QtCore/QPointer>
+#include "platform_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_SEEKSLIDER
+
+namespace Phonon
+{
+class MediaObject;
+class SeekSliderPrivate
+{
+ Q_DECLARE_PUBLIC(SeekSlider)
+ protected:
+ SeekSliderPrivate(SeekSlider *parent)
+ : layout(QBoxLayout::LeftToRight, parent),
+ slider(Qt::Horizontal, parent),
+ iconLabel(parent),
+ ticking(false)
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ ,icon(Platform::icon(QLatin1String("player-time"), parent->style()))
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ {
+ const int e = parent->style()->pixelMetric(QStyle::PM_ButtonIconSize);
+ iconSize = QSize(e, e);
+
+ slider.setPageStep(5000); // 5 sec
+ slider.setSingleStep(500); // 0.5 sec
+
+ layout.setMargin(0);
+ layout.setSpacing(2);
+ layout.addWidget(&iconLabel, 0, Qt::AlignVCenter);
+ layout.addWidget(&slider, 0, Qt::AlignVCenter);
+
+ setEnabled(false);
+
+ if (icon.isNull()) {
+ iconLabel.setVisible(false);
+ }
+ }
+
+ SeekSlider *q_ptr;
+
+ private:
+ void setEnabled(bool);
+ void _k_stateChanged(Phonon::State);
+ void _k_seek(int);
+ void _k_tick(qint64);
+ void _k_length(qint64);
+ void _k_seekableChanged(bool);
+ void _k_currentSourceChanged();
+
+ QBoxLayout layout;
+ SwiftSlider slider;
+ QLabel iconLabel;
+ QPointer<MediaObject> media;
+ bool ticking;
+ QIcon icon;
+ QSize iconSize;
+};
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_SEEKSLIDER
+
+QT_END_NAMESPACE
+
+#endif // SEEKSLIDER_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/stream-thoughts b/src/3rdparty/phonon/phonon/stream-thoughts
new file mode 100644
index 0000000..5fb6711
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/stream-thoughts
@@ -0,0 +1,72 @@
+there are two different kind of streams: 1. media files 2. live radio/television
+
+The difference cannot reliably be determined by the backend so the application has to tell the
+frontend.
+
+This is the expected behaviour:
+1. media files
+==============
+function | prev. state | action | new state
+---------+-------------+----------------------------------------------------------------+----------
+ctor | | | Loading
+---------+-------------+----------------------------------------------------------------+----------
+setUrl | Loading | refill buffers | Loading
+ | Stopped | refill buffers | Loading
+---------+-------------+----------------------------------------------------------------+----------
+play | Loading | continue buffering | Buffering
+ | Stopped | start playing | Playing
+ | Buffering | continue buffering | Buffering
+ | Playing | | Playing
+ | Paused | continue playback | Playing
+---------+-------------+----------------------------------------------------------------+----------
+pause | Loading | | Loading
+ | Stopped | | Stopped
+ | Buffering | continue buffering | Paused
+ | Playing | pause output and fill buffers to the max | Paused
+ | Paused | | Paused
+---------+-------------+----------------------------------------------------------------+----------
+stop | Loading | | Loading
+ | Stopped | | Stopped
+ | Buffering | restart buffering from the beginning of the file | Loading
+ | Playing | stop output and refill buffers from the beginning of the file | Loading
+ | Paused | restart buffering from the beginning of the file | Loading
+
+events
+function | prev. state | event | new state
+---------+-------------+----------------------------------------------------------------+----------
+ | Buffering | when the buffers are filled start playing | Playing
+ | Loading | when buffers are filled | Stopped
+
+
+
+2. live stream
+==============
+function | prev. state | action | new state
+---------+-------------+----------------------------------------------------------------+----------
+ctor | | | Loading
+---------+-------------+----------------------------------------------------------------+----------
+setUrl | Loading | | Stopped
+ | Stopped | | Stopped
+---------+-------------+----------------------------------------------------------------+----------
+play | Loading | | Error
+ | Stopped | start buffering | Buffering
+ | Buffering | continue buffering | Buffering
+ | Playing | | Playing
+ | Paused | continue playback | Playing
+---------+-------------+----------------------------------------------------------------+----------
+pause | Loading | | Error
+ | Stopped | | Stopped
+ | Buffering | continue buffering | Paused
+ | Playing | pause output and fill (ring-)buffers to the max | Paused
+ | Paused | | Paused
+---------+-------------+----------------------------------------------------------------+----------
+stop | Loading | | Error
+ | Stopped | | Stopped
+ | Buffering | clear buffers | Stopped
+ | Playing | stop output and clear buffers | Stopped
+ | Paused | clear buffers | Stopped
+
+events
+function | prev. state | event | new state
+---------+-------------+----------------------------------------------------------------+----------
+ | Buffering | when the buffers are filled start playing | Playing
diff --git a/src/3rdparty/phonon/phonon/streaminterface.cpp b/src/3rdparty/phonon/phonon/streaminterface.cpp
new file mode 100644
index 0000000..666cb1e
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/streaminterface.cpp
@@ -0,0 +1,114 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "streaminterface.h"
+#include "streaminterface_p.h"
+#include "abstractmediastream.h"
+#include "abstractmediastream_p.h"
+#include "mediasource_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+
+StreamInterface::StreamInterface()
+ : d(new StreamInterfacePrivate)
+{
+ d->q = this;
+}
+
+StreamInterface::~StreamInterface()
+{
+ if (d->connected) {
+ AbstractMediaStreamPrivate *dd = d->mediaSource.stream()->d_func();
+ dd->setStreamInterface(0);
+ }
+ delete d;
+}
+
+void StreamInterface::connectToSource(const MediaSource &mediaSource)
+{
+ Q_ASSERT(!d->connected);
+ d->connected = true;
+ d->mediaSource = mediaSource;
+ Q_ASSERT(d->mediaSource.type() == MediaSource::Stream);
+ Q_ASSERT(d->mediaSource.stream());
+ AbstractMediaStreamPrivate *dd = d->mediaSource.stream()->d_func();
+ dd->setStreamInterface(this);
+ d->mediaSource.stream()->reset();
+}
+
+void StreamInterfacePrivate::disconnectMediaStream()
+{
+ Q_ASSERT(connected);
+ connected = false;
+
+ // if mediaSource has autoDelete set then it will delete the AbstractMediaStream again who's
+ // destructor is calling us right now
+ mediaSource.setAutoDelete(false);
+
+ mediaSource = MediaSource();
+ q->endOfData();
+ q->setStreamSeekable(false);
+}
+
+void StreamInterface::needData()
+{
+ if (d->mediaSource.type() == MediaSource::Stream) {
+ d->mediaSource.stream()->needData();
+ }
+}
+
+void StreamInterface::enoughData()
+{
+ Q_ASSERT(d->connected);
+ if (d->mediaSource.type() == MediaSource::Stream) {
+ d->mediaSource.stream()->enoughData();
+ }
+}
+
+void StreamInterface::seekStream(qint64 offset)
+{
+ Q_ASSERT(d->connected);
+ if (d->mediaSource.type() == MediaSource::Stream) {
+ d->mediaSource.stream()->seekStream(offset);
+ }
+}
+
+void StreamInterface::reset()
+{
+ Q_ASSERT(d->connected);
+ if (d->mediaSource.type() == MediaSource::Stream) {
+ d->mediaSource.stream()->reset();
+ }
+}
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+
+
diff --git a/src/3rdparty/phonon/phonon/streaminterface.h b/src/3rdparty/phonon/phonon/streaminterface.h
new file mode 100644
index 0000000..67df05d
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/streaminterface.h
@@ -0,0 +1,123 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_STREAMINTERFACE_H
+#define PHONON_STREAMINTERFACE_H
+
+#include "phonon_export.h"
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+class StreamInterfacePrivate;
+class MediaSource;
+
+/** \class StreamInterface streaminterface.h Phonon/StreamInterface
+ * \brief Backend interface to handle media streams (AbstractMediaStream).
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class PHONON_EXPORT StreamInterface
+{
+ friend class StreamInterfacePrivate;
+ friend class AbstractMediaStreamPrivate;
+ public:
+ virtual ~StreamInterface();
+ /**
+ * Called by the application to send a chunk of (encoded) media data.
+ *
+ * It is recommended to keep the QByteArray object until the data is consumed so that no
+ * memcopy is needed.
+ */
+ virtual void writeData(const QByteArray &data) = 0;
+ /**
+ * Called when no more media data is available and writeData will not be called anymore.
+ */
+ virtual void endOfData() = 0;
+ /**
+ * Called at the start of the stream to tell how many bytes will be sent through writeData
+ * (if no seeks happen, of course). If this value is negative the stream size cannot be
+ * determined (might be a "theoretically infinite" stream - like webradio).
+ */
+ virtual void setStreamSize(qint64 newSize) = 0;
+ /**
+ * Tells whether the stream is seekable.
+ */
+ virtual void setStreamSeekable(bool s) = 0;
+
+ /**
+ * Call this function from the constructor of your StreamInterface implementation (or as
+ * soon as you get the MediaSource object). This will connect your object to the
+ * AbstractMediaStream object. Only after the connection is done will the following
+ * functions have an effect.
+ */
+ void connectToSource(const MediaSource &mediaSource);
+
+ /**
+ * Call this function to tell the AbstractMediaStream that you need more data. The data will
+ * arrive through writeData. Don't rely on writeData getting called from needData, though
+ * some AbstractMediaStream implementations might do so.
+ *
+ * Depending on the buffering you need you either treat needData as a replacement for a
+ * read call like QIODevice::read, or you start calling needData whenever your buffer
+ * reaches a certain lower threshold.
+ */
+ void needData();
+
+ /**
+ * Call this function to tell the AbstractMediaStream that you have enough data in your
+ * buffer and that it should pause calling writeData if possible.
+ */
+ void enoughData();
+
+ /**
+ * If the stream is seekable, calling this function will make the next call to writeData
+ * pass data that starts at the byte offset \p seekTo.
+ */
+ void seekStream(qint64 seekTo);
+
+ /**
+ * Resets the AbstractMediaStream. E.g. this can be useful for non-seekable streams to start
+ * over again.
+ */
+ void reset();
+
+ protected:
+ StreamInterface();
+
+ StreamInterfacePrivate *const d;
+};
+} // namespace Phonon
+
+Q_DECLARE_INTERFACE(Phonon::StreamInterface, "StreamInterface1.phonon.kde.org")
+
+#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_STREAMINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/streaminterface_p.h b/src/3rdparty/phonon/phonon/streaminterface_p.h
new file mode 100644
index 0000000..426c58d
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/streaminterface_p.h
@@ -0,0 +1,59 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef STREAMINTERFACE_P_H
+#define STREAMINTERFACE_P_H
+
+#include "streaminterface.h"
+#include "mediasource.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+namespace Phonon
+{
+class StreamInterfacePrivate
+{
+ friend class StreamInterface;
+ public:
+ void disconnectMediaStream();
+
+ protected:
+ inline StreamInterfacePrivate()
+ : connected(false)
+ {
+ }
+
+ StreamInterface *q;
+ MediaSource mediaSource;
+ bool connected;
+};
+
+} // namespace Phonon
+
+#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
+
+QT_END_NAMESPACE
+
+#endif // STREAMINTERFACE_P_H
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/phonon/swiftslider.cpp b/src/3rdparty/phonon/phonon/swiftslider.cpp
new file mode 100644
index 0000000..1e274aa
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/swiftslider.cpp
@@ -0,0 +1,103 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2008 Ricardo Villalba <rvm@escomposlinux.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "swiftslider_p.h"
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER)
+
+namespace Phonon
+{
+
+SwiftSlider::SwiftSlider(Qt::Orientation orientation, QWidget * parent)
+ : QSlider(orientation, parent)
+{
+}
+
+SwiftSlider::~SwiftSlider()
+{
+}
+
+// Function copied from qslider.cpp
+inline int SwiftSlider::pick(const QPoint &pt) const
+{
+ return orientation() == Qt::Horizontal ? pt.x() : pt.y();
+}
+
+// Function copied from qslider.cpp and modified to make it compile
+int SwiftSlider::pixelPosToRangeValue(int pos) const
+{
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+ QRect gr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
+ QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
+ int sliderMin, sliderMax, sliderLength;
+
+ if (orientation() == Qt::Horizontal) {
+ sliderLength = sr.width();
+ sliderMin = gr.x();
+ sliderMax = gr.right() - sliderLength + 1;
+ } else {
+ sliderLength = sr.height();
+ sliderMin = gr.y();
+ sliderMax = gr.bottom() - sliderLength + 1;
+ }
+ return QStyle::sliderValueFromPosition(minimum(), maximum(), pos - sliderMin,
+ sliderMax - sliderMin, opt.upsideDown);
+}
+
+// Based on code from qslider.cpp
+void SwiftSlider::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+ const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
+ const QPoint center = sliderRect.center() - sliderRect.topLeft();
+ // to take half of the slider off for the setSliderPosition call we use the center - topLeft
+
+ if (!sliderRect.contains(event->pos())) {
+ event->accept();
+
+ setSliderPosition(pixelPosToRangeValue(pick(event->pos() - center)));
+ triggerAction(SliderMove);
+ setRepeatAction(SliderNoAction);
+ } else {
+ QSlider::mousePressEvent(event);
+ }
+ } else {
+ QSlider::mousePressEvent(event);
+ }
+}
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER
+
+QT_END_NAMESPACE
+
+#include "moc_swiftslider_p.cpp"
diff --git a/src/3rdparty/phonon/phonon/swiftslider_p.h b/src/3rdparty/phonon/phonon/swiftslider_p.h
new file mode 100644
index 0000000..b063b47
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/swiftslider_p.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2008 Ricardo Villalba <rvm@escomposlinux.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef SWIFTSLIDER_H
+#define SWIFTSLIDER_H
+
+#include <QtGui/QSlider>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER)
+
+namespace Phonon
+{
+
+/** \class SwiftSlider swiftslider_p.h phonon/SwiftSlider
+ * \short Modified QSlider that allows sudden/quick moves instead of stepped moves ("Click'n'Go" QSlider)
+ *
+ * This is an internal class used by SeekSlider and VolumeSlider.
+ *
+ * Ricardo Villalba, the original author of MySlider.cpp (from the SMPlayer project)
+ * gave his permission for the inclusion of this code inside Phonon by
+ * switching MySlider.cpp to the LGPLv2.1+ license.
+ * See http://smplayer.svn.sourceforge.net/viewvc/smplayer/smplayer/trunk/src/myslider.cpp?revision=2406&view=markup
+ *
+ * The original discussion about a "Click'n'Go QSlider": http://lists.trolltech.com/qt-interest/2006-11/msg00363.html
+ *
+ * \ingroup PhononWidgets
+ */
+class SwiftSlider : public QSlider
+{
+ Q_OBJECT
+public:
+ SwiftSlider(Qt::Orientation orientation, QWidget * parent);
+ ~SwiftSlider();
+
+private:
+ void mousePressEvent(QMouseEvent *event);
+ inline int pick(const QPoint &pt) const;
+ int pixelPosToRangeValue(int pos) const;
+};
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER
+
+QT_END_NAMESPACE
+
+#endif //SWIFTSLIDER_H
diff --git a/src/3rdparty/phonon/phonon/videoplayer.cpp b/src/3rdparty/phonon/phonon/videoplayer.cpp
new file mode 100644
index 0000000..8851b05
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/videoplayer.cpp
@@ -0,0 +1,184 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "videoplayer.h"
+#include "mediaobject.h"
+#include "audiooutput.h"
+#include "videowidget.h"
+#include "path.h"
+#include <QtGui/QBoxLayout>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEOPLAYER
+
+namespace Phonon
+{
+
+class VideoPlayerPrivate
+{
+ public:
+ VideoPlayerPrivate()
+ : player(0)
+ , aoutput(0)
+ , voutput(0) {}
+
+ void init(VideoPlayer *q, Phonon::Category category);
+
+ MediaObject *player;
+ AudioOutput *aoutput;
+ VideoWidget *voutput;
+
+ MediaSource src;
+};
+
+void VideoPlayerPrivate::init(VideoPlayer *q, Phonon::Category category)
+{
+ QVBoxLayout *layout = new QVBoxLayout(q);
+ layout->setMargin(0);
+
+ aoutput = new AudioOutput(category, q);
+
+ voutput = new VideoWidget(q);
+ layout->addWidget(voutput);
+
+ player = new MediaObject(q);
+ Phonon::createPath(player, aoutput);
+ Phonon::createPath(player, voutput);
+
+ q->connect(player, SIGNAL(finished()), SIGNAL(finished()));
+}
+
+VideoPlayer::VideoPlayer(Phonon::Category category, QWidget *parent)
+ : QWidget(parent)
+ , d(new VideoPlayerPrivate)
+{
+ d->init(this, category);
+}
+
+VideoPlayer::VideoPlayer(QWidget *parent)
+ : QWidget(parent)
+ , d(new VideoPlayerPrivate)
+{
+ d->init(this, Phonon::VideoCategory);
+}
+
+VideoPlayer::~VideoPlayer()
+{
+ delete d;
+}
+
+MediaObject *VideoPlayer::mediaObject() const
+{
+ return d->player;
+}
+
+AudioOutput *VideoPlayer::audioOutput() const
+{
+ return d->aoutput;
+}
+
+VideoWidget *VideoPlayer::videoWidget() const
+{
+ return d->voutput;
+}
+
+void VideoPlayer::load(const MediaSource &source)
+{
+ d->player->setCurrentSource(source);
+}
+
+void VideoPlayer::play(const MediaSource &source)
+{
+ if (source == d->player->currentSource()) {
+ if (!isPlaying())
+ d->player->play();
+ return;
+ }
+ // new URL
+ d->player->setCurrentSource(source);
+
+ if (ErrorState == d->player->state())
+ return;
+
+ d->player->play();
+}
+
+void VideoPlayer::play()
+{
+ d->player->play();
+}
+
+void VideoPlayer::pause()
+{
+ d->player->pause();
+}
+
+void VideoPlayer::stop()
+{
+ d->player->stop();
+}
+
+qint64 VideoPlayer::totalTime() const
+{
+ return d->player->totalTime();
+}
+
+qint64 VideoPlayer::currentTime() const
+{
+ return d->player->currentTime();
+}
+
+void VideoPlayer::seek(qint64 ms)
+{
+ d->player->seek(ms);
+}
+
+float VideoPlayer::volume() const
+{
+ return d->aoutput->volume();
+}
+
+void VideoPlayer::setVolume(float v)
+{
+ d->aoutput->setVolume(v);
+}
+
+bool VideoPlayer::isPlaying() const
+{
+ return (d->player->state() == PlayingState);
+}
+
+bool VideoPlayer::isPaused() const
+{
+ return (d->player->state() == PausedState);
+}
+
+} // namespaces
+
+#endif //QT_NO_PHONON_VIDEOPLAYER
+
+QT_END_NAMESPACE
+
+#include "moc_videoplayer.cpp"
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/videoplayer.h b/src/3rdparty/phonon/phonon/videoplayer.h
new file mode 100644
index 0000000..7970f04
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/videoplayer.h
@@ -0,0 +1,207 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef Phonon_VIDEOPLAYER_H
+#define Phonon_VIDEOPLAYER_H
+
+#include "phonon_export.h"
+#include "phononnamespace.h"
+#include "mediasource.h"
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEOPLAYER
+
+namespace Phonon
+{
+class VideoPlayerPrivate;
+class MediaObject;
+class AudioOutput;
+class VideoWidget;
+
+/** \class VideoPlayer videoplayer.h Phonon/VideoPlayer
+ * \short Playback class for simple tasks.
+ *
+ * With %VideoPlayer you can get results quickly and easily. You can do the standard
+ * playback tasks like play, pause and stop, but also set a playback volume and
+ * seek (there's no guarantee that the seek will work, though).
+ *
+ * Keep in mind that when the %VideoPlayer instance is deleted the playback will
+ * stop.
+ *
+ * A play and forget code example:
+ * \code
+ * VideoPlayer *player = new VideoPlayer(parentWidget);
+ * connect(player, SIGNAL(finished()), player, SLOT(deleteLater()));
+ * player->play(url);
+ * \endcode
+ *
+ * \ingroup Playback
+ * \ingroup PhononVideo
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class PHONON_EXPORT VideoPlayer : public QWidget
+{
+ Q_OBJECT
+ public:
+ /**
+ * Constructs a new %VideoPlayer instance.
+ *
+ * \param category The category used for the audio output device.
+ * \param parent The QObject parent.
+ */
+ explicit VideoPlayer(Phonon::Category category, QWidget *parent = 0);
+
+ /**
+ * Constructs a new video widget with a \p parent
+ * using Phonon::VideoCategory as its category.
+ *
+ * \param parent The QObject parent.
+ */
+ VideoPlayer(QWidget *parent = 0);
+
+ /**
+ * On destruction the playback is stopped, also the audio output is
+ * removed so that the desktop mixer will not show the application
+ * anymore. If you need a persistent audio output don't use
+ * %VideoPlayer but MediaObject, VideoPath and VideoOutput.
+ */
+ ~VideoPlayer();
+
+ /**
+ * Get the total time (in milliseconds) of the file currently being played.
+ */
+ qint64 totalTime() const;
+ /**
+ * Get the current time (in milliseconds) of the file currently being played.
+ */
+ qint64 currentTime() const;
+ /**
+ * This is the current volume of the output as voltage factor.
+ *
+ * 1.0 means 100%, 0.5 means 50% voltage/25% power, 0.0 means 0%
+ */
+ float volume() const;
+
+ /**
+ * \returns \c true if it is currently playing
+ * \returns \c false if it is currently stopped or paused
+ */
+ bool isPlaying() const;
+ /**
+ * \returns \c true if it is currently paused
+ * \returns \c false if it is currently playing or stopped
+ */
+ bool isPaused() const;
+
+ /**
+ * getter for the MediaObject.
+ */
+ MediaObject *mediaObject() const;
+
+ /**
+ * getter for the AudioOutput.
+ */
+ AudioOutput *audioOutput() const;
+
+ /**
+ * getter for the VideoWidget.
+ */
+ VideoWidget *videoWidget() const;
+
+ public Q_SLOTS:
+ /**
+ * Starts preloading the media data and fill audiobuffers in the
+ * backend.
+ *
+ * When there's already a media playing (or paused) it will be stopped
+ * (the finished signal will not be emitted).
+ */
+ void load(const Phonon::MediaSource &source);
+
+ /**
+ * Play the media at the given URL. Starts playback as fast as possible.
+ * This can take a considerable time depending on the URL and the
+ * backend.
+ *
+ * If you need low latency between calling play() and the sound actually
+ * starting to play on your output device you need to use MediaObject
+ * and be able to set the URL before calling play(). Note that
+ * \code
+ * audioPlayer->load(url);
+ * audioPlayer->play();
+ * \endcode
+ * doesn't make a difference: the application should be idle between the
+ * load and play calls so that the backend can start preloading the
+ * media and fill audio buffers.
+ */
+ void play(const Phonon::MediaSource &source);
+
+ /**
+ * Continues playback of a paused media. Restarts playback of a stopped
+ * media.
+ */
+ void play();
+ /**
+ * Pauses the playback.
+ */
+ void pause();
+ /**
+ * Stops the playback.
+ */
+ void stop();
+
+ /**
+ * Seeks to the requested time. Note that the backend is free to ignore
+ * the seek request if the media source isn't seekable.
+ *
+ * \param ms Time in milliseconds from the start of the media.
+ */
+ void seek(qint64 ms);
+ /**
+ * Sets the volume of the output as voltage factor.
+ *
+ * 1.0 means 100%, 0.5 means 50% voltage/25% power, 0.0 means 0%
+ */
+ void setVolume(float volume);
+
+ Q_SIGNALS:
+ /**
+ * This signal is emitted when the playback finished.
+ */
+ void finished();
+
+ protected:
+ VideoPlayerPrivate *const d;
+};
+
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEOPLAYER
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // Phonon_VIDEOPLAYER_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/videowidget.cpp b/src/3rdparty/phonon/phonon/videowidget.cpp
new file mode 100644
index 0000000..4575dfd
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/videowidget.cpp
@@ -0,0 +1,195 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "videowidget.h"
+#include "videowidget_p.h"
+#include "videowidgetinterface.h"
+#include "factory_p.h"
+#include "phonondefs_p.h"
+#include "phononnamespace_p.h"
+
+#include <QtGui/QAction>
+#define IFACES4 VideoWidgetInterface44
+#define IFACES0 VideoWidgetInterface, IFACES4
+#define PHONON_INTERFACENAME IFACES0
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+
+VideoWidget::VideoWidget(QWidget *parent)
+ : QWidget(parent)
+ , Phonon::AbstractVideoOutput(*new VideoWidgetPrivate(this))
+{
+ K_D(VideoWidget);
+ d->init();
+ d->createBackendObject();
+ setMouseTracking(true);
+}
+
+
+
+VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent)
+ : QWidget(parent),
+ Phonon::AbstractVideoOutput(dd)
+{
+ K_D(VideoWidget);
+ d->init();
+}
+
+void VideoWidgetPrivate::init()
+{
+ Q_Q(VideoWidget);
+ changeFlags = q->windowFlags() & (Qt::SubWindow | Qt::Window);
+}
+
+void VideoWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ QWidget::mouseMoveEvent(e);
+}
+
+void VideoWidgetPrivate::createBackendObject()
+{
+ if (m_backendObject)
+ return;
+ Q_Q(VideoWidget);
+ m_backendObject = Factory::createVideoWidget(q);
+ if (m_backendObject) {
+ setupBackendObject();
+ }
+}
+
+#define PHONON_CLASSNAME VideoWidget
+
+PHONON_INTERFACE_GETTER(Phonon::VideoWidget::AspectRatio, aspectRatio, d->aspectRatio)
+PHONON_INTERFACE_SETTER(setAspectRatio, aspectRatio, Phonon::VideoWidget::AspectRatio)
+
+PHONON_INTERFACE_GETTER(Phonon::VideoWidget::ScaleMode, scaleMode, d->scaleMode)
+PHONON_INTERFACE_SETTER(setScaleMode, scaleMode, Phonon::VideoWidget::ScaleMode)
+
+PHONON_INTERFACE_GETTER(qreal, brightness, d->brightness)
+PHONON_INTERFACE_SETTER(setBrightness, brightness, qreal)
+
+PHONON_INTERFACE_GETTER(qreal, contrast, d->contrast)
+PHONON_INTERFACE_SETTER(setContrast, contrast, qreal)
+
+PHONON_INTERFACE_GETTER(qreal, hue, d->hue)
+PHONON_INTERFACE_SETTER(setHue, hue, qreal)
+
+PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation)
+PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal)
+
+
+QImage VideoWidget::snapshot() const {
+ K_D(const VideoWidget);
+ ConstIface<IFACES4> iface(d);
+ if(iface) return iface->snapshot();
+ return QImage(); // TODO not implemented in VideoInterface
+}
+
+
+void VideoWidget::setFullScreen(bool newFullScreen)
+{
+ pDebug() << Q_FUNC_INFO << newFullScreen;
+ K_D(VideoWidget);
+ // TODO: disable screensaver? or should we leave that responsibility to the
+ // application?
+ Qt::WindowFlags flags = windowFlags();
+ if (newFullScreen) {
+ if (!isFullScreen()) {
+ //we only update that value if it is not already fullscreen
+ d->changeFlags = flags & (Qt::Window | Qt::SubWindow);
+ flags |= Qt::Window;
+ flags ^= Qt::SubWindow;
+ setWindowFlags(flags);
+#ifdef Q_WS_X11
+ // This works around a bug with Compiz
+ // as the window must be visible before we can set the state
+ show();
+ raise();
+ setWindowState( windowState() | Qt::WindowFullScreen ); // set
+#else
+ setWindowState( windowState() | Qt::WindowFullScreen ); // set
+ show();
+#endif
+ }
+ } else if (isFullScreen()) {
+ flags ^= (Qt::Window | Qt::SubWindow); //clear the flags...
+ flags |= d->changeFlags; //then we reset the flags (window and subwindow)
+ setWindowFlags(flags);
+ setWindowState( windowState() ^ Qt::WindowFullScreen ); // reset
+ show();
+ }
+}
+
+void VideoWidget::exitFullScreen()
+{
+ setFullScreen(false);
+}
+
+void VideoWidget::enterFullScreen()
+{
+ setFullScreen(true);
+}
+
+bool VideoWidgetPrivate::aboutToDeleteBackendObject()
+{
+ aspectRatio = pINTERFACE_CALL(aspectRatio());
+ scaleMode = pINTERFACE_CALL(scaleMode());
+ return AbstractVideoOutputPrivate::aboutToDeleteBackendObject();
+}
+
+void VideoWidgetPrivate::setupBackendObject()
+{
+ Q_Q(VideoWidget);
+ Q_ASSERT(m_backendObject);
+ //AbstractVideoOutputPrivate::setupBackendObject();
+ pDebug() << "calling setAspectRatio on the backend " << aspectRatio;
+ pINTERFACE_CALL(setAspectRatio(aspectRatio));
+ pINTERFACE_CALL(setScaleMode(scaleMode));
+
+ QWidget *w = pINTERFACE_CALL(widget());
+ if (w) {
+ layout.addWidget(w);
+ q->setSizePolicy(w->sizePolicy());
+ w->setMouseTracking(true);
+ }
+}
+
+bool VideoWidget::event(QEvent *e)
+{
+ return QWidget::event(e);
+}
+
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+
+#include "moc_videowidget.cpp"
+
+#undef PHONON_CLASSNAME
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/videowidget.h b/src/3rdparty/phonon/phonon/videowidget.h
new file mode 100644
index 0000000..804e61a
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/videowidget.h
@@ -0,0 +1,220 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef Phonon_VIDEOWIDGET_H
+#define Phonon_VIDEOWIDGET_H
+
+#include "phonon_export.h"
+#include "phonondefs.h"
+#include "abstractvideooutput.h"
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+class AbstractVideoOutput;
+ class VideoWidgetPrivate;
+ /** \class VideoWidget videowidget.h Phonon/VideoWidget
+ * \short Widget to display video.
+ *
+ * This widget shows the video signal.
+ *
+ * \code
+ * MediaObject *media = new MediaObject(parent);
+ * VideoWidget *vwidget = new VideoWidget(parent);
+ * Phonon::createPath(media, vwidget);
+ * \endcode
+ *
+ * \ingroup PhononVideo
+ * \ingroup PhononWidgets
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class PHONON_EXPORT VideoWidget : public QWidget, public Phonon::AbstractVideoOutput
+ {
+ K_DECLARE_PRIVATE(VideoWidget)
+ Q_OBJECT
+ Q_ENUMS(AspectRatio ScaleMode)
+ /**
+ * This property holds whether the video is shown using the complete
+ * screen.
+ *
+ * The property differs from QWidget::fullScreen in that it is
+ * writeable.
+ *
+ * By default the widget is not shown in fullScreen.
+ *
+ * \warning When switching the video to fullscreen using setFullScreen
+ * your application loses control over the widget that actually shows
+ * the video (which is then shown as a toplevel window while your
+ * application still uses this widget). If you only need to capture key
+ * events the event forwarding done internally should suffice for your
+ * needs. If you need to map mouse coordinates or add widgets (that are
+ * not overlays) you should probably handle fullscreen yourself.
+ */
+ Q_PROPERTY(bool fullScreen READ isFullScreen WRITE setFullScreen)
+ /**
+ *
+ * Defaults to AspectRatioAuto.
+ *
+ * \see AspectRatio
+ */
+ Q_PROPERTY(AspectRatio aspectRatio READ aspectRatio WRITE setAspectRatio)
+
+ /**
+ * If the size of the widget and the size of the video are not equal.
+ * The video will be zoomed to fit the widget. The smaller zoom
+ * (AddBarsScaleMode) adds black bars at the left/right or top/bottom to
+ * make all of the image visible (default). The bigger zoom (ExpandMode)
+ * fills the widget completely, keeping all information in one direction
+ * and leaving parts of the image outside of the widget in the other
+ * direction.
+ */
+ Q_PROPERTY(ScaleMode scaleMode READ scaleMode WRITE setScaleMode)
+
+ /**
+ * This property holds brightness of the video.
+ *
+ * Default is 0. Acceptable values are in range of -1, 1.
+ */
+ Q_PROPERTY(qreal brightness READ brightness WRITE setBrightness)
+ /**
+ * This property holds the contrast of the video.
+ *
+ * Default is 0. Acceptable values are in range of -1, 1.
+ */
+ Q_PROPERTY(qreal contrast READ contrast WRITE setContrast)
+ /**
+ * This property holds the hue of the video.
+ *
+ * Default is 0. Acceptable values are in range of -1, 1.
+ */
+ Q_PROPERTY(qreal hue READ hue WRITE setHue)
+ /**
+ * This property holds saturation of the video.
+ *
+ * Default is 0. Acceptable values are in range of -1, 1.
+ */
+ Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation)
+
+ public:
+ /**
+ * Defines the width:height to be used for the video.
+ */
+ enum AspectRatio
+ {
+ /**
+ * Let the decoder find the aspect ratio automatically from the
+ * media file (this is the default).
+ */
+ AspectRatioAuto = 0,
+ /**
+ * Fits the video into the widget making the aspect ratio depend
+ * solely on the size of the widget. This way the aspect ratio
+ * is freely resizeable by the user.
+ */
+ AspectRatioWidget = 1,
+ /**
+ * Make width/height == 4/3, which is the old TV size and
+ * monitor size (1024/768 == 4/3). (4:3)
+ */
+ AspectRatio4_3 = 2,
+ /**
+ * Make width/height == 16/9, which is the size of most current
+ * media. (16:9)
+ */
+ AspectRatio16_9 = 3
+//X /**
+//X * Assume that every pixel of the video image needs to be displayed with the same
+//X * physical width and height. (1:1 image pixels, not imagewidth
+//X * = imageheight)
+//X */
+//X AspectRatioSquare = 4,
+ };
+
+ enum ScaleMode {
+ FitInView = 0,
+ ScaleAndCrop = 1
+ };
+
+ /**
+ * Constructs a new video widget with a \p parent.
+ */
+ VideoWidget(QWidget *parent = 0);
+
+ AspectRatio aspectRatio() const;
+ ScaleMode scaleMode() const;
+
+ qreal brightness() const;
+ qreal contrast() const;
+ qreal hue() const;
+ qreal saturation() const;
+ QImage snapshot() const;
+
+ //TODO: bar colors property
+ public Q_SLOTS:
+ void setFullScreen(bool fullscreen);
+
+ /**
+ * Convenience slot, calling setFullScreen(false)
+ */
+ void exitFullScreen();
+
+ /**
+ * Convenience slot, calling setFullScreen(true)
+ */
+ void enterFullScreen();
+
+ void setAspectRatio(AspectRatio);
+ void setScaleMode(ScaleMode);
+
+ void setBrightness(qreal value);
+ void setContrast(qreal value);
+ void setHue(qreal value);
+ void setSaturation(qreal value);
+
+ protected:
+ /**
+ * \internal
+ *
+ * Constructs a new video widget with private data pointer \p d and
+ * a \p parent.
+ */
+ VideoWidget(VideoWidgetPrivate &d, QWidget *parent);
+
+ void mouseMoveEvent(QMouseEvent *);
+ bool event(QEvent *);
+ };
+
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_VIDEOWIDGET_H
diff --git a/src/3rdparty/phonon/phonon/videowidget_p.h b/src/3rdparty/phonon/phonon/videowidget_p.h
new file mode 100644
index 0000000..3335135
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/videowidget_p.h
@@ -0,0 +1,84 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef VIDEOWIDGET_P_H
+#define VIDEOWIDGET_P_H
+
+#include "videowidget.h"
+#include "abstractvideooutput_p.h"
+#include <QtGui/QBoxLayout>
+#include <QtCore/QEvent>
+#include <QtCore/QCoreApplication>
+#include <QtGui/QPalette>
+#include <QtGui/QKeyEvent>
+#include <QtCore/QTimer>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+
+class VideoWidgetPrivate : public Phonon::AbstractVideoOutputPrivate
+{
+ Q_DECLARE_PUBLIC(VideoWidget)
+ public:
+ virtual QObject *qObject() { return q_func(); }
+ protected:
+ virtual bool aboutToDeleteBackendObject();
+ virtual void createBackendObject();
+ void setupBackendObject();
+
+ VideoWidgetPrivate(VideoWidget *parent)
+ : layout(parent),
+ aspectRatio(VideoWidget::AspectRatioAuto),
+ scaleMode(VideoWidget::FitInView),
+ brightness(0),
+ contrast(0),
+ hue(0),
+ saturation(0)
+ {
+ layout.setMargin(0);
+ }
+
+ QHBoxLayout layout;
+ VideoWidget::AspectRatio aspectRatio;
+ VideoWidget::ScaleMode scaleMode;
+ Qt::WindowFlags changeFlags;
+
+ qreal brightness;
+ qreal contrast;
+ qreal hue;
+ qreal saturation;
+
+ private:
+ void init();
+};
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+#endif // VIDEOWIDGET_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/videowidgetinterface.h b/src/3rdparty/phonon/phonon/videowidgetinterface.h
new file mode 100644
index 0000000..0c33956
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/videowidgetinterface.h
@@ -0,0 +1,78 @@
+/* This file is part of the KDE project
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_VIDEOWIDGETINTERFACE_H
+#define PHONON_VIDEOWIDGETINTERFACE_H
+
+#include "videowidget.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VIDEO
+
+namespace Phonon
+{
+class VideoWidgetInterface
+{
+ public:
+ virtual ~VideoWidgetInterface() {}
+
+ virtual Phonon::VideoWidget::AspectRatio aspectRatio() const = 0;
+ virtual void setAspectRatio(Phonon::VideoWidget::AspectRatio) = 0;
+ virtual qreal brightness() const = 0;
+ virtual void setBrightness(qreal) = 0;
+ virtual Phonon::VideoWidget::ScaleMode scaleMode() const = 0;
+ virtual void setScaleMode(Phonon::VideoWidget::ScaleMode) = 0;
+ virtual qreal contrast() const = 0;
+ virtual void setContrast(qreal) = 0;
+ virtual qreal hue() const = 0;
+ virtual void setHue(qreal) = 0;
+ virtual qreal saturation() const = 0;
+ virtual void setSaturation(qreal) = 0;
+ virtual QWidget *widget() = 0;
+//X virtual int overlayCapabilities() const = 0;
+//X virtual bool createOverlay(QWidget *widget, int type) = 0;
+};
+
+class VideoWidgetInterface44 : public VideoWidgetInterface
+{
+ public:
+ virtual QImage snapshot() const = 0;
+};
+}
+
+#ifdef PHONON_BACKEND_VERSION_4_4
+namespace Phonon { typedef VideoWidgetInterface44 VideoWidgetInterfaceLatest; }
+#else
+namespace Phonon { typedef VideoWidgetInterface VideoWidgetInterfaceLatest; }
+#endif
+
+Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface44, "VideoWidgetInterface44.phonon.kde.org")
+Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface, "VideoWidgetInterface3.phonon.kde.org")
+
+#endif //QT_NO_PHONON_VIDEO
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_VIDEOWIDGETINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/volumefadereffect.cpp b/src/3rdparty/phonon/phonon/volumefadereffect.cpp
new file mode 100644
index 0000000..15d34ee
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/volumefadereffect.cpp
@@ -0,0 +1,108 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "volumefadereffect.h"
+#include "volumefadereffect_p.h"
+#include "volumefaderinterface.h"
+#include "factory_p.h"
+
+#include <QtCore/qmath.h>
+
+#define PHONON_CLASSNAME VolumeFaderEffect
+#define PHONON_INTERFACENAME VolumeFaderInterface
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+
+namespace Phonon
+{
+PHONON_HEIR_IMPL(Effect)
+
+PHONON_INTERFACE_GETTER(float, volume, d->currentVolume)
+PHONON_INTERFACE_SETTER(setVolume, currentVolume, float)
+PHONON_INTERFACE_GETTER(Phonon::VolumeFaderEffect::FadeCurve, fadeCurve, d->fadeCurve)
+PHONON_INTERFACE_SETTER(setFadeCurve, fadeCurve, Phonon::VolumeFaderEffect::FadeCurve)
+
+#ifndef PHONON_LOG10OVER20
+#define PHONON_LOG10OVER20
+static const double log10over20 = 0.1151292546497022842; // ln(10) / 20
+#endif // PHONON_LOG10OVER20
+
+double VolumeFaderEffect::volumeDecibel() const
+{
+ return log(volume()) / log10over20;
+}
+
+void VolumeFaderEffect::setVolumeDecibel(double newVolumeDecibel)
+{
+ setVolume(exp(newVolumeDecibel * log10over20));
+}
+
+
+void VolumeFaderEffect::fadeIn(int fadeTime)
+{
+ fadeTo(1.0, fadeTime);
+}
+
+void VolumeFaderEffect::fadeOut(int fadeTime)
+{
+ fadeTo(0.0, fadeTime);
+}
+
+void VolumeFaderEffect::fadeTo(float volume, int fadeTime)
+{
+ K_D(VolumeFaderEffect);
+ if (k_ptr->backendObject())
+ INTERFACE_CALL(fadeTo(volume, fadeTime));
+ else
+ d->currentVolume = volume;
+}
+
+bool VolumeFaderEffectPrivate::aboutToDeleteBackendObject()
+{
+ if (m_backendObject) {
+ currentVolume = pINTERFACE_CALL(volume());
+ fadeCurve = pINTERFACE_CALL(fadeCurve());
+ }
+ return true;
+}
+
+void VolumeFaderEffectPrivate::setupBackendObject()
+{
+ Q_ASSERT(m_backendObject);
+
+ // set up attributes
+ pINTERFACE_CALL(setVolume(currentVolume));
+ pINTERFACE_CALL(setFadeCurve(fadeCurve));
+}
+}
+
+
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+
+QT_END_NAMESPACE
+
+#include "moc_volumefadereffect.cpp"
+
+#undef PHONON_CLASSNAME
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/volumefadereffect.h b/src/3rdparty/phonon/phonon/volumefadereffect.h
new file mode 100644
index 0000000..528bffa
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/volumefadereffect.h
@@ -0,0 +1,178 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_VOLUMEFADEREFFECT_H
+#define PHONON_VOLUMEFADEREFFECT_H
+
+#include "phonon_export.h"
+#include "effect.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+
+namespace Phonon
+{
+ class VolumeFaderEffectPrivate;
+
+ /** \class VolumeFaderEffect volumefadereffect.h Phonon/VolumeFaderEffect
+ * Audio effect to gradually fade the audio volume.
+ *
+ * This effect differs from gradually changing the output volume in that
+ * a dedicated effect can change the volume in the smallest possible
+ * steps while every other volume control will make more or less
+ * noticeable steps.
+ *
+ * \ingroup PhononEffects
+ * \author Matthias Kretz <kretz@kde.org>
+ * \see AudioOutput::volume
+ */
+ class PHONON_EXPORT VolumeFaderEffect : public Effect
+ {
+ Q_OBJECT
+ K_DECLARE_PRIVATE(VolumeFaderEffect)
+ PHONON_HEIR(VolumeFaderEffect)
+ Q_ENUMS(FadeCurve)
+ /**
+ * This is the current volume of the output as voltage factor.
+ * Setting this property changes the volume immediately.
+ *
+ * 1.0 means 100%, 0.5 means 50% voltage/25% power, 0.0 means 0%
+ *
+ * \see volumeDecibel
+ */
+ Q_PROPERTY(float volume READ volume WRITE setVolume)
+ /**
+ * This is the current volume of the output in decibel.
+ * Setting this property changes the volume immediately.
+ *
+ * 0 dB means no change in volume, -6dB means an attenuation of the
+ * voltage to 50% and an attenuation of the power to 25%, -inf dB means
+ * silence.
+ *
+ * \see volume
+ */
+ Q_PROPERTY(double volumeDecibel READ volumeDecibel WRITE setVolumeDecibel)
+ /**
+ * This property holds the fade curve to be used for the fadeIn(), fadeOut()
+ * and fadeTo() slots.
+ *
+ * Defaults to Fade3Decibel.
+ *
+ * \see FadeCurve
+ */
+ Q_PROPERTY(FadeCurve fadeCurve READ fadeCurve WRITE setFadeCurve)
+ public:
+ /**
+ * Determines the curve of the volume change.
+ */
+ enum FadeCurve {
+ /**
+ * "Crossfade curve" / "fast" fade out
+ *
+ * Often the best fade for a crossfade, as after half of the
+ * time the volume reached -3dB. This means that half the
+ * possible power (which is proportional to the square of the
+ * voltage) is reached. Summed, the maximum power of two audio
+ * signals fading with a -3dB curve will always be equal.
+ *
+ * For fading in or out the -3dB curve is too abrupt in the end.
+ *
+ * This is the default fade curve.
+ */
+ Fade3Decibel,
+ /**
+ * "Linear" fade out
+ *
+ * With a -6dB fade curve after half of the fading time -6dB has
+ * been reached. -6dB is equal to half of the voltage meaning
+ * that the voltage multiplier changes linearly from the start
+ * of the fade to the end.
+ */
+ Fade6Decibel,
+ /**
+ * "slow" fade out
+ *
+ * After half of the fade time -9dB are reached. So the fade is
+ * fast in the beginning and slow in the end. This is a good
+ * fade for ending music.
+ */
+ Fade9Decibel,
+ /**
+ * more extreme version of the -9dB fade
+ */
+ Fade12Decibel
+ };
+
+ float volume() const;
+ double volumeDecibel() const;
+
+ FadeCurve fadeCurve() const;
+
+ public Q_SLOTS:
+ /**
+ * Tells the Fader to change the volume from the current volume to 100%
+ * in \p fadeTime milliseconds.
+ * Short for \c fadeTo(1.0, fadeTime).
+ *
+ * \param fadeTime the fade duration in milliseconds
+ *
+ * \see fadeTo
+ * \see volume
+ */
+ void fadeIn(int fadeTime);
+
+ /**
+ * Tells the Fader to change the volume from the current volume to 0%
+ * in \p fadeTime milliseconds.
+ * Short for \c fadeTo(0.0, fadeTime).
+ *
+ * \param fadeTime the fade duration in milliseconds
+ *
+ * \see fadeTo
+ */
+ void fadeOut(int fadeTime);
+
+ void setVolume(float volume);
+ void setVolumeDecibel(double volumeDecibel);
+
+ void setFadeCurve(FadeCurve curve);
+
+ /**
+ * Tells the Fader to change the volume from the current value to
+ * \p volume in \p fadeTime milliseconds
+ *
+ * \see fadeIn
+ * \see fadeOut
+ */
+ void fadeTo(float volume, int fadeTime);
+ };
+} //namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 tw=80
+#endif // PHONON_VOLUMEFADEREFFECT_H
diff --git a/src/3rdparty/phonon/phonon/volumefadereffect_p.h b/src/3rdparty/phonon/phonon/volumefadereffect_p.h
new file mode 100644
index 0000000..7937e63
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/volumefadereffect_p.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_VOLUMEFADEREFFECT_P_H
+#define PHONON_VOLUMEFADEREFFECT_P_H
+
+#include "volumefadereffect.h"
+#include "effect_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+
+namespace Phonon
+{
+class VolumeFaderEffectPrivate : public EffectPrivate
+{
+ Q_DECLARE_PUBLIC(VolumeFaderEffect)
+ PHONON_PRIVATECLASS
+ protected:
+ VolumeFaderEffectPrivate()
+ : currentVolume(1.0)
+ , fadeCurve(VolumeFaderEffect::Fade3Decibel)
+ {
+ // invalid EffectDescription
+ // ############# parameter functions are incorrect
+ }
+
+ float currentVolume;
+ VolumeFaderEffect::FadeCurve fadeCurve;
+};
+}
+
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+
+QT_END_NAMESPACE
+
+#endif // PHONON_VOLUMEFADEREFFECT_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/volumefaderinterface.h b/src/3rdparty/phonon/phonon/volumefaderinterface.h
new file mode 100644
index 0000000..8c6e3a4
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/volumefaderinterface.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). <thierry.bastian@trolltech.com>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_VOLUMEFADERINTERFACE_H
+#define PHONON_VOLUMEFADERINTERFACE_H
+
+#include "volumefadereffect.h"
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
+
+namespace Phonon
+{
+class VolumeFaderInterface
+{
+ public:
+ virtual ~VolumeFaderInterface() {}
+
+ virtual float volume() const { return 1.0; }
+ virtual void setVolume(float) {}
+ virtual Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const {
+ return VolumeFaderEffect::Fade3Decibel;
+ }
+ virtual void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve) {}
+ virtual void fadeTo(float, int) {}
+};
+}
+
+Q_DECLARE_INTERFACE(Phonon::VolumeFaderInterface, "VolumeFaderInterface4.phonon.kde.org")
+
+#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_VOLUMEFADERINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/volumeslider.cpp b/src/3rdparty/phonon/phonon/volumeslider.cpp
new file mode 100644
index 0000000..00970c1
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/volumeslider.cpp
@@ -0,0 +1,262 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "volumeslider.h"
+#include "volumeslider_p.h"
+#include "audiooutput.h"
+#include "phonondefs_p.h"
+#include "phononnamespace_p.h"
+#include "factory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMESLIDER
+
+namespace Phonon
+{
+VolumeSlider::VolumeSlider(QWidget *parent)
+ : QWidget(parent),
+ k_ptr(new VolumeSliderPrivate(this))
+{
+ K_D(VolumeSlider);
+#ifndef QT_NO_TOOLTIP
+ setToolTip(tr("Volume: %1%").arg(100));
+#endif
+#ifndef QT_NO_WHATSTHIS
+ setWhatsThis(tr("Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%").arg(100));
+#endif
+
+ connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_sliderChanged(int)));
+ connect(&d->muteButton, SIGNAL(clicked()), SLOT(_k_buttonClicked()));
+
+ setFocusProxy(&d->slider);
+}
+
+VolumeSlider::VolumeSlider(AudioOutput *output, QWidget *parent)
+ : QWidget(parent),
+ k_ptr(new VolumeSliderPrivate(this))
+{
+ K_D(VolumeSlider);
+#ifndef QT_NO_TOOLTIP
+ setToolTip(tr("Volume: %1%").arg(100));
+#endif
+#ifndef QT_NO_WHATSTHIS
+ setWhatsThis(tr("Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%").arg(100));
+#endif
+
+ connect(&d->slider, SIGNAL(valueChanged(int)), SLOT(_k_sliderChanged(int)));
+ connect(&d->muteButton, SIGNAL(clicked()), SLOT(_k_buttonClicked()));
+
+ if (output) {
+ d->output = output;
+ d->slider.setValue(qRound(100 * output->volume()));
+ d->slider.setEnabled(true);
+ d->muteButton.setEnabled(true);
+ connect(output, SIGNAL(volumeChanged(qreal)), SLOT(_k_volumeChanged(qreal)));
+ connect(output, SIGNAL(mutedChanged(bool)), SLOT(_k_mutedChanged(bool)));
+ }
+
+ setFocusProxy(&d->slider);
+}
+
+VolumeSlider::~VolumeSlider()
+{
+ delete k_ptr;
+}
+
+bool VolumeSlider::isMuteVisible() const
+{
+ return !k_ptr->muteButton.isHidden();
+}
+
+void VolumeSlider::setMuteVisible(bool visible)
+{
+ k_ptr->muteButton.setVisible(visible);
+}
+
+QSize VolumeSlider::iconSize() const
+{
+ return k_ptr->muteButton.iconSize();
+}
+
+void VolumeSlider::setIconSize(const QSize &iconSize)
+{
+ pDebug() << Q_FUNC_INFO << iconSize;
+ k_ptr->muteButton.setIconSize(iconSize);
+}
+
+qreal VolumeSlider::maximumVolume() const
+{
+ return k_ptr->slider.maximum() * 0.01;
+}
+
+void VolumeSlider::setMaximumVolume(qreal volume)
+{
+ int max = static_cast<int>(volume * 100);
+ k_ptr->slider.setMaximum(max);
+#ifndef QT_NO_WHATSTHIS
+ setWhatsThis(tr("Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%")
+ .arg(max));
+#endif
+}
+
+Qt::Orientation VolumeSlider::orientation() const
+{
+ return k_ptr->slider.orientation();
+}
+
+void VolumeSlider::setOrientation(Qt::Orientation o)
+{
+ K_D(VolumeSlider);
+ Qt::Alignment align = (o == Qt::Horizontal ? Qt::AlignVCenter : Qt::AlignHCenter);
+ d->layout.setAlignment(&d->muteButton, align);
+ d->layout.setAlignment(&d->slider, align);
+ d->layout.setDirection(o == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
+ d->slider.setOrientation(o);
+}
+
+AudioOutput *VolumeSlider::audioOutput() const
+{
+ K_D(const VolumeSlider);
+ return d->output;
+}
+
+void VolumeSlider::setAudioOutput(AudioOutput *output)
+{
+ K_D(VolumeSlider);
+ if (d->output) {
+ disconnect(d->output, 0, this, 0);
+ }
+ d->output = output;
+ if (output) {
+ d->slider.setValue(qRound(100 * output->volume()));
+ d->slider.setEnabled(true);
+ d->muteButton.setEnabled(true);
+
+ d->_k_volumeChanged(output->volume());
+ d->_k_mutedChanged(output->isMuted());
+
+ connect(output, SIGNAL(volumeChanged(qreal)), SLOT(_k_volumeChanged(qreal)));
+ connect(output, SIGNAL(mutedChanged(bool)), SLOT(_k_mutedChanged(bool)));
+ } else {
+ d->slider.setValue(100);
+ d->slider.setEnabled(false);
+ d->muteButton.setEnabled(false);
+ }
+}
+
+void VolumeSliderPrivate::_k_buttonClicked()
+{
+ if (output) {
+ output->setMuted(!output->isMuted());
+ } else {
+ slider.setEnabled(false);
+ muteButton.setEnabled(false);
+ }
+}
+
+void VolumeSliderPrivate::_k_mutedChanged(bool muted)
+{
+#ifndef QT_NO_TOOLTIP
+ Q_Q(VolumeSlider);
+#endif
+ if (muted) {
+#ifndef QT_NO_TOOLTIP
+ q->setToolTip(VolumeSlider::tr("Muted"));
+#endif
+ muteButton.setIcon(mutedIcon);
+ } else {
+#ifndef QT_NO_TOOLTIP
+ q->setToolTip(VolumeSlider::tr("Volume: %1%").arg(static_cast<int>(output->volume() * 100.0)));
+#endif
+ muteButton.setIcon(volumeIcon);
+ }
+}
+
+void VolumeSliderPrivate::_k_sliderChanged(int value)
+{
+#ifndef QT_NO_TOOLTIP
+ Q_Q(VolumeSlider);
+#endif
+
+ if (output) {
+#ifndef QT_NO_TOOLTIP
+ if (!output->isMuted()) {
+ q->setToolTip(VolumeSlider::tr("Volume: %1%").arg(value));
+ }
+#endif
+
+ ignoreVolumeChange = true;
+ output->setVolume((static_cast<qreal>(value)) * 0.01);
+ ignoreVolumeChange = false;
+ } else {
+ slider.setEnabled(false);
+ muteButton.setEnabled(false);
+ }
+}
+
+void VolumeSliderPrivate::_k_volumeChanged(qreal value)
+{
+ if (!ignoreVolumeChange) {
+ slider.setValue(qRound(100 * value));
+ }
+}
+
+bool VolumeSlider::hasTracking() const
+{
+ return k_ptr->slider.hasTracking();
+}
+
+void VolumeSlider::setTracking(bool tracking)
+{
+ k_ptr->slider.setTracking(tracking);
+}
+
+int VolumeSlider::pageStep() const
+{
+ return k_ptr->slider.pageStep();
+}
+
+void VolumeSlider::setPageStep(int milliseconds)
+{
+ k_ptr->slider.setPageStep(milliseconds);
+}
+
+int VolumeSlider::singleStep() const
+{
+ return k_ptr->slider.singleStep();
+}
+
+void VolumeSlider::setSingleStep(int milliseconds)
+{
+ k_ptr->slider.setSingleStep(milliseconds);
+}
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMESLIDER
+
+QT_END_NAMESPACE
+
+#include "moc_volumeslider.cpp"
+
+// vim: sw=4 et
diff --git a/src/3rdparty/phonon/phonon/volumeslider.h b/src/3rdparty/phonon/phonon/volumeslider.h
new file mode 100644
index 0000000..f5ef34f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/volumeslider.h
@@ -0,0 +1,155 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_UI_VOLUMESLIDER_H
+#define PHONON_UI_VOLUMESLIDER_H
+
+#include "phonon_export.h"
+#include "phonondefs.h"
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMESLIDER
+
+namespace Phonon
+{
+class AudioOutput;
+class VolumeSliderPrivate;
+
+/** \class VolumeSlider volumeslider.h Phonon/VolumeSlider
+ * \short Widget providing a slider to control the volume of an AudioOutput.
+ *
+ * \ingroup PhononWidgets
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+class PHONON_EXPORT VolumeSlider : public QWidget
+{
+ Q_OBJECT
+ K_DECLARE_PRIVATE(VolumeSlider)
+ /**
+ * This property holds the maximum volume that can be set with this slider.
+ *
+ * By default the maximum value is 1.0 (100%).
+ */
+ Q_PROPERTY(qreal maximumVolume READ maximumVolume WRITE setMaximumVolume)
+ /**
+ * This property holds the orientation of the slider.
+ *
+ * The orientation must be Qt::Vertical (the default) or Qt::Horizontal.
+ */
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+
+ /**
+ * This property holds whether slider tracking is enabled.
+ *
+ * If tracking is enabled (the default), the volume changes
+ * while the slider is being dragged. If tracking is
+ * disabled, the volume changes only when the user
+ * releases the slider.
+ */
+ Q_PROPERTY(bool tracking READ hasTracking WRITE setTracking)
+
+ /**
+ * This property holds the page step.
+ *
+ * The larger of two natural steps that a slider provides and
+ * typically corresponds to the user pressing PageUp or PageDown.
+ *
+ * Defaults to 5 (5% of the voltage).
+ */
+ Q_PROPERTY(int pageStep READ pageStep WRITE setPageStep)
+
+ /**
+ * This property holds the single step.
+ *
+ * The smaller of two natural steps that a slider provides and
+ * typically corresponds to the user pressing an arrow key.
+ *
+ * Defaults to 1 (1% of the voltage).
+ */
+ Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep)
+
+ /**
+ * This property holds whether the mute button/icon next to the slider is visible.
+ *
+ * By default the mute button/icon is visible.
+ */
+ Q_PROPERTY(bool muteVisible READ isMuteVisible WRITE setMuteVisible)
+
+ /**
+ * \brief the icon size used for the mute button/icon.
+ *
+ * The default size is defined by the GUI style.
+ */
+ Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
+ public:
+ /**
+ * Constructs a new volume slider with a \p parent.
+ */
+ explicit VolumeSlider(QWidget *parent = 0);
+ explicit VolumeSlider(AudioOutput *, QWidget *parent = 0);
+ ~VolumeSlider();
+
+ bool hasTracking() const;
+ void setTracking(bool tracking);
+ int pageStep() const;
+ void setPageStep(int milliseconds);
+ int singleStep() const;
+ void setSingleStep(int milliseconds);
+ bool isMuteVisible() const;
+ QSize iconSize() const;
+ qreal maximumVolume() const;
+ Qt::Orientation orientation() const;
+ AudioOutput *audioOutput() const;
+
+ public Q_SLOTS:
+ void setMaximumVolume(qreal);
+ void setOrientation(Qt::Orientation);
+ void setMuteVisible(bool);
+ void setIconSize(const QSize &size);
+
+ /**
+ * Sets the audio output object to be controlled by this slider.
+ */
+ void setAudioOutput(Phonon::AudioOutput *);
+
+ protected:
+ VolumeSliderPrivate *const k_ptr;
+
+ private:
+ Q_PRIVATE_SLOT(k_ptr, void _k_sliderChanged(int))
+ Q_PRIVATE_SLOT(k_ptr, void _k_volumeChanged(qreal))
+ Q_PRIVATE_SLOT(k_ptr, void _k_mutedChanged(bool))
+ Q_PRIVATE_SLOT(k_ptr, void _k_buttonClicked())
+};
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMESLIDER
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+// vim: sw=4 ts=4 et
+#endif // PHONON_UI_VOLUMESLIDER_H
diff --git a/src/3rdparty/phonon/phonon/volumeslider_p.h b/src/3rdparty/phonon/phonon/volumeslider_p.h
new file mode 100644
index 0000000..623275f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/volumeslider_p.h
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef VOLUMESLIDER_P_H
+#define VOLUMESLIDER_P_H
+
+#include "volumeslider.h"
+#include "swiftslider_p.h"
+#include <QtGui/QBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QPixmap>
+#include <QtGui/QToolButton>
+#include "factory_p.h"
+#include "audiooutput.h"
+#include <QtGui/QIcon>
+#include <QtCore/QPointer>
+#include "platform_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PHONON_VOLUMESLIDER
+
+namespace Phonon
+{
+class VolumeSliderPrivate
+{
+ Q_DECLARE_PUBLIC(VolumeSlider)
+ protected:
+ VolumeSliderPrivate(VolumeSlider *parent)
+ : q_ptr(parent),
+ layout(QBoxLayout::LeftToRight, parent),
+ slider(Qt::Horizontal, parent),
+ muteButton(parent),
+ volumeIcon(Platform::icon(QLatin1String("player-volume"), parent->style())),
+ mutedIcon(Platform::icon(QLatin1String("player-volume-muted"), parent->style())),
+ output(0),
+ ignoreVolumeChange(false)
+ {
+ slider.setRange(0, 100);
+ slider.setPageStep(5);
+ slider.setSingleStep(1);
+
+ muteButton.setIcon(volumeIcon);
+ muteButton.setAutoRaise(true);
+ layout.setMargin(0);
+ layout.setSpacing(2);
+ layout.addWidget(&muteButton, 0, Qt::AlignVCenter);
+ layout.addWidget(&slider, 0, Qt::AlignVCenter);
+
+ slider.setEnabled(false);
+ muteButton.setEnabled(false);
+
+ if (volumeIcon.isNull()) {
+ muteButton.setVisible(false);
+ }
+ }
+
+ VolumeSlider *q_ptr;
+
+ void _k_sliderChanged(int);
+ void _k_volumeChanged(qreal);
+ void _k_mutedChanged(bool);
+ void _k_buttonClicked();
+
+ private:
+ QBoxLayout layout;
+ SwiftSlider slider;
+ QToolButton muteButton;
+ QIcon volumeIcon;
+ QIcon mutedIcon;
+
+ QPointer<AudioOutput> output;
+ bool ignoreVolumeChange;
+};
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMESLIDER
+
+QT_END_NAMESPACE
+
+#endif // VOLUMESLIDER_P_H
+// vim: sw=4 sts=4 et tw=100
diff --git a/src/3rdparty/phonon/qt7/CMakeLists.txt b/src/3rdparty/phonon/qt7/CMakeLists.txt
new file mode 100644
index 0000000..5310be1
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/CMakeLists.txt
@@ -0,0 +1,58 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+#
+# This library 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, either version 2 or 3 of the License.
+#
+# This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+project(phonon-qt7)
+include(ConfigureChecks.cmake)
+
+include_directories(${OPENGL_INCLUDE_DIR})
+
+if (BUILD_PHONON_QT7)
+ set(phonon_qt7_SRCS
+ quicktimevideoplayer.mm
+ backendheader.mm
+ medianodevideopart.mm
+ medianodeevent.mm
+ audiooutput.mm
+ backendinfo.mm
+ audiosplitter.mm
+ audioeffects.mm
+ quicktimestreamreader.mm
+ medianode.mm
+ backend.mm
+ mediaobject.mm
+ mediaobjectaudionode.mm
+ audiomixer.mm
+ quicktimeaudioplayer.mm
+ videoframe.mm
+ quicktimemetadata.mm
+ audiodevice.mm
+ audioconnection.mm
+ audiograph.mm
+ audionode.mm
+ videowidget.mm
+ )
+
+ automoc4_add_library(phonon_qt7 MODULE ${phonon_qt7_SRCS})
+ target_link_libraries(phonon_qt7
+ ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY}
+ ${PHONON_LIBS}
+ "-framework QuickTime"
+ "-framework AudioUnit"
+ "-framework AudioToolbox"
+ "-framework CoreAudio"
+ "-framework QuartzCore"
+ "-framework QTKit"
+ )
+ install(TARGETS phonon_qt7 DESTINATION ${PLUGIN_INSTALL_DIR})
+
+endif (BUILD_PHONON_QT7)
diff --git a/src/3rdparty/phonon/qt7/ConfigureChecks.cmake b/src/3rdparty/phonon/qt7/ConfigureChecks.cmake
new file mode 100644
index 0000000..9644867
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/ConfigureChecks.cmake
@@ -0,0 +1,16 @@
+# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+#
+# This library 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, either version 2 or 3 of the License.
+#
+# This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+
+# Find the frameworks if necessary
+set(BUILD_PHONON_QT7 TRUE)
diff --git a/src/3rdparty/phonon/qt7/audioconnection.h b/src/3rdparty/phonon/qt7/audioconnection.h
new file mode 100644
index 0000000..2129744
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioconnection.h
@@ -0,0 +1,84 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AudioConnection_H
+#define Phonon_QT7_AudioConnection_H
+
+#include <QtCore/QObject>
+#include "backendheader.h"
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class MediaNode;
+ class AudioNode;
+ class AudioGraph;
+
+ class AudioConnection {
+ public:
+ AudioConnection();
+ AudioConnection(MediaNode *sink);
+ AudioConnection(MediaNode *source, int output, MediaNode *sink, int input);
+
+ AudioConnection(AudioNode *sink);
+ AudioConnection(AudioNode *source, int output, AudioNode *sink, int input);
+
+ ~AudioConnection();
+
+ bool connect(AudioGraph *graph);
+ bool disconnect(AudioGraph *graph);
+
+ bool updateStreamSpecification();
+ bool isBetween(MediaNode *source, MediaNode *sink);
+ bool isValid();
+ bool isSinkOnly();
+ void freeMemoryAllocations();
+ void invalidate();
+
+ MediaNode *m_source;
+ AudioNode *m_sourceAudioNode;
+ int m_sourceOutputBus;
+
+ MediaNode *m_sink;
+ AudioNode *m_sinkAudioNode;
+ int m_sinkInputBus;
+
+ AudioChannelLayout *m_sourceChannelLayout;
+ UInt32 m_sourceChannelLayoutSize;
+
+ AudioChannelLayout *m_sinkChannelLayout;
+ UInt32 m_sinkChannelLayoutSize;
+
+ AudioStreamBasicDescription m_sourceStreamDescription;
+ AudioStreamBasicDescription m_sinkStreamDescription;
+
+ bool m_hasSourceSpecification;
+ bool m_hasSinkSpecification;
+ bool m_connected;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AudioConnection_H
diff --git a/src/3rdparty/phonon/qt7/audioconnection.mm b/src/3rdparty/phonon/qt7/audioconnection.mm
new file mode 100644
index 0000000..39b8b30
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioconnection.mm
@@ -0,0 +1,152 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audioconnection.h"
+#include "medianode.h"
+#include "audionode.h"
+#include "audiograph.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+ AudioConnection::AudioConnection()
+ : m_source(0), m_sourceAudioNode(0), m_sourceOutputBus(0),
+ m_sink(0), m_sinkAudioNode(0), m_sinkInputBus(0),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0),
+ m_hasSourceSpecification(false), m_hasSinkSpecification(false), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(MediaNode *source, int output, MediaNode *sink, int input)
+ : m_source(source), m_sourceAudioNode(source->m_audioNode), m_sourceOutputBus(output),
+ m_sink(sink), m_sinkAudioNode(sink->m_audioNode), m_sinkInputBus(input),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0),
+ m_hasSourceSpecification(false), m_hasSinkSpecification(false), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(MediaNode *sink)
+ : m_source(0), m_sourceAudioNode(0), m_sourceOutputBus(0),
+ m_sink(sink), m_sinkAudioNode(sink->m_audioNode), m_sinkInputBus(0),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(AudioNode *source, int output, AudioNode *sink, int input)
+ : m_source(0), m_sourceAudioNode(source), m_sourceOutputBus(output),
+ m_sink(0), m_sinkAudioNode(sink), m_sinkInputBus(input),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0),
+ m_hasSourceSpecification(false), m_hasSinkSpecification(false), m_connected(false)
+ {}
+
+ AudioConnection::AudioConnection(AudioNode *sink)
+ : m_source(0), m_sourceAudioNode(0), m_sourceOutputBus(0),
+ m_sink(0), m_sinkAudioNode(sink), m_sinkInputBus(0),
+ m_sourceChannelLayout(0), m_sinkChannelLayout(0), m_connected(false)
+ {}
+
+ AudioConnection::~AudioConnection()
+ {
+ freeMemoryAllocations();
+ }
+
+ void AudioConnection::freeMemoryAllocations()
+ {
+ if (m_sinkChannelLayout && m_sourceChannelLayout != m_sinkChannelLayout)
+ free(m_sinkChannelLayout);
+ if (m_sourceChannelLayout)
+ free(m_sourceChannelLayout);
+ m_sinkChannelLayout = 0;
+ m_sourceChannelLayout = 0;
+ }
+
+ bool AudioConnection::updateStreamSpecification()
+ {
+ m_hasSourceSpecification = false;
+ m_hasSinkSpecification = false;
+ freeMemoryAllocations();
+
+ bool updateOk;
+ if (m_sourceAudioNode){
+ updateOk = m_sourceAudioNode->fillInStreamSpecification(this, AudioNode::Source);
+ if (!updateOk)
+ return false;
+ updateOk = m_sourceAudioNode->setStreamSpecification(this, AudioNode::Source);
+ if (!updateOk)
+ return false;
+ }
+ updateOk = m_sinkAudioNode->fillInStreamSpecification(this, AudioNode::Sink);
+ if (!updateOk)
+ return false;
+ updateOk = m_sinkAudioNode->setStreamSpecification(this, AudioNode::Sink);
+ if (!updateOk)
+ return false;
+ return true;
+ }
+
+ bool AudioConnection::connect(AudioGraph *graph)
+ {
+ if (m_connected || !m_sourceAudioNode)
+ return true;
+
+ DEBUG_AUDIO_GRAPH("Connection" << int(this) << "connect"
+ << int(m_sourceAudioNode) << m_sourceOutputBus << "->"
+ << int(m_sinkAudioNode) << m_sinkInputBus)
+
+ AUNode sourceOut = m_sourceAudioNode->getOutputAUNode();
+ AUNode sinkIn = m_sinkAudioNode->getInputAUNode();
+ OSStatus err = AUGraphConnectNodeInput(graph->audioGraphRef(), sourceOut, m_sourceOutputBus, sinkIn, m_sinkInputBus);
+ m_connected = (err == noErr) ? true : false;
+ return m_connected;
+ }
+
+ bool AudioConnection::disconnect(AudioGraph *graph)
+ {
+ if (!m_connected || !m_sourceAudioNode)
+ return true;
+
+ DEBUG_AUDIO_GRAPH("Connection" << int(this) << "disconnect"
+ << int(m_sourceAudioNode) << m_sourceOutputBus << "->"
+ << int(m_sinkAudioNode) << m_sinkInputBus)
+
+ AUNode sinkIn = m_sinkAudioNode->getInputAUNode();
+ AUGraphDisconnectNodeInput(graph->audioGraphRef(), sinkIn, m_sinkInputBus);
+ m_connected = false;
+ return true;
+ }
+
+ void AudioConnection::invalidate()
+ {
+ m_connected = false;
+ }
+
+ bool AudioConnection::isBetween(MediaNode *source, MediaNode *sink){
+ return (source == m_source) && (sink == m_sink);
+ }
+
+ bool AudioConnection::isValid(){
+ return (m_sourceAudioNode != 0);
+ }
+
+ bool AudioConnection::isSinkOnly(){
+ return (m_sourceAudioNode == 0) && (m_sinkAudioNode != 0);
+ }
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiodevice.h b/src/3rdparty/phonon/qt7/audiodevice.h
new file mode 100644
index 0000000..36e937e
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiodevice.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIODEVICE_H
+#define Phonon_QT7_AUDIODEVICE_H
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioDevice
+ {
+ public:
+ enum Scope {In, Out};
+
+ static QList<AudioDeviceID> devices(Scope scope);
+ static AudioDeviceID defaultDevice(Scope scope);
+ static AudioDeviceID defaultSystemDevice(Scope scope);
+ static AudioDeviceID currentDevice(AudioUnit unit, Scope scope);
+ static bool setDevice(AudioUnit unit, AudioDeviceID deviceID, Scope scope);
+ static QString deviceName(AudioDeviceID deviceId);
+ static QString deviceSourceName(AudioDeviceID deviceID);
+ static QString deviceSourceNameElseDeviceName(AudioDeviceID deviceID);
+ static QString deviceNameElseDeviceSourceName(AudioDeviceID deviceID);
+ static QString deviceUID(AudioDeviceID deviceID);
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIODEVICE_H
diff --git a/src/3rdparty/phonon/qt7/audiodevice.mm b/src/3rdparty/phonon/qt7/audiodevice.mm
new file mode 100644
index 0000000..3aae0ee
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiodevice.mm
@@ -0,0 +1,176 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiodevice.h"
+#include "audiograph.h"
+#include <QtCore/QVector>
+#include "backendheader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QList<AudioDeviceID> AudioDevice::devices(Scope scope)
+{
+ QList<AudioDeviceID> devices;
+
+ // Insert the default device explicit
+ if (AudioDeviceID defdev = defaultDevice(scope))
+ devices << defdev;
+
+ // How many input/output devices are awailable:
+ UInt32 deviceCount = 0;
+ OSStatus err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &deviceCount, 0);
+ BACKEND_ASSERT3(err == noErr, "Could not get number of audio devices awailable.", FATAL_ERROR, devices)
+
+ // Get list of all devices:
+ AudioDeviceID deviceArray[deviceCount];
+ err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &deviceCount, &deviceArray);
+ BACKEND_ASSERT3(err == noErr, "Could not get audio devices list.", FATAL_ERROR, devices)
+
+ for (uint i=0; i<deviceCount; i++){
+ if (!devices.contains(deviceArray[i])){
+ // Check if the current device is input or output:
+ UInt32 size;
+ err = AudioDeviceGetPropertyInfo(deviceArray[i], 0, scope == In, kAudioDevicePropertyStreams, &size, 0);
+ if (err == noErr && size > 0)
+ devices << deviceArray[i];
+ }
+ }
+ return devices;
+}
+
+AudioDeviceID AudioDevice::defaultSystemDevice(Scope scope)
+{
+ ARGUMENT_UNSUPPORTED(scope, In, NORMAL_ERROR, 0)
+ AudioDeviceID deviceID = 0;
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultSystemOutputDevice, &size, &deviceID);
+ BACKEND_ASSERT3(err == noErr, "Could not get default system audio device.", FATAL_ERROR, 0)
+ return deviceID;
+}
+
+AudioDeviceID AudioDevice::defaultDevice(Scope scope)
+{
+ ARGUMENT_UNSUPPORTED(scope, In, NORMAL_ERROR, 0)
+ AudioDeviceID deviceID = 0;
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &deviceID);
+ BACKEND_ASSERT3(err == noErr, "Could not get default output audio device.", FATAL_ERROR, 0)
+ return deviceID;
+}
+
+AudioDeviceID AudioDevice::currentDevice(AudioUnit /*unit*/, Scope /*scope*/)
+{
+ return 0;
+#if 0
+
+kAudioDevicePropertyDeviceUID
+
+ if (!m_audioUnit)
+ return 0;
+ AudioDeviceID deviceID = 0;
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioUnitGetProperty(m_audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &size, &deviceID);
+ BACKEND_ASSERT3(err == noErr, "Could not get current audio device.", FATAL_ERROR, 0)
+ return deviceID;
+#endif
+}
+
+bool AudioDevice::setDevice(AudioUnit unit, AudioDeviceID deviceID, Scope scope)
+{
+ ARGUMENT_UNSUPPORTED(scope, In, NORMAL_ERROR, false)
+ UInt32 size = sizeof(deviceID);
+ OSStatus err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceID, size);
+ if (err != noErr)
+ return false;
+ return true;
+}
+
+QString AudioDevice::deviceSourceNameElseDeviceName(AudioDeviceID deviceID)
+{
+ QString name = deviceSourceName(deviceID);
+ if (name.isEmpty())
+ name = deviceName(deviceID);
+ return name;
+}
+
+QString AudioDevice::deviceNameElseDeviceSourceName(AudioDeviceID deviceID)
+{
+ QString name = deviceName(deviceID);
+ if (name.isEmpty())
+ name = deviceSourceName(deviceID);
+ return name;
+}
+
+QString AudioDevice::deviceName(AudioDeviceID deviceID)
+{
+ if (!deviceID)
+ return QString();
+ CFStringRef cfString = 0;
+ UInt32 size = sizeof(cfString);
+ OSStatus err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDeviceNameCFString, &size, &cfString);
+ if (err != noErr)
+ return QString();
+ QString name = PhononCFString::toQString(cfString);
+ CFRelease(cfString);
+ return name;
+}
+
+QString AudioDevice::deviceSourceName(AudioDeviceID deviceID)
+{
+ if (!deviceID)
+ return QString();
+ UInt32 dataSource = 0;
+ UInt32 size = sizeof(dataSource);
+ OSStatus err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDataSource, &size, &dataSource);
+ if (err != noErr)
+ return QString();
+
+ CFStringRef cfName = 0;
+ AudioValueTranslation translation = {&dataSource, sizeof(dataSource), &cfName, sizeof(cfName)};
+ size = sizeof(translation);
+ err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDataSourceNameForIDCFString, &size, &translation);
+ if (err != noErr){
+ return QString();
+ }
+ QString name = PhononCFString::toQString(cfName);
+ CFRelease(cfName);
+ return name;
+}
+
+QString AudioDevice::deviceUID(AudioDeviceID deviceID)
+{
+ if (!deviceID)
+ return QString();
+
+ CFStringRef cfString = 0;
+ UInt32 size = sizeof(cfString);
+ OSStatus err = AudioDeviceGetProperty(deviceID, 0, 0, kAudioDevicePropertyDeviceUID, &size, &cfString);
+ if (err != noErr)
+ return QString();
+ QString uid = PhononCFString::toQString(cfString);
+ CFRelease(cfString);
+ return uid;
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audioeffects.h b/src/3rdparty/phonon/qt7/audioeffects.h
new file mode 100644
index 0000000..33fff1c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioeffects.h
@@ -0,0 +1,80 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOEFFECTS_H
+#define Phonon_QT7_AUDIOEFFECTS_H
+
+#include <QtCore/QVariant>
+#include <QtCore/QHash>
+#include <phonon/effectinterface.h>
+#include <phonon/effectparameter.h>
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioEffectAudioNode : public AudioNode
+ {
+ public:
+ AudioEffectAudioNode(int effectType);
+ int m_effectType;
+
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+
+ QVariant parameterValue(const Phonon::EffectParameter &value) const;
+ void setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue);
+
+ private:
+ QHash<int, float> m_alteredParameters;
+ };
+
+///////////////////////////////////////////////////////////////////////
+
+ class AudioEffect : public MediaNode, Phonon::EffectInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface)
+
+ public:
+ AudioEffect(int effectType, QObject *parent = 0);
+ AudioEffectAudioNode *m_audioNode;
+
+ QString name();
+ QString description();
+
+ // EffectInterface:
+ virtual QList<Phonon::EffectParameter> parameters() const;
+ virtual QVariant parameterValue(const Phonon::EffectParameter &parameter) const;
+ virtual void setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue);
+
+ static QList<int> effectList();
+
+ private:
+ Phonon::EffectParameter createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const;
+ };
+
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOEFFECTS_H
diff --git a/src/3rdparty/phonon/qt7/audioeffects.mm b/src/3rdparty/phonon/qt7/audioeffects.mm
new file mode 100644
index 0000000..b0ec3cc
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audioeffects.mm
@@ -0,0 +1,254 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audioeffects.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioEffectAudioNode::AudioEffectAudioNode(int effectType)
+ : AudioNode(1, 1), m_effectType(effectType)
+{
+}
+
+ComponentDescription AudioEffectAudioNode::getAudioNodeDescription() const
+{
+ ComponentDescription d;
+ d.componentType = kAudioUnitType_Effect;
+ d.componentSubType = m_effectType;
+ d.componentManufacturer = kAudioUnitManufacturer_Apple;
+ d.componentFlags = 0;
+ d.componentFlagsMask = 0;
+ return d;
+}
+
+void AudioEffectAudioNode::initializeAudioUnit()
+{
+ if (!m_audioUnit)
+ return;
+ foreach(int id, m_alteredParameters.keys()){
+ Float32 value = m_alteredParameters.value(id);
+ ComponentResult res = AudioUnitSetParameter(m_audioUnit, id, kAudioUnitScope_Global, 0, value, 0);
+ BACKEND_ASSERT2(res == noErr, "Could not initialize audio effect.", NORMAL_ERROR)
+ }
+}
+
+QVariant AudioEffectAudioNode::parameterValue(const Phonon::EffectParameter &parameter) const
+{
+ if (m_audioUnit){
+ Float32 value = 0;
+ AudioUnitGetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, &value);
+ return QVariant(value);
+ } else if (m_alteredParameters.contains(parameter.id())){
+ return QVariant(m_alteredParameters.value(parameter.id()));
+ } else {
+ // Use default value:
+ AudioUnit tmpAudioUnit;
+ ComponentDescription description = getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant())
+ OSErr err = OpenAComponent(component, &tmpAudioUnit);
+ BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant())
+ AudioUnitParameterInfo info;
+ UInt32 size = sizeof(info);
+ ComponentResult res = AudioUnitGetProperty(tmpAudioUnit,
+ kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, QVariant())
+ return QVariant(info.defaultValue);
+ }
+}
+
+void AudioEffectAudioNode::setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue)
+{
+ Float32 value = 0;
+ if (newValue.isValid()){
+ value = newValue.toDouble();
+ m_alteredParameters.insert(parameter.id(), value);
+ } else {
+ // Use default value:
+ m_alteredParameters.remove(parameter.id());
+ if (m_audioUnit){
+ AudioUnit tmpAudioUnit;
+ ComponentDescription description = getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT2(component, "Could not get parameters of audio effect.", NORMAL_ERROR)
+ OSErr err = OpenAComponent(component, &tmpAudioUnit);
+ BACKEND_ASSERT2(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR)
+ AudioUnitParameterInfo info;
+ UInt32 size = sizeof(info);
+ ComponentResult res = AudioUnitGetProperty(tmpAudioUnit,
+ kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size);
+ BACKEND_ASSERT2(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR)
+ value = info.defaultValue;
+ }
+ }
+
+ if (m_audioUnit){
+ ComponentResult res = AudioUnitSetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, value, 0);
+ BACKEND_ASSERT2(res == noErr, "Could not set effect parameter value.", NORMAL_ERROR)
+ }
+}
+
+///////////////////////////////////////////////////////////////////////
+
+AudioEffect::AudioEffect(int effectType, QObject *parent)
+ : MediaNode(AudioSink | AudioSource, 0, parent)
+{
+ m_audioNode = new AudioEffectAudioNode(effectType);
+ setAudioNode(m_audioNode);
+}
+
+QList<Phonon::EffectParameter> AudioEffect::parameters() const
+{
+ QList<Phonon::EffectParameter> effectList;
+ // Create a temporary audio unit:
+ AudioUnit audioUnit;
+ ComponentDescription description = m_audioNode->getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList)
+ OSErr err = OpenAComponent(component, &audioUnit);
+ BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList)
+
+ UInt32 size = 0;
+ // Get parameter count:
+ ComponentResult res = AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, 0, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter count from audio effect.", NORMAL_ERROR, effectList)
+ int paramCount = size / sizeof(AudioUnitParameterID);
+
+ // Get parameters:
+ AudioUnitParameterID parameters[paramCount];
+ res = AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, &parameters, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter list from audio effect.", NORMAL_ERROR, effectList)
+
+ for (int i=0; i<paramCount; ++i)
+ effectList << createParameter(audioUnit, parameters[i]);
+
+ CloseComponent(audioUnit);
+ return effectList;
+}
+
+QString AudioEffect::name()
+{
+ ComponentDescription description = m_audioNode->getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get audio effect name.", NORMAL_ERROR, QLatin1String("<unknown effect>"))
+
+ ComponentDescription cDesc;
+ Handle nameH = NewHandle(0);
+ GetComponentInfo(component, &cDesc, nameH, 0, 0);
+ HLock(nameH);
+ char *namePtr = *nameH;
+ int len = *namePtr++;
+ namePtr[len] = 0;
+ QString qsName = QString::fromUtf8(namePtr);
+ DisposeHandle(nameH);
+ return qsName;
+}
+
+QString AudioEffect::description()
+{
+ ComponentDescription description = m_audioNode->getAudioNodeDescription();
+ Component component = FindNextComponent(0, &description);
+ BACKEND_ASSERT3(component, "Could not get audio effect description.", NORMAL_ERROR, QLatin1String("<unknown effect>"))
+
+ ComponentDescription cDesc;
+ Handle descH = NewHandle(0);
+ GetComponentInfo(component, &cDesc, 0, descH, 0);
+ HLock(descH);
+ char *descPtr = *descH;
+ int len = *descPtr++;
+ descPtr[len] = 0;
+ QString qsDesc = QString::fromUtf8(descPtr);
+ DisposeHandle(descH);
+ return qsDesc;
+}
+
+QList<int> AudioEffect::effectList()
+{
+ QList<int> effects;
+
+ ComponentDescription d;
+ d.componentType = kAudioUnitType_Effect;
+ d.componentSubType = 0;
+ d.componentManufacturer = 0;
+ d.componentFlags = 0;
+ d.componentFlagsMask = 0;
+ Component component = FindNextComponent(0, &d);
+
+ while (component) {
+ ComponentDescription cDesc;
+ GetComponentInfo(component, &cDesc, 0, 0, 0);
+ effects << cDesc.componentSubType;
+ component = FindNextComponent(component, &d);
+ }
+ return effects;
+}
+
+Phonon::EffectParameter AudioEffect::createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const
+{
+ AudioUnitParameterInfo info;
+ UInt32 size = sizeof(info);
+ ComponentResult res = AudioUnitGetProperty(audioUnit,
+ kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, id, &info, &size);
+ BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, Phonon::EffectParameter())
+
+ QString name = info.flags & kAudioUnitParameterFlag_HasCFNameString
+ ? PhononCFString::toQString(info.cfNameString) : QLatin1String("<unknown parameter>");
+
+ Phonon::EffectParameter::Hint hint;
+ switch(info.unit){
+ case (kAudioUnitParameterUnit_Indexed):
+ case (kAudioUnitParameterUnit_Seconds):
+ case (kAudioUnitParameterUnit_SampleFrames):
+ case (kAudioUnitParameterUnit_Milliseconds):
+ hint = Phonon::EffectParameter::IntegerHint;
+ break;
+ case (kAudioUnitParameterUnit_Boolean):
+ hint = Phonon::EffectParameter::ToggledHint;
+ break;
+ default:
+ hint = Phonon::EffectParameter::LogarithmicHint;
+ break;
+ }
+
+ QVariant def(info.defaultValue);
+ QVariant min(info.minValue);
+ QVariant max(info.maxValue);
+ return Phonon::EffectParameter(id, name, hint, def, min, max, QVariantList(), name);
+}
+
+QVariant AudioEffect::parameterValue(const Phonon::EffectParameter &value) const
+{
+ return m_audioNode->parameterValue(value);
+}
+
+void AudioEffect::setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue)
+{
+ m_audioNode->setParameterValue(parameter, newValue);
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_audioeffects.cpp"
diff --git a/src/3rdparty/phonon/qt7/audiograph.h b/src/3rdparty/phonon/qt7/audiograph.h
new file mode 100644
index 0000000..76bc21a
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiograph.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOGRAPH_H
+#define Phonon_QT7_AUDIOGRAPH_H
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+
+#include <QtCore/qnamespace.h>
+#include "audioconnection.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioGraph : public MediaNode
+ {
+ public:
+ AudioGraph(MediaNode *root);
+ virtual ~AudioGraph();
+ AUGraph audioGraphRef();
+ void startAllOverFromScratch();
+
+ bool openAndInit();
+ void start();
+ void tryStartGraph();
+ void stop();
+ void prepare();
+ void rebuildGraph();
+ void update();
+ bool isRunning();
+ void setPaused(bool pause);
+ bool graphCannotPlay();
+ void rebuildGraphIfNeeded();
+ void updateStreamSpecifications();
+ void setStatusCannotPlay();
+ MediaNode *root();
+ void notify(const MediaNodeEvent *event, bool propagate = true);
+
+ private:
+ friend class MediaNode;
+ friend class AudioNode;
+
+ void deleteGraph();
+ bool updateStreamSpecificationRecursive(AudioConnection *connection);
+ void createAndConnectAuNodesRecursive(AudioConnection *connection);
+ bool createAudioUnitsRecursive(AudioConnection *connection);
+
+ void connectLate(AudioConnection *connection);
+ void disconnectLate(AudioConnection *connection);
+
+ int nodeCount();
+
+ bool m_initialized;
+ bool m_startedLogically;
+ bool m_rebuildLater;
+ bool m_graphCannotPlay;
+ bool m_paused;
+
+ AUGraph m_audioGraphRef;
+ MediaNode *m_root;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOGRAPH_H
diff --git a/src/3rdparty/phonon/qt7/audiograph.mm b/src/3rdparty/phonon/qt7/audiograph.mm
new file mode 100644
index 0000000..0d096e3
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiograph.mm
@@ -0,0 +1,320 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiograph.h"
+#include "quicktimeaudioplayer.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioGraph::AudioGraph(MediaNode *root) : MediaNode(AudioGraphNode, 0, root), m_root(root)
+{
+ m_audioGraphRef = 0;
+ m_initialized = false;
+ m_startedLogically = false;
+ m_graphCannotPlay = false;
+ m_paused = false;
+}
+
+AudioGraph::~AudioGraph()
+{
+ deleteGraph();
+}
+
+void AudioGraph::startAllOverFromScratch()
+{
+ MediaNodeEvent event(MediaNodeEvent::AudioGraphAboutToBeDeleted, this);
+ m_root->notify(&event);
+ deleteGraph();
+}
+
+void AudioGraph::deleteGraph()
+{
+ if (m_audioGraphRef){
+ AUGraphStop(m_audioGraphRef);
+ AUGraphUninitialize(m_audioGraphRef);
+ AUGraphClose(m_audioGraphRef);
+ DisposeAUGraph(m_audioGraphRef);
+ m_initialized = false;
+ m_graphCannotPlay = false;
+ DEBUG_AUDIO_GRAPH("Graph ref in" << int(this) << "is deleted")
+ }
+}
+
+MediaNode *AudioGraph::root()
+{
+ return m_root;
+}
+
+AUGraph AudioGraph::audioGraphRef()
+{
+ return m_audioGraphRef;
+}
+
+void AudioGraph::setStatusCannotPlay()
+{
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "received 'cannot play' request")
+ if (!m_graphCannotPlay){
+ stop();
+ m_graphCannotPlay = true;
+ MediaNodeEvent e(MediaNodeEvent::AudioGraphCannotPlay, this);
+ m_root->notify(&e);
+ }
+}
+
+void AudioGraph::rebuildGraph()
+{
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "is rebuilding")
+ startAllOverFromScratch();
+ if (!openAndInit()){
+ setStatusCannotPlay();
+ } else {
+ tryStartGraph();
+ m_graphCannotPlay = false;
+ }
+}
+
+bool AudioGraph::graphCannotPlay()
+{
+ return m_graphCannotPlay;
+}
+
+void AudioGraph::updateStreamSpecifications()
+{
+ if (!m_initialized){
+ if (m_graphCannotPlay)
+ rebuildGraph();
+ return;
+ }
+
+ AudioConnection rootConnection(m_root);
+ bool updateOk = updateStreamSpecificationRecursive(&rootConnection);
+ if (!updateOk){
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not update stream specification. Rebuild.")
+ rebuildGraph();
+ }
+}
+
+bool AudioGraph::updateStreamSpecificationRecursive(AudioConnection *connection)
+{
+ bool updateOk = connection->updateStreamSpecification();
+ if (!updateOk)
+ return false;
+
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i){
+ if (!updateStreamSpecificationRecursive(connection->m_sink->m_audioSinkList[i]))
+ return false;
+ }
+ return true;
+}
+
+bool AudioGraph::openAndInit()
+{
+ OSStatus err;
+ err = NewAUGraph(&m_audioGraphRef);
+ BACKEND_ASSERT3(err == noErr, "Could not create audio graph.", NORMAL_ERROR, false)
+
+ MediaNodeEvent eventNew(MediaNodeEvent::NewAudioGraph, this);
+ m_root->notify(&eventNew);
+
+ AudioConnection rootConnection(m_root);
+ createAndConnectAuNodesRecursive(&rootConnection);
+ err = AUGraphOpen(m_audioGraphRef);
+ BACKEND_ASSERT3(err == noErr, "Could not create audio graph.", NORMAL_ERROR, false)
+
+ if (!createAudioUnitsRecursive(&rootConnection))
+ return false;
+
+ err = AUGraphInitialize(m_audioGraphRef);
+ BACKEND_ASSERT3(err == noErr, "Could not initialize audio graph.", NORMAL_ERROR, false)
+
+ m_initialized = true;
+ MediaNodeEvent eventInit(MediaNodeEvent::AudioGraphInitialized, this);
+ m_root->notify(&eventInit);
+ return true;
+}
+
+void AudioGraph::createAndConnectAuNodesRecursive(AudioConnection *connection)
+{
+ connection->m_sink->m_audioNode->createAndConnectAUNodes();
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i){
+ AudioConnection *c = connection->m_sink->m_audioSinkList[i];
+ createAndConnectAuNodesRecursive(c);
+ bool ok = c->connect(this);
+ BACKEND_ASSERT2(ok, "Could not connect an audio nodes pair in the audio graph.", NORMAL_ERROR)
+ }
+}
+
+bool AudioGraph::createAudioUnitsRecursive(AudioConnection *connection)
+{
+ connection->m_sink->m_audioNode->createAudioUnits();
+ bool ok = connection->updateStreamSpecification();
+ if (!ok)
+ return false;
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i){
+ if (!createAudioUnitsRecursive(connection->m_sink->m_audioSinkList[i]))
+ return false;
+ }
+ return true;
+}
+
+void AudioGraph::tryStartGraph()
+{
+ // The graph will only start if the background AUGraph
+ // is valid. Therefore we just try. If it fails, user
+ // actions like connect etc. migh make the graph valid
+ // at a later point.
+ if (m_startedLogically && !isRunning()){
+ OSStatus err = AUGraphStart(m_audioGraphRef);
+ if (err == noErr)
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "started")
+ else
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not start")
+ }
+}
+
+bool AudioGraph::isRunning()
+{
+ Boolean running = false;
+ AUGraphIsRunning(m_audioGraphRef, &running);
+ return running;
+}
+
+void AudioGraph::setPaused(bool pause)
+{
+ // This function should only make
+ // a difference if the graph is
+ // running before pausing.
+ if (pause){
+ if (isRunning()){
+ stop();
+ m_paused = true;
+ }
+ } else if (m_paused){
+ start();
+ m_paused = false;
+ }
+}
+
+void AudioGraph::connectLate(AudioConnection *connection)
+{
+ MediaNodeEvent event(MediaNodeEvent::NewAudioGraph, this);
+ connection->m_sink->notify(&event);
+
+ if (!m_initialized)
+ return;
+
+ DEBUG_AUDIO_GRAPH("Graph:" << int(this) << "create and connect audio sink after init:" << int(connection->m_sink->m_audioNode))
+ AudioConnection startConnection(connection->m_source);
+ createAndConnectAuNodesRecursive(&startConnection);
+
+ if (!createAudioUnitsRecursive(&startConnection)){
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not update stream specification. Rebuild.")
+ rebuildGraph();
+ }
+}
+
+void AudioGraph::disconnectLate(AudioConnection *connection)
+{
+ if (!m_initialized)
+ return;
+
+ DEBUG_AUDIO_GRAPH("Graph:" << int(this) << "disconnect audio sink after init:" << int(connection->m_sink->m_audioNode))
+
+ if (!connection->disconnect(this)){
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "could not disconnect audio sink. Rebuild.")
+ rebuildGraph();
+ }
+}
+
+void AudioGraph::update()
+{
+ if (m_startedLogically){
+ if (m_initialized){
+ // Quick solution:
+ AUGraphUpdate(m_audioGraphRef, 0);
+ tryStartGraph();
+ } else
+ rebuildGraph();
+ }
+}
+
+int AudioGraph::nodeCount()
+{
+ if (!m_audioGraphRef)
+ return 0;
+ UInt32 count;
+ AUGraphGetNodeCount(m_audioGraphRef, &count);
+ return int(count);
+}
+
+void AudioGraph::prepare()
+{
+ if (!m_initialized)
+ rebuildGraph();
+}
+
+void AudioGraph::start()
+{
+ // Start does not mean 'start to play
+ // music'. It means 'prepare to receive
+ // audio from the player units'.
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "asked to start (cannot play:" << m_graphCannotPlay << ")")
+ m_startedLogically = true;
+
+ if (m_graphCannotPlay)
+ return;
+
+ if (!m_initialized)
+ rebuildGraph();
+
+ if (!m_graphCannotPlay)
+ tryStartGraph();
+}
+
+void AudioGraph::stop()
+{
+ DEBUG_AUDIO_GRAPH("Graph" << int(this) << "asked to stop")
+ if (m_audioGraphRef)
+ AUGraphStop(m_audioGraphRef);
+ m_startedLogically = false;
+}
+
+void AudioGraph::notify(const MediaNodeEvent *event, bool propagate)
+{
+ switch (event->type()){
+ case MediaNodeEvent::StartConnectionChange:
+ if (m_graphCannotPlay)
+ startAllOverFromScratch();
+ break;
+ case MediaNodeEvent::EndConnectionChange:
+ update();
+ break;
+ default:
+ break;
+ }
+ m_root->notify(event, propagate);
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiomixer.h b/src/3rdparty/phonon/qt7/audiomixer.h
new file mode 100644
index 0000000..275d7df
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiomixer.h
@@ -0,0 +1,91 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOMIXER_H
+#define Phonon_QT7_AUDIOMIXER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QTime>
+#include <QtCore/QEvent>
+#include <phonon/effectinterface.h>
+#include <phonon/effectparameter.h>
+#include <phonon/volumefaderinterface.h>
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioMixerAudioNode : public AudioNode
+ {
+ public:
+ AudioMixerAudioNode();
+ void setVolume(float volume, int bus = 0);
+ float volume(int bus = 0);
+
+ protected:
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+
+ private:
+ friend class AudioMixer;
+ int m_numberOfBusses;
+ float m_volume;
+ };
+
+ class AudioMixer : public MediaNode, Phonon::EffectInterface, Phonon::VolumeFaderInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface Phonon::VolumeFaderInterface)
+
+ public:
+ AudioMixer(QObject *parent = 0);
+ ~AudioMixer();
+ AudioMixerAudioNode *m_audioNode;
+ Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve;
+
+ int m_fadeTimer;
+ int m_fadeDuration;
+ float m_fadeToVolume;
+ float m_fadeFromVolume;
+ QTime m_fadeStartTime;
+
+ // EffectInterface:
+ QList<Phonon::EffectParameter> parameters() const;
+ QVariant parameterValue(const Phonon::EffectParameter &parameter) const;
+ void setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue);
+
+ // VolumeFaderInterface:
+ float volume() const;
+ void setVolume(float volume);
+ Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const;
+ void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve);
+ void fadeTo(float volume, int fadeTime);
+ void updateFade();
+
+ protected:
+ bool event(QEvent *event);
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOMIXER_H
diff --git a/src/3rdparty/phonon/qt7/audiomixer.mm b/src/3rdparty/phonon/qt7/audiomixer.mm
new file mode 100644
index 0000000..30b1e6f
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiomixer.mm
@@ -0,0 +1,181 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiomixer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioMixerAudioNode::AudioMixerAudioNode() : AudioNode(30, 1)
+{
+ m_numberOfBusses = 2;
+ m_volume = 1.0f;
+}
+
+ComponentDescription AudioMixerAudioNode::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Mixer;
+ description.componentSubType = kAudioUnitSubType_StereoMixer;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void AudioMixerAudioNode::initializeAudioUnit()
+{
+ // Set bus count:
+ OSStatus err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_BusCount, kAudioUnitScope_Input, 0, &m_numberOfBusses, sizeof(int));
+ BACKEND_ASSERT2(err == noErr, "Could not set number of busses on audio mixer node.", FATAL_ERROR)
+}
+
+void AudioMixerAudioNode::setVolume(float volume, int bus)
+{
+ if (volume < 0)
+ m_volume = 0;
+ else if (volume > 1)
+ m_volume = 1;
+ else
+ m_volume = volume;
+
+ if (m_audioUnit){
+// Float32 db = Float32(volume);//Float32(20.0 * log10(volume)); // convert to db
+ Float32 db = Float32(volume);
+ OSStatus err = AudioUnitSetParameter(m_audioUnit, kStereoMixerParam_Volume, kAudioUnitScope_Input, bus, db, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not set volume on audio mixer node.", NORMAL_ERROR)
+ }
+}
+
+float AudioMixerAudioNode::volume(int bus)
+{
+ if (!m_audioUnit)
+ return 0;
+
+ Float32 db;
+ OSStatus err = AudioUnitGetParameter(m_audioUnit, kStereoMixerParam_Volume, kAudioUnitScope_Input, bus, &db);
+ BACKEND_ASSERT3(err == noErr, "Could not get volume on audio mixer node.", NORMAL_ERROR, 0)
+ return float(db);
+}
+
+///////////////////////////////////////////////////////////////////////
+
+AudioMixer::AudioMixer(QObject *parent) : MediaNode(AudioSink | AudioSource, 0, parent)
+{
+ m_audioNode = new AudioMixerAudioNode();
+ setAudioNode(m_audioNode);
+ m_fadeCurve = Phonon::VolumeFaderEffect::Fade3Decibel;
+ m_fadeTimer = 0;
+ m_fadeDuration = 0;
+ m_fadeFromVolume = 0;
+ m_fadeToVolume = 0;
+}
+
+AudioMixer::~AudioMixer()
+{
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+}
+
+QList<Phonon::EffectParameter> AudioMixer::parameters() const
+{
+ QList<Phonon::EffectParameter> ret;
+ return ret;
+}
+
+QVariant AudioMixer::parameterValue(const Phonon::EffectParameter &value) const
+{
+ NOT_IMPLEMENTED;
+ Q_UNUSED(value);
+ return QVariant();
+}
+
+void AudioMixer::setParameterValue(const Phonon::EffectParameter &parameter, const QVariant &newValue)
+{
+ NOT_IMPLEMENTED;
+ Q_UNUSED(parameter);
+ Q_UNUSED(newValue);
+}
+
+float AudioMixer::volume() const
+{
+ return m_audioNode->volume(0);
+}
+
+void AudioMixer::setVolume(float volume)
+{
+ m_audioNode->setVolume(volume, 0);
+}
+
+Phonon::VolumeFaderEffect::FadeCurve AudioMixer::fadeCurve() const
+{
+ return m_fadeCurve;
+}
+
+void AudioMixer::setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve)
+{
+ m_fadeCurve = fadeCurve;
+}
+
+void AudioMixer::fadeTo(float volume, int fadeTime)
+{
+ m_fadeToVolume = volume;
+ m_fadeDuration = fadeTime;
+ m_fadeFromVolume = m_audioNode->volume(0);
+
+ m_fadeStartTime.start();
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+ m_fadeTimer = startTimer(100);
+}
+
+void AudioMixer::updateFade()
+{
+ float step = float(m_fadeStartTime.elapsed()) / float(m_fadeDuration);
+ if (step > 1){
+ step = 1;
+ if (m_fadeTimer)
+ killTimer(m_fadeTimer);
+ }
+ float volume = m_fadeFromVolume + ((m_fadeToVolume - m_fadeFromVolume) * step);
+ m_audioNode->setVolume(volume, 0);
+}
+
+bool AudioMixer::event(QEvent *event)
+{
+ switch (event->type()){
+ case QEvent::Timer:{
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
+ if (timerEvent->timerId() == m_fadeTimer)
+ updateFade();
+ break; }
+ default:
+ break;
+ }
+ return MediaNode::event(event);
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_audiomixer.cpp"
diff --git a/src/3rdparty/phonon/qt7/audionode.h b/src/3rdparty/phonon/qt7/audionode.h
new file mode 100644
index 0000000..dfec817
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audionode.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AudioNode_H
+#define Phonon_QT7_AudioNode_H
+
+#include <QtCore/QObject>
+#include "backendheader.h"
+#include "audioconnection.h"
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioGraph;
+ class MediaNodeEvent;
+ class MediaNode;
+
+ class MediaNodeConnection{
+ MediaNode *source;
+ MediaNode *sink;
+ int inputPort;
+ int outputPort;
+ };
+
+ class AudioNode
+ {
+ public:
+ enum ConnectionSide {Source, Sink};
+
+ AudioNode(int maxInput, int maxOutput);
+ virtual ~AudioNode();
+
+ virtual void createAndConnectAUNodes();
+ virtual void createAudioUnits();
+ virtual void setGraph(AudioGraph *audioGraph);
+ virtual AUNode getInputAUNode();
+ virtual AUNode getOutputAUNode();
+ virtual bool fillInStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ virtual bool setStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ void notify(const MediaNodeEvent *event);
+
+ virtual void mediaNodeEvent(const MediaNodeEvent *event);
+ Float64 getTimeInSamples(int timeProperty);
+
+ AudioGraph *m_audioGraph;
+ AudioConnection *m_lastConnectionIn;
+
+ int m_maxInputBusses;
+ int m_maxOutputBusses;
+
+ protected:
+ AUNode m_auNode;
+ AudioUnit m_audioUnit;
+
+ // Only the following methods needs to
+ // be overridden by only_one-audio-unit nodes:
+ virtual ComponentDescription getAudioNodeDescription() const;
+ virtual void initializeAudioUnit();
+
+ private:
+ bool setStreamHelp(AudioConnection *c, int bus, OSType scope, bool fromSource);
+ };
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AudioNode_H
diff --git a/src/3rdparty/phonon/qt7/audionode.mm b/src/3rdparty/phonon/qt7/audionode.mm
new file mode 100644
index 0000000..77cd627
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audionode.mm
@@ -0,0 +1,243 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audionode.h"
+#include "audiograph.h"
+#include "audioconnection.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioNode::AudioNode(int maxInputBusses, int maxOutputBusses)
+{
+ m_auNode = 0;
+ m_audioUnit = 0;
+ m_audioGraph = 0;
+ m_maxInputBusses = maxInputBusses;
+ m_maxOutputBusses = maxOutputBusses;
+ m_lastConnectionIn = 0;
+}
+
+AudioNode::~AudioNode()
+{
+ setGraph(0);
+}
+
+void AudioNode::setGraph(AudioGraph *audioGraph)
+{
+ if (m_audioGraph == audioGraph)
+ return;
+
+ DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "is setting graph:" << int(audioGraph))
+ if (m_auNode){
+ AUGraphRemoveNode(m_audioGraph->audioGraphRef(), m_auNode);
+ m_auNode = 0;
+ }
+
+ m_audioUnit = 0;
+ m_lastConnectionIn = 0;
+ m_audioGraph = audioGraph;
+}
+
+void AudioNode::createAndConnectAUNodes()
+{
+ if (m_auNode)
+ return;
+
+ ComponentDescription description = getAudioNodeDescription();
+ DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AUNode"
+ << QString(!FindNextComponent(0, &description) ? "ERROR: COMPONENT NOT FOUND!" : "OK!"))
+
+ OSStatus err = noErr;
+
+ // The proper function to call here is AUGraphAddNode() but the type has
+ // changed between 10.5 and 10.6. it's still OK to call this function, but
+ // if we want to use the proper thing we need to move over to
+ // AudioComponentDescription everywhere, which is very similar to the
+ // ComponentDescription, but a different size. however,
+ // AudioComponentDescription only exists on 10.6+. More fun than we need to
+ // deal with at the moment, so we'll take the "deprecated" warning instead.
+ err = AUGraphNewNode(m_audioGraph->audioGraphRef(), &description, 0, 0, &m_auNode);
+
+ BACKEND_ASSERT2(err != kAUGraphErr_OutputNodeErr, "A MediaObject can only be connected to one audio output device.", FATAL_ERROR)
+ BACKEND_ASSERT2(err == noErr, "Could not create new AUNode.", FATAL_ERROR)
+}
+
+AUNode AudioNode::getInputAUNode()
+{
+ return m_auNode;
+}
+
+AUNode AudioNode::getOutputAUNode()
+{
+ return m_auNode;
+}
+
+void AudioNode::createAudioUnits()
+{
+ if (m_audioUnit)
+ return;
+
+ DEBUG_AUDIO_GRAPH("AudioNode" << int(this) << "creates AudioUnit")
+ OSStatus err = AUGraphGetNodeInfo(m_audioGraph->audioGraphRef(), m_auNode, 0, 0, 0, &m_audioUnit);
+ BACKEND_ASSERT2(err == noErr, "Could not get audio unit from audio node.", FATAL_ERROR)
+ initializeAudioUnit();
+}
+
+ComponentDescription AudioNode::getAudioNodeDescription() const
+{
+ // Override if needed.
+ ComponentDescription cd;
+ Q_UNUSED(cd);
+ return cd;
+}
+
+bool AudioNode::setStreamHelp(AudioConnection *c, int bus, OSType scope, bool fromSource)
+{
+ if (fromSource){
+ OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope,
+ bus, &c->m_sourceStreamDescription, sizeof(AudioStreamBasicDescription));
+ if (err != noErr){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format")
+ return false;
+ }
+ AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope,
+ bus, c->m_sourceChannelLayout, c->m_sourceChannelLayoutSize);
+ } else {
+ OSStatus err = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope,
+ bus, &c->m_sinkStreamDescription, sizeof(AudioStreamBasicDescription));
+ if (err != noErr){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " - failed setting stream format")
+ return false;
+ }
+ AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_AudioChannelLayout, scope,
+ bus, c->m_sinkChannelLayout, c->m_sourceChannelLayoutSize);
+ }
+ return true;
+}
+
+bool AudioNode::setStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ // This object am source of connection:
+ if (connection->m_hasSourceSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification out"
+ << connection->m_sourceOutputBus << "from connection source")
+ return setStreamHelp(connection, connection->m_sourceOutputBus, kAudioUnitScope_Output, true);
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification out")
+ }
+ } else {
+ if (connection->m_hasSinkSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification"
+ << connection->m_sinkInputBus << "from connection sink")
+ return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, false);
+ } else if (connection->m_hasSourceSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "sets stream specification"
+ << connection->m_sinkInputBus << "from connection source")
+ return setStreamHelp(connection, connection->m_sinkInputBus, kAudioUnitScope_Input, true);
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "did not set stream specification in")
+ }
+ }
+ return true;
+}
+
+bool AudioNode::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ // As default, use the last description to describe the source:
+ if (m_lastConnectionIn->m_hasSinkSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection sink.")
+ connection->m_sourceStreamDescription = m_lastConnectionIn->m_sinkStreamDescription;
+ connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sinkChannelLayoutSize);
+ memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sinkChannelLayout, m_lastConnectionIn->m_sinkChannelLayoutSize);
+ connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sinkChannelLayoutSize;
+ connection->m_hasSourceSpecification = true;
+ } else if (m_lastConnectionIn->m_hasSourceSpecification){
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is source, and fills in stream spec using last connection source.")
+ connection->m_sourceStreamDescription = m_lastConnectionIn->m_sourceStreamDescription;
+ connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_lastConnectionIn->m_sourceChannelLayoutSize);
+ memcpy(connection->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayout, m_lastConnectionIn->m_sourceChannelLayoutSize);
+ connection->m_sourceChannelLayoutSize = m_lastConnectionIn->m_sourceChannelLayoutSize;
+ connection->m_hasSourceSpecification = true;
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << " __WARNING__: could not get stream specification...")
+ }
+ } else {
+ DEBUG_AUDIO_STREAM("AudioNode" << int(this) << "is sink, skips filling in stream.")
+ if (!connection->isSinkOnly())
+ m_lastConnectionIn = connection;
+ }
+ return true;
+}
+
+/**
+ Let timeProperty be one of e.g
+ {kAudioUnitProperty_Latency, kAudioUnitProperty_TailTime,
+ kAudioOutputUnitProperty_StartTime, kAudioUnitProperty_CurrentPlayTime}
+*/
+Float64 AudioNode::getTimeInSamples(int timeProperty)
+{
+ if (!m_audioUnit)
+ return 0;
+
+ AudioTimeStamp timeStamp;
+ UInt32 size = sizeof(timeStamp);
+ memset(&timeStamp, 0, sizeof(timeStamp));
+ OSStatus err = AudioUnitGetProperty(m_audioUnit,
+ timeProperty, kAudioUnitScope_Global,
+ 0, &timeStamp, &size);
+ if (err != noErr)
+ return 0;
+ return timeStamp.mSampleTime;
+}
+
+void AudioNode::notify(const MediaNodeEvent *event)
+{
+ switch(event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ setGraph(0);
+ break;
+ case MediaNodeEvent::NewAudioGraph:
+ setGraph(static_cast<AudioGraph *>(event->data()));
+ break;
+ default:
+ break;
+ }
+
+ mediaNodeEvent(event);
+}
+
+void AudioNode::mediaNodeEvent(const MediaNodeEvent */*event*/)
+{
+ // Override if needed
+}
+
+void AudioNode::initializeAudioUnit()
+{
+ // Override if needed.
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiooutput.h b/src/3rdparty/phonon/qt7/audiooutput.h
new file mode 100644
index 0000000..c4a0526
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiooutput.h
@@ -0,0 +1,88 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOOUTPUT_H
+#define Phonon_QT7_AUDIOOUTPUT_H
+
+#include <QtCore/QObject>
+#include <phonon/audiooutputinterface.h>
+#include <phonon/abstractaudiooutput.h>
+
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioOutputAudioPart : public QObject, AudioNode
+ {
+ Q_OBJECT
+ public:
+ AudioOutputAudioPart();
+
+ void setVolume(float volume);
+ float volume();
+
+ protected:
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+
+ signals:
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+
+ private:
+ friend class AudioOutput;
+ qreal m_volume;
+ AudioDeviceID m_audioDevice;
+ void setAudioDevice(AudioDeviceID device);
+ };
+
+ class AudioOutput : public MediaNode, public AudioOutputInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioOutputInterface)
+
+ public:
+ AudioOutput(QObject *parent = 0);
+ ~AudioOutput();
+
+ qreal volume() const;
+ void setVolume(qreal);
+ int outputDevice() const;
+ bool setOutputDevice(int);
+
+ signals:
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ private:
+ AudioOutputAudioPart *m_audioOutput;
+ int m_device;
+ bool m_redirectToMovie;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_AUDIOOUTPUT_H
diff --git a/src/3rdparty/phonon/qt7/audiooutput.mm b/src/3rdparty/phonon/qt7/audiooutput.mm
new file mode 100644
index 0000000..38066d5
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiooutput.mm
@@ -0,0 +1,168 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiooutput.h"
+#include "audiograph.h"
+#include "audiodevice.h"
+#include "mediaobject.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioOutputAudioPart::AudioOutputAudioPart() : AudioNode(1, 0)
+{
+ m_audioDevice = AudioDevice::defaultDevice(AudioDevice::Out);
+ m_volume = 1;
+}
+
+ComponentDescription AudioOutputAudioPart::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Output;
+ description.componentSubType = kAudioUnitSubType_DefaultOutput;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void AudioOutputAudioPart::initializeAudioUnit()
+{
+ setAudioDevice(m_audioDevice);
+ setVolume(m_volume);
+}
+
+void AudioOutputAudioPart::setAudioDevice(AudioDeviceID device)
+{
+ m_audioDevice = device;
+ if (!m_audioDevice)
+ return;
+ if (!m_audioUnit)
+ return;
+ bool ok = AudioDevice::setDevice(m_audioUnit, m_audioDevice, AudioDevice::Out);
+ if (!ok)
+ emit audioDeviceFailed();
+}
+
+void AudioOutputAudioPart::setVolume(float volume)
+{
+ if (volume < 0)
+ m_volume = 0;
+ if (volume > 1)
+ m_volume = 1;
+ else
+ m_volume = volume;
+
+ if (m_audioUnit){
+ float db = volume;//20.0 * log10(volume); // convert to db
+ OSStatus err = AudioUnitSetParameter(m_audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Input, 0, db, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not set volume on output audio unit.", FATAL_ERROR)
+ emit volumeChanged(qreal(db));
+ }
+}
+
+float AudioOutputAudioPart::volume()
+{
+ return m_volume;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+AudioOutput::AudioOutput(QObject *parent) : MediaNode(AudioSink, parent)
+{
+ m_audioOutput = new AudioOutputAudioPart();
+ setAudioNode(m_audioOutput);
+ connect(m_audioOutput, SIGNAL(volumeChanged(qreal)), this, SIGNAL(volumeChanged(qreal)));
+ connect(m_audioOutput, SIGNAL(audioDeviceFailed()), this, SIGNAL(audioDeviceFailed()));
+ m_redirectToMovie = false;
+}
+
+AudioOutput::~AudioOutput()
+{
+}
+
+void AudioOutput::setVolume(qreal volume)
+{
+ IMPLEMENTED;
+ m_audioOutput->setVolume(float(volume));
+ if (m_owningMediaObject)
+ m_owningMediaObject->setVolumeOnMovie(volume);
+
+ emit volumeChanged(m_audioOutput->volume());
+}
+
+qreal AudioOutput::volume() const
+{
+ IMPLEMENTED;
+ return qreal(m_audioOutput->volume());
+}
+
+bool AudioOutput::setOutputDevice(int device)
+{
+ IMPLEMENTED;
+ if (device == -1)
+ return false;
+
+ if (m_owningMediaObject){
+ bool ok = m_owningMediaObject->setAudioDeviceOnMovie(device);
+ if (!ok)
+ return false;
+ }
+
+ if (m_audioGraph){
+ MediaNodeEvent event1(MediaNodeEvent::AboutToRestartAudioStream, this);
+ m_audioGraph->notify(&event1);
+ }
+
+ m_audioOutput->setAudioDevice(device);
+
+ if (m_audioGraph){
+ MediaNodeEvent event2(MediaNodeEvent::RestartAudioStreamRequest, this);
+ m_audioGraph->notify(&event2);
+ }
+ return true;
+}
+
+int AudioOutput::outputDevice() const
+{
+ IMPLEMENTED;
+ return m_audioOutput->m_audioDevice;
+}
+
+void AudioOutput::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::SetMediaObject:
+ if (static_cast<MediaObject *>(event->data())){
+ setVolume(volume());
+ setOutputDevice(outputDevice());
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_audiooutput.cpp"
diff --git a/src/3rdparty/phonon/qt7/audiopartoutput.h b/src/3rdparty/phonon/qt7/audiopartoutput.h
new file mode 100644
index 0000000..0ccdfb6
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiopartoutput.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOPARTOUTPUT_H
+#define Phonon_QT7_AUDIOPARTOUTPUT_H
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+#include "audionode.h"
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioPartOutput : public AudioNode
+ {
+ public:
+ AudioPartOutput();
+ virtual ~AudioPartOutput();
+
+ private:
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit(AudioNode *source);
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOPARTOUTPUT_H
diff --git a/src/3rdparty/phonon/qt7/audiopartoutput.mm b/src/3rdparty/phonon/qt7/audiopartoutput.mm
new file mode 100644
index 0000000..b985e69
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiopartoutput.mm
@@ -0,0 +1,69 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiopartoutput.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioPartOutput::AudioPartOutput()
+ : AudioNode()
+{
+}
+
+AudioPartOutput::~AudioPartOutput()
+{
+}
+
+ComponentDescription AudioPartOutput::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Output;
+ description.componentSubType = kAudioUnitSubType_DefaultOutput;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void AudioPartOutput::initializeAudioUnit(AudioNode *source)
+{
+ m_audioStreamDescription = source->outputStreamDescription();
+ m_audioChannelLayout = source->outputChannelLayout();
+ m_audioChannelLayoutSize = source->outputChannelLayoutSize();
+
+ // Specify the stream format:
+ OSStatus err;
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
+ 0, m_audioStreamDescription, sizeof(AudioStreamBasicDescription));
+ BACKEND_ASSERT2(err == noErr, "Could not set stream format on audio output unit.", FATAL_ERROR)
+
+ // Set the channel layout:
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input,
+ 0, m_audioChannelLayout, m_audioChannelLayoutSize);
+ BACKEND_ASSERT2(err == noErr, "Could not set channel layout on audio output unit.", FATAL_ERROR)
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/audiosplitter.h b/src/3rdparty/phonon/qt7/audiosplitter.h
new file mode 100644
index 0000000..ed6101f
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiosplitter.h
@@ -0,0 +1,50 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_AUDIOSPLITTER_H
+#define Phonon_QT7_AUDIOSPLITTER_H
+
+#include <QtCore/QFile>
+
+#include "medianode.h"
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioNodeSplitter : public AudioNode
+ {
+ public:
+ AudioNodeSplitter();
+ ComponentDescription getAudioNodeDescription() const;
+ };
+
+ class AudioSplitter : public MediaNode
+ {
+ public:
+ AudioSplitter(QObject *parent = 0);
+ ~AudioSplitter();
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_AUDIOSPLITTER_H
diff --git a/src/3rdparty/phonon/qt7/audiosplitter.mm b/src/3rdparty/phonon/qt7/audiosplitter.mm
new file mode 100644
index 0000000..685ea12
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/audiosplitter.mm
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiosplitter.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+AudioNodeSplitter::AudioNodeSplitter() : AudioNode(1, 2)
+{
+}
+
+ComponentDescription AudioNodeSplitter::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_FormatConverter;
+ description.componentSubType = kAudioUnitSubType_Splitter;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+AudioSplitter::AudioSplitter(QObject *parent) : MediaNode(AudioSink | AudioSource, new AudioNodeSplitter(), parent)
+{
+}
+
+AudioSplitter::~AudioSplitter()
+{
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/backend.h b/src/3rdparty/phonon/qt7/backend.h
new file mode 100644
index 0000000..287fcec
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backend.h
@@ -0,0 +1,61 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_BACKEND_H
+#define Phonon_QT7_BACKEND_H
+
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+#include <QtCore/QStringList>
+#include <phonon/backendinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class Backend : public QObject, public BackendInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::BackendInterface)
+
+ public:
+ Backend();
+ Backend(QObject *parent, const QStringList &args);
+ virtual ~Backend();
+
+ QObject *createObject(BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
+ QStringList availableMimeTypes() const;
+ QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+
+ bool startConnectionChange(QSet<QObject *> nodes);
+ bool connectNodes(QObject *source, QObject *sink);
+ bool disconnectNodes(QObject *source, QObject *sink);
+ bool endConnectionChange(QSet<QObject *> nodes);
+
+ Q_SIGNALS:
+ void objectDescriptionChanged(ObjectDescriptionType);
+
+ private:
+ bool quickTime7Available();
+ };
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_BACKEND_H
diff --git a/src/3rdparty/phonon/qt7/backend.mm b/src/3rdparty/phonon/qt7/backend.mm
new file mode 100644
index 0000000..b3ca106
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backend.mm
@@ -0,0 +1,276 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backend.h"
+#include <QtCore/QDebug>
+#include <QtCore/QSet>
+#include <QtCore/QVariant>
+#include <QtCore/QtPlugin>
+
+#include "backendheader.h"
+
+#include "videowidget.h"
+#include "audiooutput.h"
+#include "mediaobject.h"
+#include "videoeffect.h"
+#include "medianode.h"
+#include "audiodevice.h"
+#include "audiomixer.h"
+#include "backendinfo.h"
+#include "quicktimeaudioplayer.h"
+
+#include "audiograph.h"
+#include "audiomixer.h"
+#include "audiooutput.h"
+#include "audiosplitter.h"
+#include "audioeffects.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+Backend::Backend()
+{
+ IMPLEMENTED << "Creating backend QT7";
+}
+
+Backend::Backend(QObject *parent, const QStringList &) : QObject(parent)
+{
+ IMPLEMENTED << "Creating backend QT7";
+ setProperty("identifier", QLatin1String("Mac OS X/QuickTime7"));
+ setProperty("backendName", QLatin1String("Mac OS X/QuickTime7"));
+ setProperty("backendComment", QLatin1String("Developed by Trolltech"));
+ setProperty("backendVersion", QLatin1String("0.1"));
+ setProperty("backendIcon", QLatin1String(""));
+ setProperty("backendWebsite", QLatin1String("http://qt.nokia.com/"));
+}
+
+Backend::~Backend()
+{
+}
+
+bool Backend::quickTime7Available()
+{
+ static bool ok = BackendInfo::isQuickTimeVersionAvailable(0x0700);
+ if (!ok){
+ static bool messageWritten = false;
+ if (!messageWritten && qgetenv("PHONON_DEBUG") == "1"){
+ messageWritten = true;
+ QString str("WARNING: Phonon backend plugin need QuickTime 7 or newer to work.");
+ str += " This computer has version "
+ + BackendInfo::quickTimeVersionString()
+ + " installed.";
+ qWarning(str.toAscii().data());
+ }
+ return false;
+ }
+ return true;
+}
+
+QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+{
+ if (!quickTime7Available())
+ return 0;
+
+ switch (c) {
+ case MediaObjectClass:
+ IMPLEMENTED << "Creating new MediaObjectClass.";
+ return new MediaObject(parent);
+ break;
+ case VolumeFaderEffectClass:
+ IMPLEMENTED << "Creating new VolumeFaderEffectClass.";
+ return new AudioMixer(parent);
+ break;
+ case AudioOutputClass:
+ IMPLEMENTED << "Creating new AudioOutputClass.";
+ return new AudioOutput(parent);
+ break;
+ case AudioDataOutputClass:
+ NOT_IMPLEMENTED << "Creating new AudioDataOutputClass.";
+ break;
+ case VisualizationClass:
+ NOT_IMPLEMENTED << "Creating new VisualizationClass.";
+ break;
+ case VideoDataOutputClass:
+ NOT_IMPLEMENTED << "Creating new VideoDataOutputClass.";
+ break;
+ case EffectClass:
+ IMPLEMENTED << "Creating new EffectClass.";
+ return new AudioEffect(args[0].toInt());
+ break;
+ case VideoWidgetClass:
+ IMPLEMENTED << "Creating new VideoWidget.";
+ return new VideoWidget(parent);
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+bool Backend::startConnectionChange(QSet<QObject *> objects)
+{
+ IMPLEMENTED;
+ QList<AudioGraph *> notifiedGraphs;
+ for (int i=0; i<objects.size(); i++){
+ MediaNode *node = qobject_cast<MediaNode*>(objects.values()[i]);
+ if (node && node->m_audioGraph && !notifiedGraphs.contains(node->m_audioGraph)){
+ MediaNodeEvent event(MediaNodeEvent::StartConnectionChange);
+ node->m_audioGraph->notify(&event);
+ notifiedGraphs << node->m_audioGraph;
+ }
+ }
+ return true;
+}
+
+bool Backend::endConnectionChange(QSet<QObject *> objects)
+{
+ IMPLEMENTED;
+ QList<AudioGraph *> notifiedGraphs;
+ for (int i=0; i<objects.size(); i++){
+ MediaNode *node = qobject_cast<MediaNode*>(objects.values()[i]);
+ if (node && node->m_audioGraph && !notifiedGraphs.contains(node->m_audioGraph)){
+ MediaNodeEvent event(MediaNodeEvent::EndConnectionChange);
+ node->m_audioGraph->notify(&event);
+ notifiedGraphs << node->m_audioGraph;
+ }
+ }
+ return true;
+}
+
+bool Backend::connectNodes(QObject *aSource, QObject *aSink)
+{
+ IMPLEMENTED;
+ MediaNode *source = qobject_cast<MediaNode*>(aSource);
+ if (!source) return false;
+ MediaNode *sink = qobject_cast<MediaNode*>(aSink);
+ if (!sink) return false;
+
+ return source->connectToSink(sink);
+}
+
+
+bool Backend::disconnectNodes(QObject *aSource, QObject *aSink)
+{
+ IMPLEMENTED;
+ MediaNode *source = qobject_cast<MediaNode*>(aSource);
+ if (!source) return false;
+ MediaNode *sink = qobject_cast<MediaNode*>(aSink);
+ if (!sink) return false;
+
+ return source->disconnectToSink(sink);
+}
+
+
+QStringList Backend::availableMimeTypes() const
+{
+ IMPLEMENTED;
+ return BackendInfo::quickTimeMimeTypes(BackendInfo::In);
+}
+
+/**
+* Returns a set of indexes that acts as identifiers for the various properties
+* this backend supports for the given ObjectDescriptionType.
+* More information for a given property/index can be
+* looked up in Backend::objectDescriptionProperties(...).
+*/
+QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+ QList<int> ret;
+
+ switch (type){
+ case AudioOutputDeviceType:{
+ IMPLEMENTED_SILENT << "Creating index set for type: AudioOutputDeviceType";
+ QList<AudioDeviceID> devices = AudioDevice::devices(AudioDevice::Out);
+ for (int i=0; i<devices.size(); i++)
+ ret << int(devices[i]);
+ break; }
+ case EffectType:{
+ IMPLEMENTED_SILENT << "Creating index set for type: EffectType";
+ if (QuickTimeAudioPlayer::soundPlayerIsAwailable())
+ ret = AudioEffect::effectList();
+ break; }
+
+#if 0 // will be awailable in a later version of phonon.
+ case AudioCaptureDeviceType:{
+ IMPLEMENTED_SILENT << "Creating index set for type: AudioCaptureDeviceType";
+ QList<AudioDeviceID> devices = AudioDevice::devices(AudioDevice::In).keys();
+ for (int i=0; i<devices.size(); i++)
+ ret <<int(devices[i]);
+ break; }
+ case VideoEffectType:{
+ // Just count the number of filters awailable (c), and
+ // add return a set with the numbers 1..c inserted:
+ IMPLEMENTED_SILENT << "Creating index set for type: VideoEffectType";
+ QList<QtCore/QString> filters = objc_getCiFilterInfo()->filterDisplayNames;
+ for (int i=0; i<filters.size(); i++)
+ ret << insert(i);
+ break; }
+#endif
+ default:
+ NOT_IMPLEMENTED;
+ break;
+ }
+ return ret;
+}
+
+QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+ QHash<QByteArray, QVariant> ret;
+
+ switch (type){
+ case AudioOutputDeviceType:{
+ IMPLEMENTED_SILENT << "Creating description hash for type: AudioOutputDeviceType";
+ ret.insert("name", AudioDevice::deviceSourceNameElseDeviceName(index));
+ ret.insert("description", AudioDevice::deviceNameElseDeviceSourceName(index));
+ break; }
+ case EffectType:{
+ AudioEffect e(index);
+ ret.insert("name", e.name());
+ ret.insert("description", e.description());
+ break; }
+
+#if 0 // will be awailable in a later version of phonon.
+ case VideoEffectType:{
+ // Get list of effects, pick out filter at index, and return its name:
+ IMPLEMENTED_SILENT << "Creating description hash for type: VideoEffectType";
+ QList<QtCore/QString> filters = objc_getCiFilterInfo()->filterDisplayNames;
+ ret.insert("name", filters[index]);
+ case AudioCaptureDeviceType:{
+ IMPLEMENTED_SILENT << "Creating description hash for type: AudioCaptureDeviceType";
+ QMap<AudioDeviceID, QString> devices = AudioDevice::devices(AudioDevice::In);
+ ret.insert("name", devices.value(index));
+ break; }
+#endif
+ default:
+ NOT_IMPLEMENTED;
+ break;
+ }
+
+ return ret;
+}
+
+Q_EXPORT_PLUGIN2(phonon_qt7, Backend)
+}}
+
+QT_END_NAMESPACE
+
+#include "moc_backend.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/backendheader.h b/src/3rdparty/phonon/qt7/backendheader.h
new file mode 100644
index 0000000..fd0d892
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendheader.h
@@ -0,0 +1,184 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_BACKENDHEADER_H
+#define Phonon_QT7_BACKENDHEADER_H
+
+#include <QtCore/QString>
+#import <Foundation/NSAutoreleasePool.h>
+#include <CoreFoundation/CFBase.h>
+
+#ifndef Q_WS_MAC64
+#define QUICKTIME_C_API_AVAILABLE
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+// Implemented in error.cpp:
+void gSetErrorString(const QString &errorString);
+QString gGetErrorString();
+void gSetErrorLocation(const QString &errorLocation);
+void gSetErrorType(int type);
+int gGetErrorType();
+void gClearError();
+
+#define NO_ERROR 0
+#define NORMAL_ERROR 1
+#define FATAL_ERROR 2
+
+#define ERROR_LOCATION \
+ QLatin1String("Function: ") + QLatin1String(__FUNCTION__) \
+ + QLatin1String(", File: ") + QLatin1String(__FILE__) \
+ + QLatin1String(", Line: ") + QString::number(__LINE__)
+
+#define SET_ERROR(string, type){ \
+ Phonon::QT7::gSetErrorString(string); \
+ Phonon::QT7::gSetErrorType(type); \
+ Phonon::QT7::gSetErrorLocation(ERROR_LOCATION); }
+
+#define BACKEND_ASSERT(test, string, type) \
+ bool fail = !test; \
+ if (fail) \
+ SET_ERROR(QLatin1String(string), type) \
+ if (fail)
+
+#define BACKEND_ASSERT2(test, string, type) \
+ if (!(test)) { \
+ SET_ERROR(QLatin1String(string), type) \
+ return; \
+ }
+
+#define BACKEND_ASSERT3(test, string, type, ret) \
+ if (!(test)) { \
+ SET_ERROR(QLatin1String(string), type) \
+ return ret; \
+ }
+
+#define ARGUMENT_UNSUPPORTED(a, x, type, ret) \
+ if ((a) == (x)) { \
+ SET_ERROR("Argument value not supported: "#a" == "#x, type); \
+ return ret; \
+ }
+
+#define CASE_UNSUPPORTED(string, type) SET_ERROR(string, type)
+
+#ifdef SET_DEBUG_IMPLEMENTED
+#define IMPLEMENTED qDebug() << "QT7:" << __FUNCTION__ << "(" << __FILE__ << "):"
+#else
+#define IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_HALF_IMPLEMENTED
+#define HALF_IMPLEMENTED qDebug() << "QT7: --- HALF IMPLEMENTED:" << __FUNCTION__ << "(" << __FILE__ << "," << __LINE__ << "):"
+#else
+#define HALF_IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_NOT_IMPLEMENTED
+#define NOT_IMPLEMENTED qDebug() << "QT7: *** NOT IMPLEMENTED:" << __FUNCTION__ << "(" << __FILE__ << "," << __LINE__ << "):"
+#else
+#define NOT_IMPLEMENTED if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_IMPLEMENTED_SILENT
+#define IMPLEMENTED_SILENT qDebug() << "QT7: (silent)" << __FUNCTION__ << "(" << __FILE__ << "," << __LINE__ << "):"
+#else
+#define IMPLEMENTED_SILENT if (1); else qDebug()
+#endif
+
+#ifdef SET_DEBUG_AUDIO_GRAPH
+#define DEBUG_AUDIO_GRAPH(x) qDebug() << "QT7 DEBUG GRAPH:" << x;
+#else
+#define DEBUG_AUDIO_GRAPH(x) {}
+#endif
+
+#ifdef SET_DEBUG_AUDIO_STREAM
+#define DEBUG_AUDIO_STREAM(x) qDebug() << "QT7 DEBUG STREAM:" << x;
+#else
+#define DEBUG_AUDIO_STREAM(x) {}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class PhononAutoReleasePool
+{
+private:
+ void *pool;
+public:
+ PhononAutoReleasePool();
+ ~PhononAutoReleasePool();
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+class PhononCFType
+{
+public:
+ inline PhononCFType(const T &t = 0) : type(t) {}
+ inline PhononCFType(const PhononCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
+ inline ~PhononCFType() { if (type) CFRelease(type); }
+ inline operator T() { return type; }
+ inline PhononCFType operator =(const PhononCFType &helper)
+ {
+ if (helper.type)
+ CFRetain(helper.type);
+ CFTypeRef type2 = type;
+ type = helper.type;
+ if (type2)
+ CFRelease(type2);
+ return *this;
+ }
+ inline T *operator&() { return &type; }
+ static PhononCFType constructFromGet(const T &t)
+ {
+ CFRetain(t);
+ return PhononCFType<T>(t);
+ }
+protected:
+ T type;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class PhononCFString : public PhononCFType<CFStringRef>
+{
+public:
+ inline PhononCFString(const QString &str) : PhononCFType<CFStringRef>(0), string(str) {}
+ inline PhononCFString(const CFStringRef cfstr = 0) : PhononCFType<CFStringRef>(cfstr) {}
+ inline PhononCFString(const PhononCFType<CFStringRef> &other) : PhononCFType<CFStringRef>(other) {}
+ operator QString() const;
+ operator CFStringRef() const;
+ static QString toQString(CFStringRef cfstr);
+ static CFStringRef toCFStringRef(const QString &str);
+private:
+ QString string;
+};
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#ifdef Q_CC_INTEL
+#pragma warning (disable : 1899) // mute icc warning for the use of 4cc
+#endif
+
+#endif // Phonon_QT7_BACKENDHEADER_H
diff --git a/src/3rdparty/phonon/qt7/backendheader.mm b/src/3rdparty/phonon/qt7/backendheader.mm
new file mode 100644
index 0000000..3a73389
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendheader.mm
@@ -0,0 +1,127 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backendheader.h"
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <QVarLengthArray>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+Q_GLOBAL_STATIC(QString, gErrorString)
+int gErrorType = NO_ERROR;
+
+void gSetErrorString(const QString &errorString)
+{
+ if (qgetenv("PHONON_DEBUG") == "1"){
+ qDebug() << "Error:" << errorString;
+ }
+
+ if (!gErrorString()->isEmpty())
+ return; // not yet caught.
+
+ *gErrorString() = errorString;
+}
+
+QString gGetErrorString()
+{
+ return *gErrorString();
+}
+
+void gSetErrorLocation(const QString &errorLocation)
+{
+ if (qgetenv("PHONON_DEBUG") == "1"){
+ qDebug() << "Location:" << errorLocation;
+ }
+}
+
+void gSetErrorType(int errorType)
+{
+ if (gErrorType != NO_ERROR)
+ return; // not yet caught.
+ gErrorType = errorType;
+}
+
+int gGetErrorType()
+{
+ return gErrorType;
+}
+
+void gClearError()
+{
+ gErrorString()->clear();
+ gErrorType = NO_ERROR;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+PhononAutoReleasePool::PhononAutoReleasePool()
+{
+ pool = (void*)[[NSAutoreleasePool alloc] init];
+}
+
+PhononAutoReleasePool::~PhononAutoReleasePool()
+{
+ [(NSAutoreleasePool*)pool release];
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+QString PhononCFString::toQString(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);
+}
+
+PhononCFString::operator QString() const
+{
+ if (string.isEmpty() && type)
+ const_cast<PhononCFString*>(this)->string = toQString(type);
+ return string;
+}
+
+CFStringRef PhononCFString::toCFStringRef(const QString &string)
+{
+ return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
+ string.length());
+}
+
+PhononCFString::operator CFStringRef() const
+{
+ if (!type)
+ const_cast<PhononCFString*>(this)->type = toCFStringRef(string);
+ return type;
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/backendinfo.h b/src/3rdparty/phonon/qt7/backendinfo.h
new file mode 100644
index 0000000..c30cda3
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendinfo.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_BACKENDINFO_H
+#define Phonon_QT7_BACKENDINFO_H
+
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class BackendInfo
+ {
+ public:
+ enum Scope {In, Out};
+
+ static QString quickTimeVersionString();
+ static bool isQuickTimeVersionAvailable(int minHexVersion);
+ static QStringList quickTimeMimeTypes(Scope scope);
+ static QStringList quickTimeCompressionFormats();
+ static QStringList coreAudioCodecs(Scope scope);
+ static QStringList coreAudioFileTypes(Scope scope);
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_BACKENDINFO_H
diff --git a/src/3rdparty/phonon/qt7/backendinfo.mm b/src/3rdparty/phonon/qt7/backendinfo.mm
new file mode 100644
index 0000000..d84e014
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/backendinfo.mm
@@ -0,0 +1,311 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
+#include "backendinfo.h"
+#include "backendheader.h"
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AudioUnit/AudioUnit.h>
+#include <CoreServices/CoreServices.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QString BackendInfo::quickTimeVersionString()
+{
+ SInt32 version;
+ OSStatus err = Gestalt(gestaltQuickTimeVersion, &version);
+ if (err != noErr)
+ return QString("00.0.0.0000");
+ QString versionString = QString("%1%2.%3.%4.%5%6%7%8")
+ .arg((version >> (7*4)) & 0xF)
+ .arg((version >> (6*4)) & 0xF)
+ .arg((version >> (5*4)) & 0xF)
+ .arg((version >> (4*4)) & 0xF)
+ .arg((version >> (3*4)) & 0xF)
+ .arg((version >> (2*4)) & 0xF)
+ .arg((version >> (1*4)) & 0xF)
+ .arg((version >> (0*4)) & 0xF);
+ return versionString;
+}
+
+bool BackendInfo::isQuickTimeVersionAvailable(int minHexVersion)
+{
+ // minHexVersion == 0x0741 means version 7.4.1
+ SInt32 qtHexVersion;
+ OSStatus err = Gestalt(gestaltQuickTimeVersion, &qtHexVersion);
+ return (err == noErr) ? ((qtHexVersion >> 16) >= minHexVersion) : 0;
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+static QString getMimeTypeTag(QTAtomContainer mimeList, int index, OSType type)
+{
+ QTAtom mimeAtom = QTFindChildByIndex(mimeList, kParentAtomIsContainer, type, index, 0);
+ char mimeCharArray[256];
+ long length;
+ OSStatus err = QTCopyAtomDataToPtr(mimeList, mimeAtom, true, sizeof(mimeCharArray)-1, mimeCharArray, &length);
+ if (err == noErr)
+ return QString::fromAscii(mimeCharArray, length);
+ return QString();
+}
+#endif // QUICKTIME_C_API_AVAILABLE
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+QStringList BackendInfo::quickTimeMimeTypes(Scope scope)
+{
+ QStringList mimeTypes;
+ ARGUMENT_UNSUPPORTED(scope, Out, NORMAL_ERROR, mimeTypes)
+
+ ComponentDescription description;
+ description.componentType = MovieImportType;
+ description.componentSubType = 0;
+ description.componentManufacturer = 0;
+ description.componentFlags = hasMovieImportMIMEList | canMovieImportFiles;
+ description.componentFlagsMask = canMovieImportFiles | movieImportSubTypeIsFileExtension | hasMovieImportMIMEList;
+ Component component = FindNextComponent(0, &description);
+
+ while (component) {
+ QTAtomContainer mimeList = 0;
+ OSStatus err = MovieImportGetMIMETypeList((MovieImportComponent)component, &mimeList);
+ if (err == noErr){
+ int count = QTCountChildrenOfType(mimeList, kParentAtomIsContainer, 0);
+ for (int i=1; i<=count; ++i){
+ QString mimeType = getMimeTypeTag(mimeList, i, kMimeInfoMimeTypeTag);
+ if (mimeType.startsWith(QLatin1String("audio")) || mimeType.startsWith(QLatin1String("video"))){
+ if (err == noErr && !mimeType.isEmpty())
+ mimeTypes << mimeType;
+ }
+ }
+ }
+ QTDisposeAtomContainer(mimeList);
+ component = FindNextComponent(component, &description);
+ }
+ mimeTypes.sort();
+ return mimeTypes;
+}
+
+#else // QUICKTIME_C_API_AVAILABLE == false
+
+QString mimeForExtensionAudio(const QString &ext)
+{
+ if (ext == "3g2") return QLatin1String("audio/3g2");
+ if (ext == "3gp") return QLatin1String("audio/3gp");
+ if (ext == "aac") return QLatin1String("audio/aac");
+ if (ext == "ac3") return QLatin1String("audio/ac3");
+ if (ext == "aif") return QLatin1String("audio/aif");
+ if (ext == "aifc") return QLatin1String("audio/aifc");
+ if (ext == "aiff") return QLatin1String("audio/aiff");
+ if (ext == "amr") return QLatin1String("audio/amr");
+ if (ext == "au") return QLatin1String("audio/au");
+ if (ext == "bwf") return QLatin1String("audio/bwf");
+ if (ext == "caf") return QLatin1String("audio/caf");
+ if (ext == "cdda") return QLatin1String("audio/cdda");
+ if (ext == "gsm") return QLatin1String("audio/gsm");
+ if (ext == "kar") return QLatin1String("audio/kar");
+ if (ext == "m1a") return QLatin1String("audio/m1a");
+ if (ext == "m1s") return QLatin1String("audio/m1s");
+ if (ext == "m3u") return QLatin1String("audio/m3u");
+ if (ext == "m3url") return QLatin1String("audio/m3url");
+ if (ext == "mid") return QLatin1String("audio/mid");
+ if (ext == "midi") return QLatin1String("audio/midi");
+ if (ext == "mka") return QLatin1String("audio/mka");
+ if (ext == "mp3") return QLatin1String("audio/mp3");
+ if (ext == "mp4") return QLatin1String("audio/mp4");
+ if (ext == "mpa") return QLatin1String("audio/mpa");
+ if (ext == "mpeg") return QLatin1String("audio/mpeg");
+ if (ext == "mpg") return QLatin1String("audio/mpg");
+ if (ext == "mpg4") return QLatin1String("audio/mpg4");
+ if (ext == "mpm") return QLatin1String("audio/mpm");
+ if (ext == "qcp") return QLatin1String("audio/qcp");
+ if (ext == "sd2") return QLatin1String("audio/sd2");
+ if (ext == "smf") return QLatin1String("audio/smf");
+ if (ext == "snd") return QLatin1String("audio/snd");
+ if (ext == "ulw") return QLatin1String("audio/ulw");
+ if (ext == "wav") return QLatin1String("audio/wav");
+ if (ext == "wax") return QLatin1String("audio/wax");
+ if (ext == "wma") return QLatin1String("audio/wma");
+ return QString();
+}
+
+QString mimeForExtensionVideo(const QString &ext)
+{
+ if (ext == "3g2") return QLatin1String("video/3g2");
+ if (ext == "3gp") return QLatin1String("video/3gp");
+ if (ext == "asf") return QLatin1String("video/asf");
+ if (ext == "asx") return QLatin1String("video/asx");
+ if (ext == "avi") return QLatin1String("video/avi");
+ if (ext == "dif") return QLatin1String("video/dif");
+ if (ext == "dv") return QLatin1String("video/dv");
+ if (ext == "flc") return QLatin1String("video/flc");
+ if (ext == "fli") return QLatin1String("video/fli");
+ if (ext == "m15") return QLatin1String("video/m15");
+ if (ext == "m1a") return QLatin1String("video/m1a");
+ if (ext == "m1s") return QLatin1String("video/m1s");
+ if (ext == "m1v") return QLatin1String("video/m1v");
+ if (ext == "m75") return QLatin1String("video/m75");
+ if (ext == "mkv") return QLatin1String("video/mkv");
+ if (ext == "mp4") return QLatin1String("video/mp4");
+ if (ext == "mpa") return QLatin1String("video/mpa");
+ if (ext == "mpeg") return QLatin1String("video/mpeg");
+ if (ext == "mpg") return QLatin1String("video/mpg");
+ if (ext == "mpg4") return QLatin1String("video/mpg4");
+ if (ext == "mpm") return QLatin1String("video/mpm");
+ if (ext == "mpv") return QLatin1String("video/mpv");
+ if (ext == "vfw") return QLatin1String("video/vfw");
+ if (ext == "wm") return QLatin1String("video/wm");
+ if (ext == "wmv") return QLatin1String("video/wmv");
+ if (ext == "wmx") return QLatin1String("video/wmx");
+ if (ext == "wvx") return QLatin1String("video/wvx");
+ return QString();
+}
+
+QStringList BackendInfo::quickTimeMimeTypes(Scope scope)
+{
+ QStringList mimeTypes;
+ QStringList fileExtensions;
+ ARGUMENT_UNSUPPORTED(scope, Out, NORMAL_ERROR, mimeTypes)
+
+ PhononAutoReleasePool pool;
+ NSArray *fileTypes = [QTMovie movieFileTypes:QTIncludeAllTypes];
+ for (NSString *type in fileTypes){
+ QString formattedType = QString::fromUtf8([type UTF8String]);
+ formattedType = formattedType.remove('\'').remove('.').toLower();
+ QString audioMime = mimeForExtensionAudio(formattedType);
+ QString videoMime = mimeForExtensionVideo(formattedType);
+ if (!audioMime.isEmpty())
+ mimeTypes << audioMime;
+ if (!videoMime.isEmpty())
+ mimeTypes << videoMime;
+ if (audioMime.isEmpty() && videoMime.isEmpty())
+ fileExtensions << QLatin1String("application/x-qt-") + formattedType;
+ }
+ mimeTypes.sort();
+ fileExtensions.sort();
+ return mimeTypes + fileExtensions;
+}
+#endif // QUICKTIME_C_API_AVAILABLE
+
+QStringList BackendInfo::quickTimeCompressionFormats()
+{
+ QStringList result;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ ComponentInstance component = 0;
+ OSStatus err = OpenADefaultComponent(StandardCompressionType, StandardCompressionSubTypeAudio, &component);
+ BACKEND_ASSERT3(err == noErr, "Could not open component for retrieving awailable compression formats", NORMAL_ERROR, result)
+
+ UInt32 size;
+ err = QTGetComponentPropertyInfo(component, kQTPropertyClass_SCAudio, kQTSCAudioPropertyID_AvailableCompressionFormatNamesList, 0, &size,0);
+ BACKEND_ASSERT3(err == noErr, "Could not get awailable compression formats", NORMAL_ERROR, result)
+
+ CFArrayRef formats[size];
+ err = QTGetComponentProperty(component, kQTPropertyClass_SCAudio, kQTSCAudioPropertyID_AvailableCompressionFormatNamesList, size, &formats, &size);
+ BACKEND_ASSERT3(err == noErr, "Could not get awailable compression formats", NORMAL_ERROR, result)
+
+ CFIndex count = CFArrayGetCount(*formats);
+ for (CFIndex i=0; i<count; ++i){
+ const CFStringRef name = (const struct __CFString *) CFArrayGetValueAtIndex(*formats, i);
+ result << PhononCFString::toQString(name);
+ }
+
+#endif // QUICKTIME_C_API_AVAILABLE
+ return result;
+}
+
+
+QStringList BackendInfo::coreAudioCodecs(Scope scope)
+{
+ QStringList result;
+ UInt32 size;
+ OSStatus err;
+ OSType *formatIDs;
+
+ OSType encodersOrDecoders = (scope == In)
+ ? kAudioFormatProperty_EncodeFormatIDs : kAudioFormatProperty_DecodeFormatIDs;
+
+ err = AudioFormatGetPropertyInfo(encodersOrDecoders, 0, NULL, &size);
+ BACKEND_ASSERT3(err == noErr, "Could not get awailable decoders/encoders", NORMAL_ERROR, result)
+
+ formatIDs = (OSType*)malloc(size);
+ UInt32 numFormats = size / sizeof(OSType);
+ err = AudioFormatGetProperty(encodersOrDecoders, 0, NULL, &size, formatIDs);
+ BACKEND_ASSERT(err == noErr, "Could not get awailable decoders/encoders", NORMAL_ERROR){
+ free(formatIDs);
+ return result;
+ }
+
+ for (UInt32 i=0; i<numFormats; ++i){
+ AudioStreamBasicDescription absd;
+ memset(&absd, 0, sizeof(absd));
+ absd.mFormatID = formatIDs[i];
+
+ CFStringRef name;
+ size = sizeof(CFStringRef);
+ err = AudioFormatGetProperty(kAudioFormatProperty_FormatName, sizeof(absd), &absd, &size, &name);
+ BACKEND_ASSERT(err == noErr, "Could not get awailable decoder/encoder names", NORMAL_ERROR){
+ free(formatIDs);
+ return result;
+ }
+ result << PhononCFString::toQString(name);
+ }
+ free(formatIDs);
+ return result;
+}
+
+QStringList BackendInfo::coreAudioFileTypes(Scope scope)
+{
+ QStringList result;
+ OSStatus err;
+ UInt32 propertySize;
+
+ OSType readOrwrite = (scope == In)
+ ? kAudioFileGlobalInfo_ReadableTypes : kAudioFileGlobalInfo_WritableTypes;
+
+ err = AudioFileGetGlobalInfoSize(readOrwrite, 0, NULL, &propertySize);
+ BACKEND_ASSERT3(err == noErr, "Could not get core audio file types", NORMAL_ERROR, result)
+
+ OSType *types = (OSType*)malloc(propertySize);
+ err = AudioFileGetGlobalInfo(readOrwrite, 0, NULL, &propertySize, types);
+ BACKEND_ASSERT3(err == noErr, "Could not get core audio file types", NORMAL_ERROR, result)
+
+ UInt32 numTypes = propertySize / sizeof(OSType);
+ for (UInt32 i=0; i<numTypes; ++i){
+ CFStringRef name;
+ UInt32 outSize = sizeof(name);
+ err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_FileTypeName, sizeof(OSType), types+i, &outSize, &name);
+ BACKEND_ASSERT3(err == noErr, "Could not get core audio file type names", NORMAL_ERROR, result)
+ result << PhononCFString::toQString(name);
+ }
+ return result;
+}
+
+}}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/qt7/lgpl-2.1.txt b/src/3rdparty/phonon/qt7/lgpl-2.1.txt
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/lgpl-2.1.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library 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; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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 library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/3rdparty/phonon/qt7/lgpl-3.txt b/src/3rdparty/phonon/qt7/lgpl-3.txt
new file mode 100644
index 0000000..fc8a5de
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/lgpl-3.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/3rdparty/phonon/qt7/medianode.h b/src/3rdparty/phonon/qt7/medianode.h
new file mode 100644
index 0000000..595e4da
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianode.h
@@ -0,0 +1,85 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MediaNode_H
+#define Phonon_QT7_MediaNode_H
+
+#include <QtCore/QObject>
+#include "backendheader.h"
+#include "medianodeevent.h"
+#include "audioconnection.h"
+#include "videoframe.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioNode;
+ class AudioGraph;
+ class MediaObject;
+ class AudioConnection;
+
+ class MediaNode : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ enum NodeDescriptionEnum {
+ AudioSource = 1,
+ AudioSink = 2,
+ VideoSource = 4,
+ VideoSink = 8,
+ AudioGraphNode = 16
+ };
+ Q_DECLARE_FLAGS(NodeDescription, NodeDescriptionEnum);
+
+ MediaNode(NodeDescription description, QObject *parent);
+ MediaNode(NodeDescription description, AudioNode *audioPart, QObject *parent);
+ virtual ~MediaNode();
+
+ void setAudioNode(AudioNode *audioPart);
+ bool connectToSink(MediaNode *sink);
+ bool disconnectToSink(MediaNode *sink);
+ AudioConnection *getAudioConnectionToSink(MediaNode *sink);
+
+ void notify(const MediaNodeEvent *event, bool propagate = true);
+ void sendEventToSinks(const MediaNodeEvent *event);
+ virtual void mediaNodeEvent(const MediaNodeEvent *event);
+
+ virtual void updateVideo(VideoFrame &frame);
+ AudioGraph *m_audioGraph;
+
+ AudioNode *m_audioNode;
+ QList<AudioConnection *> m_audioSinkList;
+ QList<AudioConnection *> m_audioSourceList;
+ QList<MediaNode *> m_videoSinkList;
+
+ int availableAudioInputBus();
+ int availableAudioOutputBus();
+
+ NodeDescription m_description;
+ MediaObject *m_owningMediaObject;
+ };
+
+ Q_DECLARE_OPERATORS_FOR_FLAGS(MediaNode::NodeDescription);
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_MediaNode_H
diff --git a/src/3rdparty/phonon/qt7/medianode.mm b/src/3rdparty/phonon/qt7/medianode.mm
new file mode 100644
index 0000000..00f8340
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianode.mm
@@ -0,0 +1,261 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "medianode.h"
+#include "audiograph.h"
+#include "audionode.h"
+#include "backendheader.h"
+
+#include "mediaobject.h"
+#include "audiooutput.h"
+#include "quicktimevideoplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaNode::MediaNode(NodeDescription description, QObject *parent)
+ : QObject(parent), m_audioGraph(0), m_audioNode(0), m_description(description), m_owningMediaObject(0)
+{
+}
+
+MediaNode::MediaNode(NodeDescription description, AudioNode *audioPart, QObject *parent)
+ : QObject(parent), m_audioGraph(0), m_audioNode(audioPart), m_description(description)
+{
+}
+
+void MediaNode::setAudioNode(AudioNode *audioPart)
+{
+ if (m_audioNode)
+ delete m_audioNode;
+ m_audioNode = audioPart;
+}
+
+MediaNode::~MediaNode()
+{
+ delete m_audioNode;
+ qDeleteAll(m_audioSinkList);
+}
+
+AudioConnection *MediaNode::getAudioConnectionToSink(MediaNode *sink)
+{
+ AudioConnection *connection = 0;
+ for (int i=0; i<m_audioSinkList.size(); ++i){
+ if (m_audioSinkList[i]->isBetween(this, sink)){
+ connection = m_audioSinkList[i];
+ break;
+ }
+ }
+ return connection;
+}
+
+bool MediaNode::connectToSink(MediaNode *sink)
+{
+ if ((m_description & AudioSource) && (sink->m_description & AudioSink)){
+ // Check that they don't belong to different graphs. If they do, but
+ // sink is not connected to any source, accept it:
+ if (m_owningMediaObject && sink->m_owningMediaObject
+ && m_owningMediaObject != sink->m_owningMediaObject
+ && !sink->m_audioSourceList.isEmpty()){
+ return false;
+ }
+
+ // Check that the connection doesn't already exists:
+ AudioConnection *connection = getAudioConnectionToSink(sink);
+ if (connection)
+ return true;
+
+ // Check that there are awailable input/output busses:
+ int inputBus = sink->availableAudioInputBus();
+ int outputBus = availableAudioOutputBus();
+ if (inputBus >= sink->m_audioNode->m_maxInputBusses || outputBus >= m_audioNode->m_maxOutputBusses)
+ return false;
+
+ // All OK. Create connection:
+ connection = new AudioConnection(this, outputBus, sink, inputBus);
+ m_audioSinkList << connection;
+ sink->m_audioSourceList << connection;
+
+ if (m_audioNode->m_audioGraph)
+ m_audioNode->m_audioGraph->connectLate(connection);
+
+ MediaNodeEvent event1(MediaNodeEvent::AudioSinkAdded, connection);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::AudioSourceAdded, connection);
+ sink->notify(&event2, false);
+ return true;
+ }
+
+ if ((m_description & VideoSource) && (sink->m_description & VideoSink)){
+ // Check that the connection doesn't already exists:
+ if (m_videoSinkList.contains(sink))
+ return true;
+
+ m_videoSinkList << sink;
+ MediaNodeEvent event1(MediaNodeEvent::VideoSinkAdded, sink);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::VideoSourceAdded, this);
+ sink->notify(&event2, false);
+ return true;
+ }
+
+ return false;
+}
+
+bool MediaNode::disconnectToSink(MediaNode *sink)
+{
+ if ((m_description & AudioSource) && (sink->m_description & AudioSink)){
+ AudioConnection *connection = getAudioConnectionToSink(sink);
+ if (!connection)
+ return false;
+
+ m_audioSinkList.removeOne(connection);
+ sink->m_audioSourceList.removeOne(connection);
+
+ if (m_audioNode->m_audioGraph)
+ m_audioNode->m_audioGraph->disconnectLate(connection);
+
+ MediaNodeEvent event1(MediaNodeEvent::AudioSinkRemoved, connection);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::AudioSourceRemoved, connection);
+ sink->notify(&event2, false);
+
+ delete connection;
+ return true;
+ }
+
+ if ((m_description & VideoSource) && (sink->m_description & VideoSink)){
+ m_videoSinkList.removeOne(sink);
+
+ MediaNodeEvent event1(MediaNodeEvent::VideoSinkRemoved, sink);
+ notify(&event1, false);
+ MediaNodeEvent event2(MediaNodeEvent::VideoSourceRemoved, this);
+ sink->notify(&event2, false);
+ return true;
+ }
+
+ return false;
+}
+
+int MediaNode::availableAudioInputBus()
+{
+ // Scan through all the connection <u>in</u> to this
+ // node, and find an awailable index:
+ int index = -1;
+ bool available = false;
+
+ while (!available){
+ ++index;
+ available = true;
+ for (int i=0; i<m_audioSourceList.size(); ++i){
+ if (m_audioSourceList[i]->m_sinkInputBus == index){
+ available = false;
+ break;
+ }
+ }
+ }
+ return index;
+}
+
+int MediaNode::availableAudioOutputBus()
+{
+ // Scan through all the connection <u>out</u> from this
+ // node, and find an awailable index:
+ int bus = -1;
+ bool available = false;
+
+ while (!available){
+ ++bus;
+ available = true;
+ for (int i=0; i<m_audioSinkList.size(); ++i){
+ if (m_audioSinkList[i]->m_sourceOutputBus == bus){
+ available = false;
+ break;
+ }
+ }
+ }
+ return bus;
+}
+
+void MediaNode::notify(const MediaNodeEvent *event, bool propagate)
+{
+ // Let subclass handle the event first:
+ mediaNodeEvent(event);
+
+ switch(event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ if (m_audioNode){
+ foreach(AudioConnection *connection, m_audioSinkList)
+ connection->invalidate();
+ }
+ break;
+ case MediaNodeEvent::NewAudioGraph:
+ m_audioGraph = static_cast<AudioGraph *>(event->data());
+ break;
+ case MediaNodeEvent::AudioSinkAdded:
+ case MediaNodeEvent::VideoSinkAdded:
+ if (m_owningMediaObject){
+ MediaNodeEvent e1(MediaNodeEvent::SetMediaObject, m_owningMediaObject);
+ sendEventToSinks(&e1);
+ QRect videoRect = m_owningMediaObject->videoPlayer()->videoRect();
+ MediaNodeEvent e2(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
+ sendEventToSinks(&e2);
+ }
+ break;
+ case MediaNodeEvent::SetMediaObject:
+ m_owningMediaObject = static_cast<MediaObject *>(event->data());
+ break;
+ default:
+ break;
+ }
+
+ // Inform the audio node as well:
+ if (m_audioNode)
+ m_audioNode->notify(event);
+
+ // And perhaps the sinks:
+ if (propagate)
+ sendEventToSinks(event);
+}
+
+void MediaNode::sendEventToSinks(const MediaNodeEvent *event)
+{
+ for (int i=0; i<m_audioSinkList.size(); ++i)
+ m_audioSinkList[i]->m_sink->notify(event);
+ for (int i=0; i<m_videoSinkList.size(); ++i)
+ m_videoSinkList[i]->notify(event);
+}
+
+void MediaNode::updateVideo(VideoFrame &frame){
+ for (int i=0; i<m_videoSinkList.size(); ++i)
+ m_videoSinkList[i]->updateVideo(frame);
+}
+
+void MediaNode::mediaNodeEvent(const MediaNodeEvent */*event*/)
+{
+ // Override if needed.
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_medianode.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/medianodeevent.h b/src/3rdparty/phonon/qt7/medianodeevent.h
new file mode 100644
index 0000000..ad6e212
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodeevent.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIANODEEVENT_H
+#define Phonon_QT7_MEDIANODEEVENT_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+
+ class MediaNodeEvent
+ {
+ public:
+ enum Type {
+ AudioGraphAboutToBeDeleted,
+ NewAudioGraph,
+ AudioGraphInitialized,
+ AudioGraphCannotPlay,
+ AboutToRestartAudioStream,
+ RestartAudioStreamRequest,
+ VideoSinkAdded,
+ VideoSinkRemoved,
+ AudioSinkAdded,
+ AudioSinkRemoved,
+ VideoSourceAdded,
+ VideoSourceRemoved,
+ AudioSourceAdded,
+ AudioSourceRemoved,
+ VideoOutputCountChanged,
+ VideoFrameSizeChanged,
+ SetMediaObject,
+ StartConnectionChange,
+ EndConnectionChange,
+ MediaPlaying
+ };
+
+ MediaNodeEvent(Type type, void *data = 0);
+ virtual ~MediaNodeEvent();
+ inline Type type() const{ return eventType; };
+ inline void* data() const { return eventData; };
+
+ private:
+ Type eventType;
+ void *eventData;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_MEDIANODEEVENT_H
diff --git a/src/3rdparty/phonon/qt7/medianodeevent.mm b/src/3rdparty/phonon/qt7/medianodeevent.mm
new file mode 100644
index 0000000..664fbbc
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodeevent.mm
@@ -0,0 +1,37 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "medianodeevent.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaNodeEvent::MediaNodeEvent(Type type, void *data) : eventType(type), eventData(data)
+{
+}
+
+MediaNodeEvent::~MediaNodeEvent()
+{
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/medianodevideopart.h b/src/3rdparty/phonon/qt7/medianodevideopart.h
new file mode 100644
index 0000000..fb1f89c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodevideopart.h
@@ -0,0 +1,42 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIANODEVIDEOPART_H
+#define Phonon_QT7_MEDIANODEVIDEOPART_H
+
+#include <QtCore/qnamespace.h>
+#include "backendheader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class MediaNodeVideoPart
+ {
+ public:
+ MediaNodeVideoPart();
+ virtual ~MediaNodeVideoPart();
+ virtual void updateVideo(void *ciImage) = 0;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_MEDIANODEVIDEOPART_H
diff --git a/src/3rdparty/phonon/qt7/medianodevideopart.mm b/src/3rdparty/phonon/qt7/medianodevideopart.mm
new file mode 100644
index 0000000..da060da
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/medianodevideopart.mm
@@ -0,0 +1,37 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "medianodevideopart.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaNodeVideoPart::MediaNodeVideoPart()
+{
+}
+
+MediaNodeVideoPart::~MediaNodeVideoPart()
+{
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/mediaobject.h b/src/3rdparty/phonon/qt7/mediaobject.h
new file mode 100644
index 0000000..27949ec
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobject.h
@@ -0,0 +1,171 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIAOBJECT_H
+#define Phonon_QT7_MEDIAOBJECT_H
+
+#include <QtCore/QStringList>
+#include <QtCore/QTime>
+#include <phonon/mediaobjectinterface.h>
+#include <phonon/addoninterface.h>
+
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+ class QuickTimeAudioPlayer;
+ class QuickTimeMetaData;
+ class AudioGraph;
+ class MediaObjectAudioNode;
+
+ class MediaObject : public MediaNode,
+ public Phonon::MediaObjectInterface, public Phonon::AddonInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface)
+
+ public:
+ MediaObject(QObject *parent);
+ ~MediaObject();
+
+ QStringList availableAudioStreams() const;
+ QStringList availableVideoStreams() const;
+ QStringList availableSubtitleStreams() const;
+ QString currentAudioStream(const QObject *audioPath) const;
+ QString currentVideoStream(const QObject *videoPath) const;
+ QString currentSubtitleStream(const QObject *videoPath) const;
+
+ void setCurrentAudioStream(const QString &streamName,const QObject *audioPath);
+ void setCurrentVideoStream(const QString &streamName,const QObject *videoPath);
+ void setCurrentSubtitleStream(const QString &streamName,const QObject *videoPath);
+
+ void play();
+ void pause();
+ void stop();
+ void seek(qint64 milliseconds);
+
+ qint32 tickInterval() const;
+ void setTickInterval(qint32 interval);
+ bool hasVideo() const;
+ bool isSeekable() const;
+ qint64 currentTime() const;
+ Phonon::State state() const;
+
+ QString errorString() const;
+ Phonon::ErrorType errorType() const;
+
+ qint64 totalTime() const;
+ MediaSource source() const;
+ void setSource(const MediaSource &);
+ void setNextSource(const MediaSource &source);
+ qint32 prefinishMark() const;
+ void setPrefinishMark(qint32);
+ qint32 transitionTime() const;
+ void setTransitionTime(qint32);
+ bool hasInterface(Interface interface) const;
+ QVariant interfaceCall(Interface interface, int command, const QList<QVariant> &arguments = QList<QVariant>());
+
+ QuickTimeVideoPlayer* videoPlayer() const;
+ QuickTimeAudioPlayer* audioPlayer() const;
+
+ void setVolumeOnMovie(float volume);
+ bool setAudioDeviceOnMovie(int id);
+
+ int videoOutputCount();
+
+ signals:
+ void stateChanged(Phonon::State,Phonon::State);
+ void tick(qint64);
+ void seekableChanged(bool);
+ void hasVideoChanged(bool);
+ void bufferStatus(int);
+ void finished();
+ void aboutToFinish();
+ void prefinishMarkReached(qint32);
+ void totalTimeChanged(qint64);
+ void metaDataChanged(QMultiMap<QString,QString>);
+ void currentSourceChanged(const MediaSource &newSource);
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+ bool event(QEvent *event);
+
+ private:
+ enum AudioSystem {AS_Unset, AS_Video, AS_Graph, AS_Silent} m_audioSystem;
+ Phonon::State m_state;
+
+ QuickTimeVideoPlayer *m_videoPlayer;
+ QuickTimeAudioPlayer *m_audioPlayer;
+ QuickTimeVideoPlayer *m_nextVideoPlayer;
+ QuickTimeAudioPlayer *m_nextAudioPlayer;
+ MediaObjectAudioNode *m_mediaObjectAudioNode;
+ QuickTimeMetaData *m_metaData;
+
+ qint32 m_tickInterval;
+ qint32 m_transitionTime;
+ quint32 m_prefinishMark;
+ quint32 m_currentTime;
+ float m_percentageLoaded;
+
+ int m_tickTimer;
+ int m_bufferTimer;
+ int m_rapidTimer;
+
+ bool m_waitNextSwap;
+ int m_swapTimeLeft;
+ QTime m_swapTime;
+
+ void synchAudioVideo();
+ void updateCurrentTime();
+ void swapCurrentWithNext(qint32 transitionTime);
+ bool setState(Phonon::State state);
+ void pause_internal();
+ void play_internal();
+ void setupAudioSystem();
+ void updateTimer(int &timer, int interval);
+ void bufferAudioVideo();
+ void updateRapidly();
+ void updateCrossFade();
+ void updateAudioBuffers();
+ void updateLipSynch(int allowedOffset);
+ void updateVideoFrames();
+ void updateBufferStatus();
+ void setMute(bool mute);
+ void inspectAudioGraphRecursive(AudioConnection *connection, int &effectCount, int &outputCount);
+ void inspectVideoGraphRecursive(MediaNode *node, int &effectCount, int &outputCount);
+ void inspectGraph();
+ bool isCrossFading();
+
+ QString m_errorString;
+ Phonon::ErrorType m_errorType;
+ bool checkForError();
+
+ int m_audioEffectCount;
+ int m_audioOutputCount;
+ int m_videoEffectCount;
+ int m_videoOutputCount;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_MEDIAOBJECT_H
diff --git a/src/3rdparty/phonon/qt7/mediaobject.mm b/src/3rdparty/phonon/qt7/mediaobject.mm
new file mode 100644
index 0000000..002c337
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobject.mm
@@ -0,0 +1,852 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QtCore/QEvent>
+#include "mediaobject.h"
+#include "backendheader.h"
+#include "videowidget.h"
+#include "videoframe.h"
+#include "audiooutput.h"
+#include "quicktimevideoplayer.h"
+#include "quicktimemetadata.h"
+#include "audiograph.h"
+#include "mediaobjectaudionode.h"
+#include "quicktimeaudioplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource, parent)
+{
+ m_owningMediaObject = this;
+ m_state = Phonon::LoadingState;
+
+ m_videoPlayer = new QuickTimeVideoPlayer();
+ m_audioPlayer = new QuickTimeAudioPlayer();
+ m_nextVideoPlayer = new QuickTimeVideoPlayer();
+ m_nextAudioPlayer = new QuickTimeAudioPlayer();
+ m_mediaObjectAudioNode = new MediaObjectAudioNode(m_audioPlayer, m_nextAudioPlayer);
+ setAudioNode(m_mediaObjectAudioNode);
+
+ m_metaData = new QuickTimeMetaData();
+ m_audioGraph = new AudioGraph(this);
+
+ m_tickInterval = 0;
+ m_prefinishMark = 0;
+ m_currentTime = 0;
+ m_transitionTime = 0;
+ m_percentageLoaded = 0;
+ m_waitNextSwap = false;
+ m_audioEffectCount = 0;
+ m_audioOutputCount = 0;
+ m_videoEffectCount = 0;
+ m_videoOutputCount = 0;
+ m_audioSystem = AS_Unset;
+ m_errorType = Phonon::NoError;
+
+ m_tickTimer = 0;
+ m_bufferTimer = 0;
+ m_rapidTimer = 0;
+
+ checkForError();
+}
+
+MediaObject::~MediaObject()
+{
+ // m_mediaObjectAudioNode is owned by super class.
+ m_audioPlayer->unsetVideoPlayer();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ delete m_videoPlayer;
+ delete m_nextVideoPlayer;
+ delete m_metaData;
+ checkForError();
+}
+
+bool MediaObject::setState(Phonon::State state)
+{
+ Phonon::State prevState = m_state;
+ m_state = state;
+ if (prevState != m_state){
+ emit stateChanged(m_state, prevState);
+ if (m_state != state){
+ // End-application did something
+ // upon receiving the signal.
+ return false;
+ }
+ }
+ return true;
+}
+
+void MediaObject::inspectAudioGraphRecursive(AudioConnection *connection, int &effectCount, int &outputCount)
+{
+ if ((connection->m_sink->m_description & (AudioSource | AudioSink)) == (AudioSource | AudioSink))
+ ++effectCount;
+ else if (connection->m_sink->m_description & AudioSink)
+ ++outputCount;
+
+ for (int i=0; i<connection->m_sink->m_audioSinkList.size(); ++i)
+ inspectAudioGraphRecursive(connection->m_sink->m_audioSinkList[i], effectCount, outputCount);
+}
+
+void MediaObject::inspectVideoGraphRecursive(MediaNode *node, int &effectCount, int &outputCount)
+{
+ if ((node->m_description & (VideoSource | VideoSink)) == (VideoSource | VideoSink))
+ ++effectCount;
+ else if (node->m_description & VideoSink)
+ ++outputCount;
+
+ for (int i=0; i<node->m_videoSinkList.size(); ++i)
+ inspectVideoGraphRecursive(node->m_videoSinkList[i], effectCount, outputCount);
+}
+
+void MediaObject::inspectGraph()
+{
+ // Inspect the graph to check wether there are any
+ // effects or outputs connected. This will have
+ // influence on the audio system and video system that ends up beeing used:
+ int prevVideoOutputCount = m_videoOutputCount;
+ m_audioEffectCount = 0;
+ m_audioOutputCount = 0;
+ m_videoEffectCount = 0;
+ m_videoOutputCount = 0;
+ AudioConnection rootConnection(this);
+ inspectAudioGraphRecursive(&rootConnection, m_audioEffectCount, m_audioOutputCount);
+ inspectVideoGraphRecursive(this, m_videoEffectCount, m_videoOutputCount);
+
+ if (m_videoOutputCount != prevVideoOutputCount){
+ MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount);
+ notify(&e1);
+ }
+}
+
+void MediaObject::setupAudioSystem()
+{
+ // Select which audio system to use:
+ AudioSystem newAudioSystem = AS_Unset;
+ if (!m_audioOutputCount || !m_videoPlayer->canPlayMedia()){
+ newAudioSystem = AS_Silent;
+ } else if (m_audioEffectCount == 0){
+ newAudioSystem = AS_Video;
+ } else if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_4){
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for Mac OS 10.3 and below", NORMAL_ERROR);
+ } else if (m_videoPlayer->isDrmProtected()){
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for DRM protected media", NORMAL_ERROR);
+ } else if (m_audioGraph->graphCannotPlay()){
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for the current codec", NORMAL_ERROR);
+#ifdef QUICKTIME_C_API_AVAILABLE
+ } else {
+ newAudioSystem = AS_Graph;
+ }
+#else
+ } else {
+ newAudioSystem = AS_Video;
+ SET_ERROR("Audio effects are not supported for the 64-bit version of the Phonon QT7 backend", NORMAL_ERROR);
+ }
+#endif
+
+ if (newAudioSystem == m_audioSystem)
+ return;
+
+ // Enable selected audio system:
+ m_audioSystem = newAudioSystem;
+ switch (newAudioSystem){
+ case AS_Silent:
+ m_audioGraph->stop();
+ m_videoPlayer->enableAudio(false);
+ m_nextVideoPlayer->enableAudio(false);
+ m_audioPlayer->enableAudio(false);
+ m_nextAudioPlayer->enableAudio(false);
+ break;
+ case AS_Graph:
+ if (m_state == Phonon::PausedState)
+ m_audioGraph->prepare();
+ else
+ m_audioGraph->start();
+ // Starting the graph can lead to a recursive call
+ // telling us that we must direct audio through
+ // video. If that has happened, we must not proceed:
+ if (m_audioSystem != AS_Graph)
+ return;
+ m_videoPlayer->enableAudio(false);
+ m_nextVideoPlayer->enableAudio(false);
+ m_audioPlayer->enableAudio(true);
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ m_nextAudioPlayer->enableAudio(true);
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime());
+ break;
+ case AS_Video:
+ case AS_Unset:
+ m_audioGraph->stop();
+ m_videoPlayer->enableAudio(true);
+ m_nextVideoPlayer->enableAudio(true);
+ m_audioPlayer->enableAudio(false);
+ m_nextAudioPlayer->enableAudio(false);
+ m_videoPlayer->seek(m_audioPlayer->currentTime());
+ m_nextVideoPlayer->seek(m_nextAudioPlayer->currentTime());
+ break;
+ }
+}
+
+void MediaObject::setSource(const MediaSource &source)
+{
+ IMPLEMENTED;
+ PhononAutoReleasePool pool;
+ setState(Phonon::LoadingState);
+
+ // Save current state for event/signal handling below:
+ bool prevHasVideo = m_videoPlayer->hasVideo();
+ qint64 prevTotalTime = totalTime();
+ m_waitNextSwap = false;
+
+ // Cancel cross-fade if any:
+ m_nextVideoPlayer->pause();
+ m_nextAudioPlayer->pause();
+ m_mediaObjectAudioNode->cancelCrossFade();
+
+ // Set new source:
+ m_audioPlayer->unsetVideoPlayer();
+ m_videoPlayer->setMediaSource(source);
+ m_audioPlayer->setVideoPlayer(m_videoPlayer);
+ m_metaData->setVideo(m_videoPlayer);
+
+ m_audioGraph->updateStreamSpecifications();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ m_nextVideoPlayer->unsetVideo();
+ m_currentTime = 0;
+
+ // Emit/notify information about the new source:
+ QRect videoRect = m_videoPlayer->videoRect();
+ MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
+ notify(&e1);
+
+ // Clear video widgets:
+ VideoFrame emptyFrame;
+ updateVideo(emptyFrame);
+
+ emit currentSourceChanged(source);
+ emit metaDataChanged(m_metaData->metaData());
+
+ if (prevHasVideo != m_videoPlayer->hasVideo())
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
+ if (prevTotalTime != totalTime())
+ emit totalTimeChanged(totalTime());
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->isDrmAuthorized())
+ SET_ERROR("This computer is not authorized to play current media (DRM protected).", FATAL_ERROR)
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->canPlayMedia())
+ SET_ERROR("Cannot play media.", FATAL_ERROR)
+
+ // The state might have changed from LoadingState
+ // as a response to an error state change. So we
+ // need to check it before stopping:
+ if (m_state == Phonon::LoadingState)
+ stop();
+
+ setupAudioSystem();
+ checkForError();
+}
+
+void MediaObject::setNextSource(const MediaSource &source)
+{
+ IMPLEMENTED;
+ m_nextAudioPlayer->unsetVideoPlayer();
+ m_nextVideoPlayer->setMediaSource(source);
+ m_nextAudioPlayer->setVideoPlayer(m_nextVideoPlayer);
+ checkForError();
+}
+
+void MediaObject::swapCurrentWithNext(qint32 transitionTime)
+{
+ PhononAutoReleasePool pool;
+ setState(Phonon::LoadingState);
+ // Save current state for event/signal handling below:
+ bool prevHasVideo = m_videoPlayer->hasVideo();
+ qint64 prevTotalTime = totalTime();
+
+ qSwap(m_audioPlayer, m_nextAudioPlayer);
+ qSwap(m_videoPlayer, m_nextVideoPlayer);
+ m_mediaObjectAudioNode->startCrossFade(transitionTime);
+ m_audioGraph->updateStreamSpecifications();
+ m_metaData->setVideo(m_videoPlayer);
+
+ m_waitNextSwap = false;
+ m_currentTime = 0;
+
+ // Emit/notify information about the new source:
+ QRect videoRect = m_videoPlayer->videoRect();
+ MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
+ notify(&e1);
+
+ emit currentSourceChanged(m_videoPlayer->mediaSource());
+ emit metaDataChanged(m_metaData->metaData());
+
+ if (prevHasVideo != m_videoPlayer->hasVideo())
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
+ if (prevTotalTime != totalTime())
+ emit totalTimeChanged(totalTime());
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->isDrmAuthorized())
+ SET_ERROR("This computer is not authorized to play current media (DRM protected).", FATAL_ERROR)
+ if (checkForError())
+ return;
+ if (!m_videoPlayer->canPlayMedia())
+ SET_ERROR("Cannot play next media.", FATAL_ERROR)
+
+ setupAudioSystem();
+ checkForError();
+ if (m_state == Phonon::LoadingState){
+ if (setState(Phonon::PlayingState))
+ play_internal();
+ checkForError();
+ }
+}
+
+void MediaObject::updateTimer(int &timer, int interval)
+{
+ if (timer)
+ killTimer(timer);
+ timer = 0;
+ if (interval >= 0)
+ timer = startTimer(interval);
+}
+
+void MediaObject::play_internal()
+{
+ // Play main audio/video:
+ m_videoPlayer->play();
+ m_audioPlayer->play();
+ updateLipSynch(0);
+ // Play old audio/video to finish cross-fade:
+ if (m_nextVideoPlayer->currentTime() > 0){
+ m_nextVideoPlayer->play();
+ m_nextAudioPlayer->play();
+ }
+ bufferAudioVideo();
+ updateTimer(m_rapidTimer, 100);
+}
+
+void MediaObject::pause_internal()
+{
+ m_audioGraph->stop();
+ m_audioPlayer->pause();
+ m_nextAudioPlayer->pause();
+ m_videoPlayer->pause();
+ m_nextVideoPlayer->pause();
+ updateTimer(m_rapidTimer, -1);
+ updateTimer(m_bufferTimer, -1);
+
+ if (m_waitNextSwap)
+ m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime());
+}
+
+void MediaObject::play()
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::PlayingState)
+ return;
+ if (m_waitNextSwap){
+ // update swap time after pause:
+ m_swapTime = QTime::currentTime();
+ m_swapTime.addMSecs(m_swapTimeLeft);
+ setState(Phonon::PlayingState);
+ return;
+ }
+ if (m_currentTime == m_videoPlayer->duration())
+ return;
+ if (!m_videoPlayer->canPlayMedia())
+ return;
+ if (!setState(Phonon::PlayingState))
+ return;
+ if (m_audioSystem == AS_Graph){
+ m_audioGraph->start();
+ m_mediaObjectAudioNode->setMute(true);
+ }
+ // Inform the graph that we are about to play:
+ bool playing = true;
+ MediaNodeEvent e1(MediaNodeEvent::MediaPlaying, &playing);
+ notify(&e1);
+ // Start to play:
+ play_internal();
+ m_mediaObjectAudioNode->setMute(false);
+ checkForError();
+}
+
+void MediaObject::pause()
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::PausedState)
+ return;
+ if (!setState(Phonon::PausedState))
+ return;
+ pause_internal();
+ // Inform the graph that we are no longer playing:
+ bool playing = false;
+ MediaNodeEvent e1(MediaNodeEvent::MediaPlaying, &playing);
+ notify(&e1);
+ // But be prepared:
+ if (m_audioSystem == AS_Graph)
+ m_audioGraph->prepare();
+ checkForError();
+}
+
+void MediaObject::stop()
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::StoppedState)
+ return;
+ if (!setState(Phonon::StoppedState))
+ return;
+ m_waitNextSwap = false;
+ m_nextVideoPlayer->unsetVideo();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ pause_internal();
+ seek(0);
+ checkForError();
+}
+
+void MediaObject::seek(qint64 milliseconds)
+{
+ IMPLEMENTED;
+ if (m_state == Phonon::ErrorState)
+ return;
+
+ // Stop cross-fade if any:
+ m_nextVideoPlayer->unsetVideo();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ m_mediaObjectAudioNode->cancelCrossFade();
+
+ // Seek to new position:
+ m_mediaObjectAudioNode->setMute(true);
+ m_videoPlayer->seek(milliseconds);
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ m_mediaObjectAudioNode->setMute(false);
+
+ // Update time and cancel pending swap:
+ if (m_currentTime < m_videoPlayer->duration())
+ m_waitNextSwap = false;
+
+ updateCurrentTime();
+ if (m_state != Phonon::PlayingState)
+ updateVideoFrames();
+ checkForError();
+}
+
+QStringList MediaObject::availableAudioStreams() const
+{
+ NOT_IMPLEMENTED;
+ return QStringList();
+}
+
+QStringList MediaObject::availableVideoStreams() const
+{
+ NOT_IMPLEMENTED;
+ return QStringList();
+}
+
+QStringList MediaObject::availableSubtitleStreams() const
+{
+ NOT_IMPLEMENTED;
+ return QStringList();
+}
+
+QString MediaObject::currentAudioStream(const QObject */*audioPath*/) const
+{
+ NOT_IMPLEMENTED;
+ return QString();
+}
+
+QString MediaObject::currentVideoStream(const QObject */*videoPath*/) const
+{
+ NOT_IMPLEMENTED;
+ return QString();
+}
+
+QString MediaObject::currentSubtitleStream(const QObject */*videoPath*/) const
+{
+ NOT_IMPLEMENTED;
+ return QString();
+}
+
+void MediaObject::setCurrentAudioStream(const QString &/*streamName*/,const QObject */*audioPath*/)
+{
+ NOT_IMPLEMENTED;
+}
+
+void MediaObject::setCurrentVideoStream(const QString &/*streamName*/,const QObject */*videoPath*/)
+{
+ NOT_IMPLEMENTED;
+}
+
+void MediaObject::setCurrentSubtitleStream(const QString &/*streamName*/,const QObject */*videoPath*/)
+{
+ NOT_IMPLEMENTED;
+}
+
+int MediaObject::videoOutputCount()
+{
+ return m_videoOutputCount;
+}
+
+void MediaObject::synchAudioVideo()
+{
+ if (m_state != Phonon::PlayingState)
+ return;
+ if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
+ return;
+
+ seek(m_currentTime);
+ checkForError();
+}
+
+qint32 MediaObject::tickInterval() const
+{
+ IMPLEMENTED;
+ return m_tickInterval;
+}
+
+void MediaObject::setTickInterval(qint32 interval)
+{
+ IMPLEMENTED;
+ m_tickInterval = interval;
+ if (m_tickInterval > 0)
+ m_tickTimer = startTimer(m_tickInterval);
+ else{
+ killTimer(m_tickTimer);
+ m_tickTimer = 0;
+ }
+}
+
+bool MediaObject::hasVideo() const
+{
+ IMPLEMENTED;
+ return m_videoPlayer ? m_videoPlayer->hasVideo() : false;
+}
+
+bool MediaObject::isSeekable() const
+{
+ IMPLEMENTED;
+ return m_videoPlayer ? m_videoPlayer->isSeekable() : false;
+}
+
+qint64 MediaObject::currentTime() const
+{
+ IMPLEMENTED_SILENT;
+ const_cast<MediaObject *>(this)->updateCurrentTime();
+ return m_currentTime;
+}
+
+void MediaObject::updateCurrentTime()
+{
+ quint64 lastUpdateTime = m_currentTime;
+ m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
+ quint64 total = m_videoPlayer->duration();
+
+ // Check if it's time to emit aboutToFinish:
+ quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit aboutToFinish();
+
+ // Check if it's time to emit prefinishMarkReached:
+ mark = qMax(quint64(0), total - m_prefinishMark);
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit prefinishMarkReached(total - m_currentTime);
+
+ if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
+ // There is no next source in que.
+ // Check if it's time to emit finished:
+ if (lastUpdateTime < m_currentTime && m_currentTime == total){
+ emit finished();
+ m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
+ if (m_state == Phonon::PlayingState && m_currentTime == total)
+ pause();
+ }
+ } else {
+ // We have a next source.
+ // Check if it's time to swap to next source:
+ mark = qMax(quint64(0), total + m_transitionTime);
+ if (m_waitNextSwap && m_state == Phonon::PlayingState &&
+ m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){
+ swapCurrentWithNext(0);
+ } else if (mark >= total){
+ if (lastUpdateTime < total && total == m_currentTime){
+ m_swapTime = QTime::currentTime();
+ m_swapTime.addMSecs(mark - total);
+ m_waitNextSwap = true;
+ }
+ } else if (lastUpdateTime < mark && mark <= m_currentTime){
+ swapCurrentWithNext(total - m_currentTime);
+ }
+ }
+}
+
+qint64 MediaObject::totalTime() const
+{
+ IMPLEMENTED_SILENT;
+ return m_videoPlayer->duration();
+}
+
+Phonon::State MediaObject::state() const
+{
+ IMPLEMENTED;
+ return m_state;
+}
+
+QString MediaObject::errorString() const
+{
+ IMPLEMENTED;
+ return m_errorString;
+}
+
+Phonon::ErrorType MediaObject::errorType() const
+{
+ IMPLEMENTED;
+ return m_errorType;
+}
+
+bool MediaObject::checkForError()
+{
+ int type = gGetErrorType();
+ if (type == NO_ERROR)
+ return false;
+
+ m_errorType = (type == NORMAL_ERROR) ? Phonon::NormalError : Phonon::FatalError;
+ m_errorString = gGetErrorString();
+ pause_internal();
+ gClearError();
+ setState(Phonon::ErrorState);
+ return true;
+}
+
+QuickTimeVideoPlayer* MediaObject::videoPlayer() const
+{
+ return m_videoPlayer;
+}
+
+MediaSource MediaObject::source() const
+{
+ IMPLEMENTED;
+ return m_videoPlayer->mediaSource();
+}
+
+qint32 MediaObject::prefinishMark() const
+{
+ IMPLEMENTED;
+ return m_prefinishMark;
+}
+
+void MediaObject::setPrefinishMark(qint32 mark)
+{
+ IMPLEMENTED;
+ m_prefinishMark = mark;
+}
+
+qint32 MediaObject::transitionTime() const
+{
+ IMPLEMENTED;
+ return m_transitionTime;
+}
+
+void MediaObject::setTransitionTime(qint32 transitionTime)
+{
+ IMPLEMENTED;
+ m_transitionTime = transitionTime;
+}
+
+void MediaObject::setVolumeOnMovie(float volume)
+{
+ m_videoPlayer->setMasterVolume(volume);
+ m_nextVideoPlayer->setMasterVolume(volume);
+}
+
+bool MediaObject::setAudioDeviceOnMovie(int id)
+{
+ m_nextVideoPlayer->setAudioDevice(id);
+ return m_videoPlayer->setAudioDevice(id);
+}
+
+void MediaObject::updateCrossFade()
+{
+ m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
+ // Clean-up previous movie if done fading:
+ if (m_mediaObjectAudioNode->m_fadeDuration == 0){
+ if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){
+ m_nextVideoPlayer->unsetVideo();
+ m_nextAudioPlayer->unsetVideoPlayer();
+ }
+ }
+}
+
+void MediaObject::updateBufferStatus()
+{
+ float percent = m_videoPlayer->percentageLoaded();
+ if (percent != m_percentageLoaded){
+ m_percentageLoaded = percent;
+ emit bufferStatus(m_percentageLoaded * 100);
+ }
+}
+
+void MediaObject::updateAudioBuffers()
+{
+ // Schedule audio slices:
+ m_audioPlayer->scheduleAudioToGraph();
+ m_nextAudioPlayer->scheduleAudioToGraph();
+}
+
+bool MediaObject::isCrossFading()
+{
+ return m_mediaObjectAudioNode->isCrossFading();
+}
+
+void MediaObject::updateVideoFrames()
+{
+ // Draw next frame if awailable:
+ if (m_videoPlayer->videoFrameChanged()){
+ updateLipSynch(50);
+ VideoFrame frame(m_videoPlayer);
+ if (m_nextVideoPlayer->isPlaying()
+ && m_nextVideoPlayer->hasVideo()
+ && isCrossFading()){
+ VideoFrame bgFrame(m_nextVideoPlayer);
+ frame.setBackgroundFrame(bgFrame);
+ frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1);
+ }
+
+ // Send the frame through the graph:
+ updateVideo(frame);
+ checkForError();
+ }
+}
+
+void MediaObject::updateLipSynch(int allowedOffset)
+{
+ if (m_audioSystem != AS_Graph || !m_audioGraph->isRunning())
+ return;
+ if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
+ return;
+
+ if (m_videoPlayer->hasVideo()){
+ qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime();
+ if (-allowedOffset > diff || diff > allowedOffset)
+ m_audioPlayer->seek(m_videoPlayer->currentTime());
+ }
+
+ if (isCrossFading() && m_nextVideoPlayer->hasVideo()){
+ qint64 diff = m_nextAudioPlayer->currentTime() - m_nextVideoPlayer->currentTime();
+ if (-(allowedOffset*2) > diff || diff > (allowedOffset*2))
+ m_nextAudioPlayer->seek(m_nextVideoPlayer->currentTime());
+ }
+}
+
+void MediaObject::bufferAudioVideo()
+{
+ long nextVideoUpdate = m_videoPlayer->hasVideo() ? 30 : INT_MAX;
+ long nextAudioUpdate = m_audioPlayer->regularTaskFrequency();
+ updateAudioBuffers();
+ updateVideoFrames();
+ if (m_state == Phonon::PlayingState)
+ updateTimer(m_bufferTimer, qMin(nextVideoUpdate, nextAudioUpdate));
+}
+
+void MediaObject::updateRapidly()
+{
+ updateCurrentTime();
+ updateCrossFade();
+ updateBufferStatus();
+}
+
+void MediaObject::setMute(bool mute)
+{
+ m_mediaObjectAudioNode->setMute(mute);
+ m_videoPlayer->setMute(mute);
+ m_nextVideoPlayer->setMute(mute);
+}
+
+void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::EndConnectionChange:
+ m_mediaObjectAudioNode->setMute(true);
+ inspectGraph();
+ setupAudioSystem();
+ synchAudioVideo();
+ checkForError();
+ m_mediaObjectAudioNode->setMute(false);
+ if (m_state == Phonon::PlayingState)
+ bufferAudioVideo();
+ break;
+ case MediaNodeEvent::AudioGraphCannotPlay:
+ case MediaNodeEvent::AudioGraphInitialized:
+ if (m_state != Phonon::LoadingState){
+ m_mediaObjectAudioNode->setMute(true);
+ setupAudioSystem();
+ updateLipSynch(0);
+ checkForError();
+ m_mediaObjectAudioNode->setMute(false);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+bool MediaObject::event(QEvent *event)
+{
+ switch (event->type()){
+ case QEvent::Timer: {
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
+ if (timerEvent->timerId() == m_rapidTimer)
+ updateRapidly();
+ else if (timerEvent->timerId() == m_tickTimer)
+ emit tick(currentTime());
+ else if (timerEvent->timerId() == m_bufferTimer)
+ bufferAudioVideo();
+ }
+ break;
+ default:
+ break;
+ }
+ return QObject::event(event);
+}
+
+bool MediaObject::hasInterface(Interface /*interface*/) const
+{
+ return false;
+}
+
+QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/)
+{
+ return QVariant();
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_mediaobject.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/mediaobjectaudionode.h b/src/3rdparty/phonon/qt7/mediaobjectaudionode.h
new file mode 100644
index 0000000..7939aaa
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobjectaudionode.h
@@ -0,0 +1,75 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_MEDIAOBJECTAUDIONODE_H
+#define Phonon_QT7_MEDIAOBJECTAUDIONODE_H
+
+#include <QtCore/qnamespace.h>
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeAudioPlayer;
+ class AudioMixerAudioNode;
+ class AudioConnection;
+
+ class MediaObjectAudioNode : public AudioNode
+ {
+ public:
+ MediaObjectAudioNode(QuickTimeAudioPlayer *player1, QuickTimeAudioPlayer *player2);
+ ~MediaObjectAudioNode();
+
+ // Overridden section from AudioNode:
+ void createAndConnectAUNodes();
+ void createAudioUnits();
+ void setGraph(AudioGraph *audioGraph);
+ AUNode getOutputAUNode();
+ bool fillInStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ bool setStreamSpecification(AudioConnection *connection, ConnectionSide side);
+
+ void startCrossFade(qint64 duration);
+ void updateCrossFade(qint64 currentTime);
+ void cancelCrossFade();
+ void setMute(bool mute);
+ bool isCrossFading();
+
+ QuickTimeAudioPlayer *m_player1;
+ QuickTimeAudioPlayer *m_player2;
+ AudioMixerAudioNode *m_mixer;
+
+ AudioConnection *m_connection1;
+ AudioConnection *m_connection2;
+
+ float m_fadeDuration;
+ float m_volume1;
+ float m_volume2;
+ float m_mute;
+
+ float applyCurve(float volume);
+ void updateVolume();
+
+ void mediaNodeEvent(const MediaNodeEvent *event);
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_MEDIAOBJECTAUDIONODE_H
diff --git a/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm b/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm
new file mode 100644
index 0000000..39b0d4e
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm
@@ -0,0 +1,209 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+
+#include "mediaobjectaudionode.h"
+#include "quicktimeaudioplayer.h"
+#include "quicktimevideoplayer.h"
+#include "audiomixer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+MediaObjectAudioNode::MediaObjectAudioNode(QuickTimeAudioPlayer *player1, QuickTimeAudioPlayer *player2) : AudioNode(0, 1)
+{
+ m_mute = false;
+ m_player1 = player1;
+ m_player2 = player2;
+ m_mixer = new AudioMixerAudioNode();
+
+ m_connection1 = new AudioConnection(m_player1, 0, m_mixer, 0);
+ m_connection2 = new AudioConnection(m_player2, 0, m_mixer, 1);
+
+ m_fadeDuration = 0;
+}
+
+MediaObjectAudioNode::~MediaObjectAudioNode()
+{
+ setGraph(0);
+ delete m_player1;
+ delete m_player2;
+ delete m_mixer;
+ delete m_connection1;
+ delete m_connection2;
+}
+
+void MediaObjectAudioNode::createAndConnectAUNodes()
+{
+ DEBUG_AUDIO_GRAPH("(MediaObjectAudioNode" << int(this) << "createAndConnectAUNodes called)" )
+ m_player1->createAndConnectAUNodes();
+ m_player2->createAndConnectAUNodes();
+ m_mixer->createAndConnectAUNodes();
+
+ m_connection1->connect(m_audioGraph);
+ m_connection2->connect(m_audioGraph);
+}
+
+void MediaObjectAudioNode::createAudioUnits()
+{
+ DEBUG_AUDIO_GRAPH("(MediaObjectAudioNode" << int(this) << "createAudioUnits called)" )
+ m_player1->createAudioUnits();
+ m_player2->createAudioUnits();
+ m_mixer->createAudioUnits();
+}
+
+void MediaObjectAudioNode::setGraph(AudioGraph *audioGraph)
+{
+ DEBUG_AUDIO_GRAPH("MediaObjectAudioNode" << int(this) << "is setting graph:" << int(audioGraph))
+ m_audioGraph = audioGraph;
+ m_player1->setGraph(audioGraph);
+ m_player2->setGraph(audioGraph);
+ m_mixer->setGraph(audioGraph);
+}
+
+AUNode MediaObjectAudioNode::getOutputAUNode()
+{
+ return m_mixer->getOutputAUNode();
+}
+
+bool MediaObjectAudioNode::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "fillInStreamSpecification called, role = source)")
+ return m_mixer->fillInStreamSpecification(connection, side);
+ } else {
+ DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "fillInStreamSpecification called, role = sink)")
+ return (m_connection2->updateStreamSpecification() && m_connection1->updateStreamSpecification());
+ }
+}
+
+bool MediaObjectAudioNode::setStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (side == Source){
+ DEBUG_AUDIO_STREAM("(MediaObjectAudioNode" << int(this) << "setStreamSpecification called, role = source)")
+ return m_mixer->setStreamSpecification(connection, side);
+ }
+ return true;
+}
+
+void MediaObjectAudioNode::setMute(bool mute)
+{
+ m_mute = mute;
+ m_mixer->setVolume(m_mute ? 0 : m_volume1, m_connection1->m_sinkInputBus);
+ m_mixer->setVolume(m_mute ? 0 : m_volume2, m_connection2->m_sinkInputBus);
+}
+
+void MediaObjectAudioNode::updateVolume()
+{
+ if (m_mute)
+ return;
+
+ QuickTimeVideoPlayer *player1 = static_cast<QuickTimeAudioPlayer *>(m_connection1->m_sourceAudioNode)->videoPlayer();
+ QuickTimeVideoPlayer *player2 = static_cast<QuickTimeAudioPlayer *>(m_connection2->m_sourceAudioNode)->videoPlayer();
+ if (player1)
+ player1->setRelativeVolume(m_volume1);
+ if (player2)
+ player2->setRelativeVolume(m_volume2);
+
+ m_mixer->setVolume(m_volume1, m_connection1->m_sinkInputBus);
+ m_mixer->setVolume(m_volume2, m_connection2->m_sinkInputBus);
+}
+
+void MediaObjectAudioNode::startCrossFade(qint64 duration)
+{
+ m_fadeDuration = duration;
+
+ // Swap:
+ AudioConnection *tmp = m_connection1;
+ m_connection1 = m_connection2;
+ m_connection2 = tmp;
+
+ // Init volume:
+ if (m_fadeDuration > 0){
+ m_volume1 = 0;
+ m_volume2 = 1;
+ } else {
+ m_volume1 = 1;
+ m_volume2 = 0;
+ }
+ updateVolume();
+}
+
+float MediaObjectAudioNode::applyCurve(float volume)
+{
+ float newValue = 0;
+ if (volume > 0)
+ newValue = float(0.5f * (2 + log10(volume)));
+ return newValue;
+}
+
+void MediaObjectAudioNode::updateCrossFade(qint64 currentTime)
+{
+ // Assume that currentTime starts at 0 and progress.
+ if (m_fadeDuration > 0){
+ float volume = float(currentTime) / float(m_fadeDuration);
+ if (volume >= 1){
+ volume = 1;
+ m_fadeDuration = 0;
+ }
+ m_volume1 = applyCurve(volume);
+ m_volume2 = 1 - volume;
+ updateVolume();
+ }
+}
+
+bool MediaObjectAudioNode::isCrossFading()
+{
+ return (m_fadeDuration > 0);
+}
+
+void MediaObjectAudioNode::cancelCrossFade()
+{
+ m_fadeDuration = 0;
+ m_volume1 = 1;
+ m_volume2 = 0;
+ updateVolume();
+}
+
+void MediaObjectAudioNode::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ m_connection1->invalidate();
+ m_connection2->invalidate();
+ break;
+ case MediaNodeEvent::AudioGraphCannotPlay:
+ case MediaNodeEvent::AudioGraphInitialized:
+ updateVolume();
+ break;
+ default:
+ break;
+ }
+
+ m_player1->mediaNodeEvent(event);
+ m_player2->mediaNodeEvent(event);
+ m_mixer->mediaNodeEvent(event);
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/quicktimeaudioplayer.h b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.h
new file mode 100644
index 0000000..25ddb5e
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.h
@@ -0,0 +1,112 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMEAUDIOPLAYER_H
+#define Phonon_QT7_QUICKTIMEAUDIOPLAYER_H
+
+#include "backendheader.h"
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QString>
+#include "audionode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class AudioGraph;
+ class MediaNodeEvent;
+ class QuickTimeVideoPlayer;
+
+ class QuickTimeAudioPlayer : public AudioNode
+ {
+ public:
+ enum State {Playing, Paused, NoMedia, NoState};
+
+ QuickTimeAudioPlayer();
+ virtual ~QuickTimeAudioPlayer();
+
+ void play();
+ void pause();
+ void seek(quint64 milliseconds);
+ void enableAudio(bool enable);
+ bool audioEnabled();
+ void flush();
+
+ void setVideoPlayer(QuickTimeVideoPlayer *videoPlayer);
+ void unsetVideoPlayer();
+
+ bool hasAudio();
+ bool isPlaying();
+ void scheduleAudioToGraph();
+ long regularTaskFrequency();
+ quint64 currentTime();
+ QString currentTimeString();
+ QuickTimeVideoPlayer *videoPlayer();
+
+ ComponentDescription getAudioNodeDescription() const;
+ void initializeAudioUnit();
+ bool fillInStreamSpecification(AudioConnection *connection, ConnectionSide side);
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ static bool soundPlayerIsAwailable();
+
+ private:
+ void initSoundExtraction();
+ void newGraphNotification();
+ void allocateSoundSlices();
+ void scheduleSoundSlices();
+
+ State m_state;
+ QuickTimeVideoPlayer *m_videoPlayer;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ MovieAudioExtractionRef m_audioExtractionRef;
+#endif
+
+ ScheduledAudioSlice *m_sliceList;
+ AudioChannelLayout *m_audioChannelLayout;
+ UInt32 m_audioChannelLayoutSize;
+ AudioStreamBasicDescription m_audioStreamDescription;
+
+ bool m_discrete;
+ bool m_playerUnitStarted;
+ bool m_audioExtractionComplete;
+ bool m_audioEnabled;
+ bool m_audioUnitIsReset;
+
+ long m_samplesRemaining;
+ int m_sliceCount;
+ int m_maxExtractionPacketCount;
+
+ Float64 m_sampleTimeStamp;
+ quint64 m_startTime;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMEAUDIOPLAYER_H
diff --git a/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm
new file mode 100644
index 0000000..aefec02
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm
@@ -0,0 +1,493 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+
+#include "quicktimeaudioplayer.h"
+#include "quicktimevideoplayer.h"
+#include "audiograph.h"
+#include "medianodeevent.h"
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QuickTimeAudioPlayer::QuickTimeAudioPlayer() : AudioNode(0, 1)
+{
+ m_state = NoMedia;
+ m_videoPlayer = 0;
+ m_audioChannelLayout = 0;
+ m_sliceList = 0;
+ m_sliceCount = 30;
+ m_maxExtractionPacketCount = 4096;
+ m_audioExtractionComplete = false;
+ m_audioEnabled = true;
+ m_samplesRemaining = -1;
+ m_startTime = 0;
+ m_sampleTimeStamp = 0;
+ m_audioUnitIsReset = true;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ m_audioExtractionRef = 0;
+#endif
+}
+
+QuickTimeAudioPlayer::~QuickTimeAudioPlayer()
+{
+ unsetVideoPlayer();
+}
+
+void QuickTimeAudioPlayer::unsetVideoPlayer()
+{
+ if (m_audioUnit){
+ OSStatus err = AudioUnitReset(m_audioUnit, kAudioUnitScope_Global, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not reset audio player unit when unsetting movie", FATAL_ERROR)
+ }
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_audioExtractionRef && m_videoPlayer && m_videoPlayer->hasMovie())
+ MovieAudioExtractionEnd(m_audioExtractionRef);
+ m_audioExtractionRef = 0;
+#endif
+
+ if (m_audioChannelLayout){
+ free(m_audioChannelLayout);
+ m_audioChannelLayout = 0;
+ }
+
+ if (m_sliceList){
+ for (int i=0; i<m_sliceCount; i++)
+ free(m_sliceList[i].mBufferList);
+ free(m_sliceList);
+ m_sliceList = 0;
+ }
+
+ m_videoPlayer = 0;
+ m_audioExtractionComplete = false;
+ m_samplesRemaining = -1;
+ m_sampleTimeStamp = 0;
+ m_state = NoMedia;
+}
+
+void QuickTimeAudioPlayer::enableAudio(bool enable)
+{
+ // Remember to seek after enabling audio.
+ if (enable == m_audioEnabled)
+ return;
+
+ m_audioEnabled = enable;
+ if (!enable)
+ flush();
+}
+
+bool QuickTimeAudioPlayer::audioEnabled()
+{
+ return m_audioEnabled;
+}
+
+void QuickTimeAudioPlayer::setVideoPlayer(QuickTimeVideoPlayer *videoPlayer)
+{
+ unsetVideoPlayer();
+ if (videoPlayer && videoPlayer->hasMovie()){
+ m_videoPlayer = videoPlayer;
+ initSoundExtraction();
+ allocateSoundSlices();
+ m_state = Paused;
+ seek(0);
+ }
+}
+
+QuickTimeVideoPlayer *QuickTimeAudioPlayer::videoPlayer()
+{
+ return m_videoPlayer;
+}
+
+void QuickTimeAudioPlayer::scheduleAudioToGraph()
+{
+ if (!m_videoPlayer || !m_audioEnabled || m_audioExtractionComplete || m_state != Playing)
+ return;
+
+ // Schedule audio slices, and detect if everything went OK.
+ // If not, flag the need for another audio system, but let
+ // the end app know about it:
+ gClearError();
+ scheduleSoundSlices();
+ if (gGetErrorType() != NO_ERROR){
+ gClearError();
+ if (m_audioGraph)
+ m_audioGraph->setStatusCannotPlay();
+ }
+}
+
+void QuickTimeAudioPlayer::flush()
+{
+ // Empty scheduled audio data, so playback
+ // will stop. Call seek to refill data again.
+ if (m_audioUnit){
+ m_startTime = currentTime();
+ OSStatus err = AudioUnitReset(m_audioUnit, kAudioUnitScope_Global, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not reset audio player unit on pause", FATAL_ERROR)
+ m_audioUnitIsReset = true;
+ }
+}
+
+void QuickTimeAudioPlayer::pause()
+{
+ m_state = Paused;
+ flush();
+}
+
+void QuickTimeAudioPlayer::play()
+{
+ m_state = Playing;
+ if (!m_audioEnabled)
+ return;
+ if (m_audioUnitIsReset)
+ seek(m_startTime);
+ else
+ scheduleAudioToGraph();
+}
+
+bool QuickTimeAudioPlayer::isPlaying()
+{
+ return m_videoPlayer && m_state == Playing;
+}
+
+void QuickTimeAudioPlayer::seek(quint64 milliseconds)
+{
+ if (!m_videoPlayer || !m_videoPlayer->hasMovie())
+ return;
+ if (milliseconds > m_videoPlayer->duration())
+ milliseconds = m_videoPlayer->duration();
+ if (!m_audioUnitIsReset && milliseconds == currentTime())
+ return;
+
+ m_startTime = milliseconds;
+
+ // Since the graph may be running (advancing time), there is
+ // no point in seeking if were not going to play immidiatly:
+ if (m_state != Playing)
+ return;
+ if (!m_audioUnit)
+ return;
+ if (!m_audioEnabled || !m_videoPlayer->isSeekable())
+ return;
+
+ // Reset (and stop playing):
+ OSStatus err;
+ if (!m_audioUnitIsReset){
+ err = AudioUnitReset(m_audioUnit, kAudioUnitScope_Global, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not reset audio player unit before seek", FATAL_ERROR)
+ }
+ m_sampleTimeStamp = 0;
+ for (int i = 0; i < m_sliceCount; i++)
+ m_sliceList[i].mFlags = kScheduledAudioSliceFlag_Complete;
+
+ // Start to play again immidiatly:
+ AudioTimeStamp timeStamp;
+ memset(&timeStamp, 0, sizeof(timeStamp));
+ timeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+ timeStamp.mSampleTime = -1;
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_ScheduleStartTimeStamp, kAudioUnitScope_Global,
+ 0, &timeStamp, sizeof(timeStamp));
+ BACKEND_ASSERT2(err == noErr, "Could not set schedule start time stamp on audio player unit", FATAL_ERROR)
+
+ // Seek back to 'now' in the movie:
+ TimeRecord timeRec;
+ timeRec.scale = m_videoPlayer->timeScale();
+ timeRec.base = 0;
+ timeRec.value.hi = 0;
+ timeRec.value.lo = (milliseconds / 1000.0f) * timeRec.scale;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ err = MovieAudioExtractionSetProperty(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Movie,
+ kQTMovieAudioExtractionMoviePropertyID_CurrentTime,
+ sizeof(TimeRecord), &timeRec);
+ BACKEND_ASSERT2(err == noErr, "Could not set current time on audio player unit", FATAL_ERROR)
+#endif
+
+ float durationLeftSec = float(m_videoPlayer->duration() - milliseconds) / 1000.0f;
+ m_samplesRemaining = (durationLeftSec > 0) ? (durationLeftSec * m_audioStreamDescription.mSampleRate) : -1;
+ m_audioExtractionComplete = false;
+ m_audioUnitIsReset = false;
+ scheduleAudioToGraph();
+
+}
+
+quint64 QuickTimeAudioPlayer::currentTime()
+{
+ if (!m_audioUnit){
+ if (m_videoPlayer)
+ return m_videoPlayer->currentTime();
+ else
+ return m_startTime;
+ }
+
+ Float64 currentUnitTime = getTimeInSamples(kAudioUnitProperty_CurrentPlayTime);
+ if (currentUnitTime == -1)
+ currentUnitTime = 0;
+
+ quint64 cTime = quint64(m_startTime +
+ float(currentUnitTime / float(m_audioStreamDescription.mSampleRate)) * 1000.0f);
+ return (m_videoPlayer && cTime > m_videoPlayer->duration()) ? m_videoPlayer->duration() : cTime;
+}
+
+QString QuickTimeAudioPlayer::currentTimeString()
+{
+ return QuickTimeVideoPlayer::timeToString(currentTime());
+}
+
+bool QuickTimeAudioPlayer::hasAudio()
+{
+ if (!m_videoPlayer)
+ return false;
+
+ return m_videoPlayer->hasAudio();
+}
+
+bool QuickTimeAudioPlayer::soundPlayerIsAwailable()
+{
+ QuickTimeAudioPlayer player;
+ ComponentDescription d = player.getAudioNodeDescription();
+ return FindNextComponent(0, &d);
+}
+
+ComponentDescription QuickTimeAudioPlayer::getAudioNodeDescription() const
+{
+ ComponentDescription description;
+ description.componentType = kAudioUnitType_Generator;
+ description.componentSubType = kAudioUnitSubType_ScheduledSoundPlayer;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+ description.componentFlags = 0;
+ description.componentFlagsMask = 0;
+ return description;
+}
+
+void QuickTimeAudioPlayer::initializeAudioUnit()
+{
+}
+
+bool QuickTimeAudioPlayer::fillInStreamSpecification(AudioConnection *connection, ConnectionSide side)
+{
+ if (!m_videoPlayer){
+ if (side == Source)
+ DEBUG_AUDIO_STREAM("QuickTimeAudioPlayer" << int(this) << "is source, but has no movie to use for stream spec fill.")
+ return true;
+ }
+
+ if (side == Source){
+ DEBUG_AUDIO_STREAM("QuickTimeAudioPlayer" << int(this) << "is source, and fills in stream spec from movie.")
+ connection->m_sourceStreamDescription = m_audioStreamDescription;
+ connection->m_sourceChannelLayout = (AudioChannelLayout *) malloc(m_audioChannelLayoutSize);
+ memcpy(connection->m_sourceChannelLayout, m_audioChannelLayout, m_audioChannelLayoutSize);
+ connection->m_sourceChannelLayoutSize = m_audioChannelLayoutSize;
+ connection->m_hasSourceSpecification = true;
+ }
+ return true;
+}
+
+long QuickTimeAudioPlayer::regularTaskFrequency(){
+ if (!m_audioEnabled || !m_audioUnit || (m_audioGraph && m_audioGraph->graphCannotPlay()))
+ return INT_MAX;
+
+ // Calculate how much audio in
+ // milliseconds our slices can hold:
+ int packetNeedPerSecond = m_audioStreamDescription.mSampleRate / m_maxExtractionPacketCount;
+ long bufferTimeLengthSec = float(m_sliceCount) / float(packetNeedPerSecond);
+ // Make sure we also get some time to fill the
+ // buffer, so divide the time by two:
+ return (bufferTimeLengthSec * (1000 / 2));
+}
+
+void QuickTimeAudioPlayer::initSoundExtraction()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ // Initilize the extraction:
+ OSStatus err = noErr;
+ err = MovieAudioExtractionBegin([m_videoPlayer->qtMovie() quickTimeMovie], 0, &m_audioExtractionRef);
+ BACKEND_ASSERT2(err == noErr, "Could not start audio extraction on audio player unit", FATAL_ERROR)
+ m_discrete = false;
+#if 0
+ // Extract all channels as descrete:
+ err = MovieAudioExtractionSetProperty(audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Movie,
+ kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete,
+ sizeof (discrete),
+ &discrete);
+ BACKEND_ASSERT2(err == noErr, "Could not set channels discrete on audio player unit", FATAL_ERROR)
+#endif
+
+ // Get the size of the audio channel layout (may include offset):
+ err = MovieAudioExtractionGetPropertyInfo(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Audio,
+ kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
+ 0, &m_audioChannelLayoutSize, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not get channel layout size from audio extraction", FATAL_ERROR)
+
+ // Allocate memory for the layout
+ m_audioChannelLayout = (AudioChannelLayout *) calloc(1, m_audioChannelLayoutSize);
+ BACKEND_ASSERT2(m_audioChannelLayout, "Could not allocate memory for channel layout on audio player unit", FATAL_ERROR)
+
+ // Get the layout:
+ err = MovieAudioExtractionGetProperty(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Audio,
+ kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
+ m_audioChannelLayoutSize, m_audioChannelLayout, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not get channel layout from audio extraction", FATAL_ERROR)
+
+ // Get audio stream description:
+ err = MovieAudioExtractionGetProperty(m_audioExtractionRef,
+ kQTPropertyClass_MovieAudioExtraction_Audio,
+ kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
+ sizeof(m_audioStreamDescription), &m_audioStreamDescription, 0);
+ BACKEND_ASSERT2(err == noErr, "Could not get audio stream description from audio extraction", FATAL_ERROR)
+
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeAudioPlayer::allocateSoundSlices()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ // m_sliceList will contain a specified number of ScheduledAudioSlice-s that each can
+ // carry audio from extraction, and be scheduled for playback at an audio unit.
+ // Each ScheduledAudioSlice will contain several audio buffers, one for each sound channel.
+ // Each buffer will carry (at most) a specified number of sound packets, and each packet can
+ // contain one or more frames.
+
+ // Create a list of ScheduledAudioSlices:
+ m_sliceList = (ScheduledAudioSlice *) calloc(m_sliceCount, sizeof(ScheduledAudioSlice));
+ BACKEND_ASSERT2(m_sliceList, "Could not allocate memory for audio slices", FATAL_ERROR)
+ bzero(m_sliceList, m_sliceCount * sizeof(ScheduledAudioSlice));
+
+ // Calculate the size of the different structures needed:
+ int packetsBufferSize = m_maxExtractionPacketCount * m_audioStreamDescription.mBytesPerPacket;
+ int channels = m_audioStreamDescription.mChannelsPerFrame;
+ int audioBufferListSize = int(sizeof(AudioBufferList) + (channels-1) * sizeof(AudioBuffer));
+ int mallocSize = audioBufferListSize + (packetsBufferSize * m_audioStreamDescription.mChannelsPerFrame);
+
+ // Round off to Altivec sizes:
+ packetsBufferSize = int(((packetsBufferSize + 15) / 16) * 16);
+ audioBufferListSize = int(((audioBufferListSize + 15) / 16) * 16);
+
+ for (int sliceIndex = 0; sliceIndex < m_sliceCount; ++sliceIndex){
+ // Create the memory chunk for this audio slice:
+ AudioBufferList *audioBufferList = (AudioBufferList*) calloc(1, mallocSize);
+ BACKEND_ASSERT2(audioBufferList, "Could not allocate memory for audio buffer list", FATAL_ERROR)
+
+ // The AudioBufferList contains an AudioBuffer for each channel in the audio stream:
+ audioBufferList->mNumberBuffers = m_audioStreamDescription.mChannelsPerFrame;
+ for (uint i = 0; i < audioBufferList->mNumberBuffers; ++i){
+ audioBufferList->mBuffers[i].mNumberChannels = 1;
+ audioBufferList->mBuffers[i].mData = (char *) audioBufferList + audioBufferListSize + (i * packetsBufferSize);
+ audioBufferList->mBuffers[i].mDataByteSize = packetsBufferSize;
+ }
+
+ m_sliceList[sliceIndex].mBufferList = audioBufferList;
+ m_sliceList[sliceIndex].mNumberFrames = m_maxExtractionPacketCount;
+ m_sliceList[sliceIndex].mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
+ m_sliceList[sliceIndex].mCompletionProcUserData = 0;
+ m_sliceList[sliceIndex].mCompletionProc = 0;
+ m_sliceList[sliceIndex].mFlags = kScheduledAudioSliceFlag_Complete;
+ m_sliceList[sliceIndex].mReserved = 0;
+ }
+
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeAudioPlayer::scheduleSoundSlices()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+ PhononAutoReleasePool pool;
+ // For each completed (or never used) slice, fill and schedule it.
+ for (int sliceIndex = 0; sliceIndex < m_sliceCount; ++sliceIndex){
+ if (m_sliceList[sliceIndex].mFlags & kScheduledAudioSliceFlag_Complete){
+ if (m_samplesRemaining == 0)
+ m_audioExtractionComplete = true;
+
+ if (!m_audioExtractionComplete){
+ // Determine how many samples to read:
+ int samplesCount = m_samplesRemaining;
+ if ((samplesCount > m_maxExtractionPacketCount) || (samplesCount == -1))
+ samplesCount = m_maxExtractionPacketCount;
+ m_sliceList[sliceIndex].mTimeStamp.mSampleTime = m_sampleTimeStamp;
+
+ // Reset buffer sizes:
+ int byteSize = samplesCount * m_audioStreamDescription.mBytesPerPacket;
+ for (uint i = 0; i < m_sliceList[sliceIndex].mBufferList->mNumberBuffers; ++i)
+ m_sliceList[sliceIndex].mBufferList->mBuffers[i].mDataByteSize = byteSize;
+
+ // Do the extraction:
+ UInt32 flags = 0;
+ UInt32 samplesRead = samplesCount;
+ OSStatus err = MovieAudioExtractionFillBuffer(
+ m_audioExtractionRef, &samplesRead, m_sliceList[sliceIndex].mBufferList, &flags);
+ BACKEND_ASSERT2(err == noErr, "Could not fill audio buffers from audio extraction", FATAL_ERROR)
+ m_audioExtractionComplete = (flags & kQTMovieAudioExtractionComplete);
+
+ // Play the slice:
+ if (samplesRead != 0 && m_audioUnit != 0){
+ m_sliceList[sliceIndex].mNumberFrames = samplesRead;
+ err = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_ScheduleAudioSlice, kAudioUnitScope_Global,
+ 0, &m_sliceList[sliceIndex], sizeof(ScheduledAudioSlice));
+ BACKEND_ASSERT2(err == noErr, "Could not schedule audio buffers on audio unit", FATAL_ERROR)
+ } else
+ m_sliceList[sliceIndex].mFlags = kScheduledAudioSliceFlag_Complete;
+
+ // Move the window:
+ m_sampleTimeStamp += samplesRead;
+ if (m_samplesRemaining != -1)
+ m_samplesRemaining -= samplesRead;
+ }
+ }
+ }
+
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeAudioPlayer::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::AudioGraphAboutToBeDeleted:
+ case MediaNodeEvent::AboutToRestartAudioStream:
+ case MediaNodeEvent::StartConnectionChange:
+ m_startTime = currentTime();
+ break;
+ case MediaNodeEvent::AudioGraphInitialized:
+ case MediaNodeEvent::RestartAudioStreamRequest:
+ case MediaNodeEvent::EndConnectionChange:
+ if (m_state == Playing)
+ seek(m_startTime);
+ break;
+ default:
+ break;
+ }
+}
+
+}}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.h b/src/3rdparty/phonon/qt7/quicktimemetadata.h
new file mode 100644
index 0000000..d524183
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.h
@@ -0,0 +1,67 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMEMETADATA_H
+#define Phonon_QT7_QUICKTIMEMETADATA_H
+
+#include "backendheader.h"
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QString>
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+ class QuickTimeMetaData
+ {
+ public:
+ QuickTimeMetaData();
+ virtual ~QuickTimeMetaData();
+
+ void setVideo(QuickTimeVideoPlayer *videoPlayer);
+ QMultiMap<QString, QString> metaData();
+
+ private:
+ QMultiMap<QString, QString> m_metaData;
+ bool m_movieChanged;
+ QuickTimeVideoPlayer *m_videoPlayer;
+ void readMetaData();
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QString stripCopyRightSymbol(const QString &key);
+ QString convertQuickTimeKeyToUserKey(const QString &key);
+ OSStatus readMetaValue(QTMetaDataRef, QTMetaDataItem, QTPropertyClass, QTPropertyID, QTPropertyValuePtr *, ByteCount *);
+ UInt32 getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item);
+ QString getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id);
+ void readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap<QString, QString> &result);
+#endif // QUICKTIME_C_API_AVAILABLE
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMEMETADATA_H
diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.mm b/src/3rdparty/phonon/qt7/quicktimemetadata.mm
new file mode 100644
index 0000000..4ae3e2c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.mm
@@ -0,0 +1,187 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#import <QTKit/QTMovie.h>
+
+#include "quicktimemetadata.h"
+#include "quicktimevideoplayer.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QuickTimeMetaData::QuickTimeMetaData()
+{
+ m_videoPlayer = 0;
+ m_movieChanged = false;
+}
+
+QuickTimeMetaData::~QuickTimeMetaData()
+{
+}
+
+void QuickTimeMetaData::setVideo(QuickTimeVideoPlayer *videoPlayer)
+{
+ m_videoPlayer = videoPlayer;
+ m_movieChanged = true;
+ m_metaData.clear();
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+
+QString QuickTimeMetaData::stripCopyRightSymbol(const QString &key)
+{
+ return key.right(key.length()-1);
+}
+
+QString QuickTimeMetaData::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("???");
+}
+
+OSStatus QuickTimeMetaData::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);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data value size", NORMAL_ERROR, err)
+
+ *value = malloc(propSize);
+
+ err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data value", NORMAL_ERROR, err)
+
+ if (type == 'code' || type == 'itsk' || type == 'itlk') {
+ // convert from native endian to big endian
+ OSTypePtr pType = (OSTypePtr)*value;
+ *pType = EndianU32_NtoB(*pType);
+ }
+
+ return err;
+}
+
+UInt32 QuickTimeMetaData::getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item)
+{
+ QTPropertyValuePtr value = 0;
+ ByteCount ignore = 0;
+ OSStatus err = readMetaValue(
+ metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data type", NORMAL_ERROR, 0)
+ UInt32 type = *((UInt32 *) value);
+ if (value)
+ free(value);
+ return type;
+}
+
+QString QuickTimeMetaData::getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id)
+{
+ QTPropertyValuePtr value = 0;
+ ByteCount size = 0;
+ OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size);
+ BACKEND_ASSERT3(err == noErr, "Could not read meta data item", NORMAL_ERROR, QString())
+ BACKEND_ASSERT3(value != 0, "Could not read meta data item", NORMAL_ERROR, QString())
+
+ QString string;
+ UInt32 dataType = getMetaType(metaDataRef, item);
+ switch (dataType){
+ case kQTMetaDataTypeUTF8:
+ case kQTMetaDataTypeMacEncodedText:
+ string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false));
+ break;
+ case kQTMetaDataTypeUTF16BE:
+ string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false));
+ break;
+ default:
+ break;
+ }
+
+ if (value)
+ free(value);
+ return string;
+}
+
+void QuickTimeMetaData::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 // QUICKTIME_C_API_AVAILABLE
+
+void QuickTimeMetaData::readMetaData()
+{
+ if (!m_videoPlayer)
+ return;
+ QMultiMap<QString, QString> metaMap;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTMetaDataRef metaDataRef;
+ OSStatus err = QTCopyMovieMetaData([m_videoPlayer->qtMovie() quickTimeMovie], &metaDataRef);
+ BACKEND_ASSERT2(err == noErr, "Could not read QuickTime meta data", NORMAL_ERROR)
+
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap);
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap);
+ readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap);
+#else
+ NSString *name = [m_videoPlayer->qtMovie() attributeForKey:@"QTMovieDisplayNameAttribute"];
+ metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String]));
+#endif // QUICKTIME_C_API_AVAILABLE
+
+ m_metaData.insert(QLatin1String("ARTIST"), metaMap.value(QLatin1String("ART")));
+ m_metaData.insert(QLatin1String("ALBUM"), metaMap.value(QLatin1String("alb")));
+ m_metaData.insert(QLatin1String("TITLE"), metaMap.value(QLatin1String("nam")));
+ m_metaData.insert(QLatin1String("DATE"), metaMap.value(QLatin1String("day")));
+ m_metaData.insert(QLatin1String("GENRE"), metaMap.value(QLatin1String("gnre")));
+ m_metaData.insert(QLatin1String("TRACKNUMBER"), metaMap.value(QLatin1String("trk")));
+ m_metaData.insert(QLatin1String("DESCRIPTION"), metaMap.value(QLatin1String("des")));
+}
+
+QMultiMap<QString, QString> QuickTimeMetaData::metaData()
+{
+ if (m_videoPlayer && m_videoPlayer->hasMovie() && m_movieChanged)
+ readMetaData();
+ return m_metaData;
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/quicktimestreamreader.h b/src/3rdparty/phonon/qt7/quicktimestreamreader.h
new file mode 100644
index 0000000..0e7590c
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimestreamreader.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMESTREAMREADER_H
+#define Phonon_QT7_QUICKTIMESTREAMREADER_H
+
+#include <phonon/mediasource.h>
+#include <phonon/streaminterface.h>
+#include <QtCore/QReadWriteLock>
+
+#ifndef QT_MAC_USE_COCOA
+#include <QuickTime/Movies.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeStreamReader : public QObject, Phonon::StreamInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::StreamInterface)
+
+ public:
+ QuickTimeStreamReader(const Phonon::MediaSource &source);
+ ~QuickTimeStreamReader();
+
+ int readData(long offset, long size, void *data);
+ bool readAllData();
+ QByteArray *pointerToData();
+ void writeData(const QByteArray &data);
+ void endOfData();
+ void setStreamSize(qint64 newSize);
+ qint64 streamSize() const;
+ void setStreamSeekable(bool s);
+ bool streamSeekable() const;
+ void setCurrentPos(qint64 pos);
+ qint64 currentPos() const;
+ int currentBufferSize() const;
+#ifndef QT_MAC_USE_COCOA
+ Movie movieRef();
+#endif
+
+ QByteArray m_buffer;
+ mutable QReadWriteLock m_lock;
+ bool m_seekable;
+ qint64 m_pos;
+ qint64 m_size;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMESTREAMREADER_H
diff --git a/src/3rdparty/phonon/qt7/quicktimestreamreader.mm b/src/3rdparty/phonon/qt7/quicktimestreamreader.mm
new file mode 100644
index 0000000..7131616
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimestreamreader.mm
@@ -0,0 +1,137 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backendheader.h"
+#include "quicktimestreamreader.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+QuickTimeStreamReader::QuickTimeStreamReader(const Phonon::MediaSource &source)
+{
+ connectToSource(source);
+}
+
+QuickTimeStreamReader::~QuickTimeStreamReader()
+{
+}
+
+bool QuickTimeStreamReader::readAllData()
+{
+ int oldSize = m_buffer.size();
+ while (m_buffer.size() < m_size){
+ needData();
+ if (oldSize == currentBufferSize())
+ BACKEND_ASSERT3(oldSize != currentBufferSize(),
+ "Could not create new movie from IO stream. Not enough free memory to preload the whole movie.",
+ FATAL_ERROR, false)
+ oldSize = m_buffer.size();
+ }
+ return true;
+}
+
+QByteArray *QuickTimeStreamReader::pointerToData()
+{
+ return &m_buffer;
+}
+
+int QuickTimeStreamReader::readData(long offset, long size, void *data)
+{
+// QReadLocker readLocker(&m_lock);
+ if (streamSize() != 1 && offset + size > streamSize()){
+ size = streamSize() - offset;
+ }
+
+ if (currentPos() - currentBufferSize() != offset)
+ setCurrentPos(offset);
+
+ int oldSize = currentBufferSize();
+ while (currentBufferSize() < int(size)) {
+ needData();
+ if (oldSize == currentBufferSize())
+ break;
+ oldSize = currentBufferSize();
+ }
+
+ int bytesRead = qMin(currentBufferSize(), int(size));
+// QWriteLocker writeLocker(&m_lock);
+ qMemCopy(data, m_buffer.data(), bytesRead);
+ m_buffer = m_buffer.mid(bytesRead);
+
+ return bytesRead;
+}
+
+void QuickTimeStreamReader::writeData(const QByteArray &data)
+{
+ QWriteLocker locker(&m_lock);
+ m_pos += data.size();
+ m_buffer += data;
+}
+
+void QuickTimeStreamReader::endOfData()
+{
+}
+
+void QuickTimeStreamReader::setStreamSize(qint64 newSize)
+{
+ m_size = newSize;
+}
+
+qint64 QuickTimeStreamReader::streamSize() const
+{
+ return m_size;
+}
+
+void QuickTimeStreamReader::setStreamSeekable(bool s)
+{
+ m_seekable = s;
+}
+
+bool QuickTimeStreamReader::streamSeekable() const
+{
+ return m_seekable;
+}
+
+void QuickTimeStreamReader::setCurrentPos(qint64 pos)
+{
+ QWriteLocker locker(&m_lock);
+ m_pos = pos;
+ seekStream(pos);
+ m_buffer.clear();
+}
+
+qint64 QuickTimeStreamReader::currentPos() const
+{
+ return m_pos;
+}
+
+int QuickTimeStreamReader::currentBufferSize() const
+{
+ QReadLocker locker(&m_lock);
+ return m_buffer.size();
+}
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_quicktimestreamreader.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
new file mode 100644
index 0000000..0b3aec2
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
@@ -0,0 +1,167 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_QUICKTIMEVIDEOPLAYER_H
+#define Phonon_QT7_QUICKTIMEVIDEOPLAYER_H
+
+#include "backendheader.h"
+
+#import <QTKit/QTDataReference.h>
+#import <QTKit/QTMovie.h>
+
+#include <phonon/mediasource.h>
+#include <Carbon/Carbon.h>
+#include <QtCore/QString>
+#include <QtOpenGL/QGLPixelBuffer>
+#include "videoframe.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGLContext;
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeStreamReader;
+ class VideoRenderWidgetQTMovieView;
+
+ class QuickTimeVideoPlayer : QObject
+ {
+ public:
+ enum StateEnum {
+ Playing = 0x1,
+ Paused = 0x2,
+ NoMedia = 0x4,
+ };
+ Q_DECLARE_FLAGS(State, StateEnum);
+
+ QuickTimeVideoPlayer();
+ virtual ~QuickTimeVideoPlayer();
+
+ void setMediaSource(const MediaSource &source);
+ MediaSource mediaSource() const;
+ void unsetVideo();
+
+ void play();
+ void pause();
+ void seek(quint64 milliseconds);
+
+ bool videoFrameChanged();
+ CVOpenGLTextureRef currentFrameAsCVTexture();
+ GLuint currentFrameAsGLTexture();
+ void *currentFrameAsCIImage();
+ QImage currentFrameAsQImage();
+ QRect videoRect() const;
+
+ quint64 duration() const;
+ quint64 currentTime() const;
+ long timeScale() const;
+ QString currentTimeString();
+
+ void setColors(qreal brightness = 0, qreal contrast = 1, qreal hue = 0, qreal saturation = 1);
+ void setMasterVolume(float volume);
+ void setRelativeVolume(float volume);
+ void setVolume(float masterVolume, float relativeVolume);
+ void setMute(bool mute);
+ void enableAudio(bool enable);
+ bool audioEnabled();
+ bool setAudioDevice(int id);
+ void setPlaybackRate(float rate);
+ QTMovie *qtMovie() const;
+
+ float playbackRate() const;
+ float prefferedPlaybackRate() const;
+
+ QuickTimeVideoPlayer::State state() const;
+
+ bool hasAudio() const;
+ bool hasVideo() const;
+ bool hasMovie() const;
+ bool canPlayMedia() const;
+ bool isPlaying() const;
+ bool isSeekable() const;
+ bool isDrmProtected() const;
+ bool isDrmAuthorized() const;
+
+ bool preRollMovie(qint64 startTime = 0);
+ float percentageLoaded();
+ quint64 timeLoaded();
+
+ static QString timeToString(quint64 ms);
+
+ // Help functions when drawing to more that one widget in cocoa 64:
+ void *m_primaryRenderingTarget;
+ void setPrimaryRenderingTarget(NSObject *target);
+
+ void *primaryRenderingCIImage();
+ void setPrimaryRenderingCIImage(void *ciImage);
+
+ private:
+ QTMovie *m_QTMovie;
+ State m_state;
+ QGLPixelBuffer *m_QImagePixelBuffer;
+
+ bool m_playbackRateSat;
+ bool m_isDrmProtected;
+ bool m_isDrmAuthorized;
+ bool m_mute;
+ bool m_audioEnabled;
+ bool m_hasVideo;
+ float m_masterVolume;
+ float m_relativeVolume;
+ float m_playbackRate;
+ quint64 m_currentTime;
+ MediaSource m_mediaSource;
+ void *m_primaryRenderingCIImage;
+ qreal m_brightness;
+ qreal m_contrast;
+ qreal m_hue;
+ qreal m_saturation;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTVisualContextRef m_visualContext;
+#endif
+ VideoFrame m_currentFrame;
+ QuickTimeStreamReader *m_streamReader;
+
+ void createVisualContext();
+ void openMovieFromCurrentMediaSource();
+ void openMovieFromDataRef(QTDataReference *dataRef);
+ void openMovieFromFile();
+ void openMovieFromUrl();
+ void openMovieFromStream();
+ void openMovieFromData(QByteArray *data, char *fileType);
+ void openMovieFromDataGuessType(QByteArray *data);
+ QString mediaSourcePath();
+ bool codecExistsAccordingToSuffix(const QString &fileName);
+
+ void setError(NSError *error);
+ bool errorOccured();
+ void readProtection();
+ void checkIfVideoAwailable();
+ bool movieNotLoaded();
+ void waitStatePlayable();
+ };
+
+ Q_DECLARE_OPERATORS_FOR_FLAGS(QuickTimeVideoPlayer::State);
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_QUICKTIMEVIDEOPLAYER_H
diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
new file mode 100644
index 0000000..3f76132
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
@@ -0,0 +1,955 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "quicktimevideoplayer.h"
+#include "mediaobject.h"
+#include "videowidget.h"
+#include "audiodevice.h"
+#include "quicktimestreamreader.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QEventLoop>
+#include <QtCore/QFileInfo>
+#include <QtCore/QUrl>
+#include <QtOpenGL/QGLContext>
+
+#import <QTKit/QTTrack.h>
+#import <QTKit/QTMedia.h>
+#import <QuartzCore/CIContext.h>
+#import <QuartzCore/CIFilter.h>
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+ #include <AGL/agl.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+// Defined in videowidget.cpp:
+QGLWidget *PhononSharedQGLWidget();
+
+QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0)
+{
+ m_state = NoMedia;
+ m_mediaSource = MediaSource();
+ m_QTMovie = 0;
+ m_streamReader = 0;
+ m_playbackRate = 1.0f;
+ m_masterVolume = 1.0f;
+ m_relativeVolume = 1.0f;
+ m_currentTime = 0;
+ m_mute = false;
+ m_audioEnabled = false;
+ m_hasVideo = false;
+ m_playbackRateSat = false;
+ m_isDrmProtected = false;
+ m_isDrmAuthorized = true;
+ m_primaryRenderingTarget = 0;
+ m_primaryRenderingCIImage = 0;
+ m_QImagePixelBuffer = 0;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ OSStatus err = EnterMovies();
+ BACKEND_ASSERT2(err == noErr, "Could not initialize QuickTime", FATAL_ERROR)
+ createVisualContext();
+#endif
+}
+
+QuickTimeVideoPlayer::~QuickTimeVideoPlayer()
+{
+ unsetVideo();
+ [(NSObject*)m_primaryRenderingTarget release];
+ m_primaryRenderingTarget = 0;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_visualContext)
+ CFRelease(m_visualContext);
+#endif
+}
+
+void QuickTimeVideoPlayer::createVisualContext()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ PhononSharedQGLWidget()->makeCurrent();
+
+ PhononAutoReleasePool pool;
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
+ CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
+ BACKEND_ASSERT2(cglContext, "Could not get current CoreVideo GL context (OpenGL)", FATAL_ERROR)
+ BACKEND_ASSERT2(cglPixelFormat, "Could not get current CoreVideo pixel format (OpenGL)", FATAL_ERROR)
+
+ CFTypeRef keys[] = { kQTVisualContextWorkingColorSpaceKey };
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CFDictionaryRef textureContextAttributes = CFDictionaryCreate(kCFAllocatorDefault,
+ (const void **)keys,
+ (const void **)&colorSpace, 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ OSStatus err = QTOpenGLTextureContextCreate(kCFAllocatorDefault, cglContext,
+ cglPixelFormat, textureContextAttributes, &m_visualContext);
+ CFRelease(textureContextAttributes);
+ BACKEND_ASSERT2(err == noErr, "Could not create visual context (OpenGL)", FATAL_ERROR)
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+bool QuickTimeVideoPlayer::videoFrameChanged()
+{
+ if (!m_QTMovie || !m_hasVideo)
+ return false;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_primaryRenderingTarget)
+ return true;
+ if (!m_visualContext)
+ return false;
+
+ QTVisualContextTask(m_visualContext);
+ return QTVisualContextIsNewImageAvailable(m_visualContext, 0);
+
+#elif defined(QT_MAC_USE_COCOA)
+ return true;
+
+#else
+ return false;
+#endif
+}
+
+CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (!m_visualContext)
+ return 0;
+ CVOpenGLTextureRef texture = 0;
+ OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &texture);
+ BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0)
+ return texture;
+
+#else
+ return 0;
+#endif
+}
+
+QImage QuickTimeVideoPlayer::currentFrameAsQImage()
+{
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QGLContext *prevContext = const_cast<QGLContext *>(QGLContext::currentContext());
+ CVOpenGLTextureRef texture = currentFrameAsCVTexture();
+ GLenum target = CVOpenGLTextureGetTarget(texture);
+ GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2];
+
+ if (!m_QImagePixelBuffer){
+ m_QImagePixelBuffer = new QGLPixelBuffer(videoRect().size(), QGLFormat::defaultFormat(), PhononSharedQGLWidget());
+ m_QImagePixelBuffer->makeCurrent();
+ glEnable(target);
+ glDisable(GL_BLEND);
+ glDisable(GL_CULL_FACE);
+ } else {
+ m_QImagePixelBuffer->makeCurrent();
+ }
+
+ CVOpenGLTextureGetCleanTexCoords(texture, upperLeft, upperRight, lowerRight, lowerLeft);
+ glBindTexture(target, CVOpenGLTextureGetName(texture));
+ glBegin(GL_QUADS);
+ glTexCoord2f(lowerLeft[0], lowerLeft[1]);
+ glVertex2i(-1, 1);
+ glTexCoord2f(lowerRight[0], lowerRight[1]);
+ glVertex2i(1, 1);
+ glTexCoord2f(upperRight[0], upperRight[1]);
+ glVertex2i(1, -1);
+ glTexCoord2f(upperLeft[0], upperLeft[1]);
+ glVertex2i(-1, -1);
+ glEnd();
+
+ QImage image = m_QImagePixelBuffer->toImage();
+ CVOpenGLTextureRelease(texture);
+ // Because of QuickTime, m_QImagePixelBuffer->doneCurrent() will fail.
+ // So we store, and restore, the context our selves:
+ prevContext->makeCurrent();
+ return image;
+#else
+ CIImage *img = (CIImage *)currentFrameAsCIImage();
+ if (!img)
+ return QImage();
+
+ NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
+ CGRect bounds = [img extent];
+ QImage qImg([bitmap bitmapData], bounds.size.width, bounds.size.height, QImage::Format_ARGB32);
+ QImage swapped = qImg.rgbSwapped();
+ [bitmap release];
+ [img release];
+ return swapped;
+#endif
+}
+
+void QuickTimeVideoPlayer::setPrimaryRenderingCIImage(void *ciImage)
+{
+ [(CIImage *)m_primaryRenderingCIImage release];
+ m_primaryRenderingCIImage = ciImage;
+ [(CIImage *)m_primaryRenderingCIImage retain];
+}
+
+void QuickTimeVideoPlayer::setPrimaryRenderingTarget(NSObject *target)
+{
+ [(NSObject*)m_primaryRenderingTarget release];
+ m_primaryRenderingTarget = target;
+ [(NSObject*)m_primaryRenderingTarget retain];
+}
+
+void *QuickTimeVideoPlayer::primaryRenderingCIImage()
+{
+ return m_primaryRenderingCIImage;
+}
+
+void *QuickTimeVideoPlayer::currentFrameAsCIImage()
+{
+ if (!m_QTMovie)
+ return 0;
+
+#if defined(QT_MAC_USE_COCOA)
+ if (m_primaryRenderingCIImage){
+ CIImage *img = (CIImage *)m_primaryRenderingCIImage;
+ if (m_brightness || m_contrast || m_saturation){
+ 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 retain];
+ }
+#endif
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ CVOpenGLTextureRef cvImg = currentFrameAsCVTexture();
+ CIImage *img = [[CIImage alloc] initWithCVImageBuffer:cvImg];
+ CVOpenGLTextureRelease(cvImg);
+ return img;
+#else
+ return 0;
+#endif
+}
+
+GLuint QuickTimeVideoPlayer::currentFrameAsGLTexture()
+{
+ CIImage *img = (CIImage *)currentFrameAsCIImage();
+ if (!img)
+ return 0;
+
+ NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
+ GLuint texName = 0;
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glGenTextures(1, &texName);
+ glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texName);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ int samplesPerPixel = [bitmap samplesPerPixel];
+ if (![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)){
+ glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
+ samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
+ [bitmap pixelsWide], [bitmap pixelsHigh],
+ 0, samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
+ GL_UNSIGNED_BYTE, [bitmap bitmapData]);
+ } else {
+ // Handle other bitmap formats.
+ }
+
+ [bitmap release];
+ [img release];
+ return texName;
+}
+
+void QuickTimeVideoPlayer::setMasterVolume(float volume)
+{
+ setVolume(volume, m_relativeVolume);
+}
+
+void QuickTimeVideoPlayer::setRelativeVolume(float volume)
+{
+ setVolume(m_masterVolume, volume);
+}
+
+void QuickTimeVideoPlayer::setVolume(float masterVolume, float relativeVolume)
+{
+ m_masterVolume = masterVolume;
+ m_relativeVolume = relativeVolume;
+ if (!m_QTMovie || !m_audioEnabled || m_mute)
+ return;
+ [m_QTMovie setVolume:(m_masterVolume * m_relativeVolume)];
+}
+
+void QuickTimeVideoPlayer::setMute(bool mute)
+{
+ m_mute = mute;
+ if (!m_QTMovie || m_state != Playing || !m_audioEnabled)
+ return;
+
+ // Work-around bug that happends if you set/unset mute
+ // before movie is playing, and audio is not played
+ // through graph. Then audio is delayed.
+ [m_QTMovie setMuted:mute];
+ [m_QTMovie setVolume:(mute ? 0 : m_masterVolume * m_relativeVolume)];
+}
+
+void QuickTimeVideoPlayer::enableAudio(bool enable)
+{
+ m_audioEnabled = enable;
+ if (!m_QTMovie || m_state != Playing)
+ return;
+
+ // Work-around bug that happends if you set/unset mute
+ // before movie is playing, and audio is not played
+ // through graph. Then audio is delayed.
+ [m_QTMovie setMuted:(!enable || m_mute)];
+ [m_QTMovie setVolume:((!enable || m_mute) ? 0 : m_masterVolume * m_relativeVolume)];
+}
+
+bool QuickTimeVideoPlayer::audioEnabled()
+{
+ return m_audioEnabled;
+}
+
+bool QuickTimeVideoPlayer::setAudioDevice(int id)
+{
+ if (!m_QTMovie)
+ return false;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ // The following code will not work for some media codecs that
+ // typically mingle audio/video frames (e.g mpeg).
+ CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id));
+ QTAudioContextRef context;
+ QTAudioContextCreateForAudioDevice(kCFAllocatorDefault, idString, 0, &context);
+ OSStatus err = SetMovieAudioContext([m_QTMovie quickTimeMovie], context);
+ CFRelease(context);
+ if (err != noErr)
+ return false;
+ return true;
+#else
+ Q_UNUSED(id);
+ return false;
+#endif
+}
+
+void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+{
+ if (!m_QTMovie)
+ return;
+
+ // 0 is default value for the colors
+ // in phonon, so adjust scale:
+ contrast += 1;
+ saturation += 1;
+
+ m_brightness = brightness;
+ m_contrast = contrast;
+ m_hue = hue;
+ m_saturation = saturation;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ Float32 value;
+ value = brightness;
+ SetMovieVisualBrightness([m_QTMovie quickTimeMovie], value, 0);
+ value = contrast;
+ SetMovieVisualContrast([m_QTMovie quickTimeMovie], value, 0);
+ value = hue;
+ SetMovieVisualHue([m_QTMovie quickTimeMovie], value, 0);
+ value = saturation;
+ SetMovieVisualSaturation([m_QTMovie quickTimeMovie], value, 0);
+#endif
+}
+
+QRect QuickTimeVideoPlayer::videoRect() const
+{
+ if (!m_QTMovie)
+ return QRect();
+
+ PhononAutoReleasePool pool;
+ NSSize size = [[m_QTMovie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue];
+ return QRect(0, 0, size.width, size.height);
+}
+
+void QuickTimeVideoPlayer::unsetVideo()
+{
+ if (!m_QTMovie)
+ return;
+
+ [m_QTMovie release];
+ m_QTMovie = 0;
+ delete m_streamReader;
+ m_streamReader = 0;
+ m_currentTime = 0;
+ m_state = NoMedia;
+ m_isDrmProtected = false;
+ m_isDrmAuthorized = true;
+ m_mediaSource = MediaSource();
+ [(CIImage *)m_primaryRenderingCIImage release];
+ m_primaryRenderingCIImage = 0;
+ delete m_QImagePixelBuffer;
+ m_QImagePixelBuffer = 0;
+}
+
+QuickTimeVideoPlayer::State QuickTimeVideoPlayer::state() const
+{
+ return m_state;
+}
+
+quint64 QuickTimeVideoPlayer::timeLoaded()
+{
+ if (!m_QTMovie)
+ return 0;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ TimeValue value;
+ GetMaxLoadedTimeInMovie([m_QTMovie quickTimeMovie], &value);
+ quint64 loaded = static_cast<quint64>(float(value) / float(GetMovieTimeScale([m_QTMovie quickTimeMovie])) * 1000.0f);
+ return (loaded == INT_MAX) ? 0 : loaded;
+#else
+ return 0;
+#endif
+}
+
+float QuickTimeVideoPlayer::percentageLoaded()
+{
+ if (!m_QTMovie || !isSeekable())
+ return 0;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ TimeValue loaded;
+ GetMaxLoadedTimeInMovie([m_QTMovie quickTimeMovie], &loaded);
+ float duration = GetMovieDuration([m_QTMovie quickTimeMovie]);
+ return duration ? float(loaded) / duration : 0;
+#else
+ return 0;
+#endif
+}
+
+void QuickTimeVideoPlayer::waitStatePlayable()
+{
+#if defined(QT_MAC_USE_COCOA)
+ long state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
+ while (state != QTMovieLoadStateError && state < QTMovieLoadStatePlayable)
+ state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
+#elif defined(QUICKTIME_C_API_AVAILABLE)
+ long state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
+ while (state != kMovieLoadStateError && state < kMovieLoadStatePlayable){
+ MoviesTask(0, 0);
+ state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
+ }
+#endif
+}
+
+bool QuickTimeVideoPlayer::movieNotLoaded()
+{
+ if (!m_QTMovie)
+ return true;
+
+#if defined(QT_MAC_USE_COCOA)
+ long state = [[m_QTMovie attributeForKey:@"QTMovieLoadStateAttribute"] longValue];
+ return state == QTMovieLoadStateError;
+#elif defined(QUICKTIME_C_API_AVAILABLE)
+ long state = GetMovieLoadState([m_QTMovie quickTimeMovie]);
+ return state == kMovieLoadStateError;
+#endif
+}
+
+void QuickTimeVideoPlayer::setError(NSError *error)
+{
+ if (!error)
+ return;
+ QString desc = QString::fromUtf8([[error localizedDescription] UTF8String]);
+ if (desc == "The file is not a movie file.")
+ desc = QLatin1String("Could not decode media source.");
+ else if (desc == "A necessary data reference could not be resolved."){
+ if (codecExistsAccordingToSuffix(mediaSourcePath()))
+ desc = QLatin1String("Could not locate media source.");
+ else
+ desc = QLatin1String("Could not decode media source.");
+ } else if (desc == "You do not have sufficient permissions for this operation.")
+ desc = QLatin1String("Could not open media source.");
+ SET_ERROR(desc, FATAL_ERROR)
+}
+
+bool QuickTimeVideoPlayer::errorOccured()
+{
+ if (gGetErrorType() != NO_ERROR){
+ return true;
+ } else if (movieNotLoaded()){
+ SET_ERROR("Could not open media source.", FATAL_ERROR)
+ return true;
+ }
+ return false;
+}
+
+bool QuickTimeVideoPlayer::codecExistsAccordingToSuffix(const QString &fileName)
+{
+ PhononAutoReleasePool pool;
+ NSArray *fileTypes = [QTMovie movieFileTypes:QTIncludeAllTypes];
+ for (uint i=0; i<[fileTypes count]; ++i){
+ NSString *type = [fileTypes objectAtIndex:i];
+ QString formattedType = QString::fromUtf8([type UTF8String]);
+ formattedType.remove('\'').remove('.');
+ if (fileName.endsWith(QChar('.') + formattedType, Qt::CaseInsensitive))
+ return true;
+ }
+ return false;
+}
+
+void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource)
+{
+ PhononAutoReleasePool pool;
+ unsetVideo();
+ m_mediaSource = mediaSource;
+ if (mediaSource.type() == MediaSource::Empty || mediaSource.type() == MediaSource::Invalid){
+ m_state = NoMedia;
+ return;
+ }
+ openMovieFromCurrentMediaSource();
+ if (errorOccured()){
+ unsetVideo();
+ return;
+ }
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_visualContext)
+ SetMovieVisualContext([m_QTMovie quickTimeMovie], m_visualContext);
+#endif
+
+ waitStatePlayable();
+ if (errorOccured()){
+ unsetVideo();
+ return;
+ }
+
+ readProtection();
+ preRollMovie();
+ if (errorOccured()){
+ unsetVideo();
+ return;
+ }
+
+ if (!m_playbackRateSat)
+ m_playbackRate = prefferedPlaybackRate();
+ checkIfVideoAwailable();
+ enableAudio(m_audioEnabled);
+ setMute(m_mute);
+ setVolume(m_masterVolume, m_relativeVolume);
+ pause();
+}
+
+void QuickTimeVideoPlayer::openMovieFromCurrentMediaSource()
+{
+ switch (m_mediaSource.type()){
+ case MediaSource::LocalFile:
+ openMovieFromFile();
+ break;
+ case MediaSource::Url:
+ openMovieFromUrl();
+ break;
+ case MediaSource::Disc:
+ CASE_UNSUPPORTED("Could not open media source.", FATAL_ERROR)
+ break;
+ case MediaSource::Stream:
+ openMovieFromStream();
+ break;
+ case MediaSource::Empty:
+ case MediaSource::Invalid:
+ break;
+ }
+}
+
+QString QuickTimeVideoPlayer::mediaSourcePath()
+{
+ switch (m_mediaSource.type()){
+ case MediaSource::LocalFile:{
+ QFileInfo fileInfo(m_mediaSource.fileName());
+ return fileInfo.isSymLink() ? fileInfo.symLinkTarget() : fileInfo.canonicalFilePath();
+ break;}
+ case MediaSource::Url:
+ return m_mediaSource.url().toEncoded();
+ break;
+ default:
+ break;
+ }
+ return QString();
+}
+
+void QuickTimeVideoPlayer::openMovieFromDataRef(QTDataReference *dataRef)
+{
+ PhononAutoReleasePool pool;
+ NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
+ dataRef, QTMovieDataReferenceAttribute,
+ [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,
+ [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute,
+ [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute,
+ [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute,
+ nil];
+
+ NSError *err = 0;
+ m_QTMovie = [[QTMovie movieWithAttributes:attr error:&err] retain];
+ if (err){
+ [m_QTMovie release];
+ m_QTMovie = 0;
+ setError(err);
+ }
+}
+
+void QuickTimeVideoPlayer::openMovieFromData(QByteArray *data, char *fileType)
+{
+ PhononAutoReleasePool pool;
+ NSString *type = [NSString stringWithUTF8String:fileType];
+ NSData *nsData = [NSData dataWithBytesNoCopy:data->data() length:data->size() freeWhenDone:NO];
+ QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToData:nsData name:type MIMEType:@""];
+ openMovieFromDataRef(dataRef);
+}
+
+void QuickTimeVideoPlayer::openMovieFromDataGuessType(QByteArray *data)
+{
+ // It turns out to be better to just try the standard file types rather
+ // than using e.g [QTMovie movieFileTypes:QTIncludeCommonTypes]. Some
+ // codecs *think* they can decode the stream, and crash...
+#define TryOpenMovieWithCodec(type) gClearError(); \
+ openMovieFromData(data, "."type); \
+ if (m_QTMovie) return;
+
+ TryOpenMovieWithCodec("avi");
+ TryOpenMovieWithCodec("mp4");
+ TryOpenMovieWithCodec("m4p");
+ TryOpenMovieWithCodec("m1s");
+ TryOpenMovieWithCodec("mp3");
+ TryOpenMovieWithCodec("mpeg");
+ TryOpenMovieWithCodec("mov");
+ TryOpenMovieWithCodec("ogg");
+ TryOpenMovieWithCodec("wav");
+ TryOpenMovieWithCodec("wmv");
+#undef TryOpenMovieWithCodec(type)
+}
+
+void QuickTimeVideoPlayer::openMovieFromFile()
+{
+ NSString *nsFilename = (NSString *)PhononCFString::toCFStringRef(mediaSourcePath());
+ QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFilename];
+ openMovieFromDataRef(dataRef);
+}
+
+void QuickTimeVideoPlayer::openMovieFromUrl()
+{
+ PhononAutoReleasePool pool;
+ NSString *urlString = (NSString *)PhononCFString::toCFStringRef(mediaSourcePath());
+ NSURL *url = [NSURL URLWithString: urlString];
+ QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToURL:url];
+ openMovieFromDataRef(dataRef);
+}
+
+void QuickTimeVideoPlayer::openMovieFromStream()
+{
+ m_streamReader = new QuickTimeStreamReader(m_mediaSource);
+ if (!m_streamReader->readAllData())
+ return;
+ openMovieFromDataGuessType(m_streamReader->pointerToData());
+}
+
+MediaSource QuickTimeVideoPlayer::mediaSource() const
+{
+ return m_mediaSource;
+}
+
+QTMovie *QuickTimeVideoPlayer::qtMovie() const
+{
+ return m_QTMovie;
+}
+
+void QuickTimeVideoPlayer::setPlaybackRate(float rate)
+{
+ PhononAutoReleasePool pool;
+ m_playbackRateSat = true;
+ m_playbackRate = rate;
+ if (m_QTMovie)
+ [m_QTMovie setRate:m_playbackRate];
+}
+
+float QuickTimeVideoPlayer::playbackRate() const
+{
+ return m_playbackRate;
+}
+
+quint64 QuickTimeVideoPlayer::currentTime() const
+{
+ if (!m_QTMovie || m_state == Paused)
+ return m_currentTime;
+
+ PhononAutoReleasePool pool;
+ QTTime qtTime = [m_QTMovie currentTime];
+ quint64 t = static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
+ const_cast<QuickTimeVideoPlayer *>(this)->m_currentTime = t;
+ return m_currentTime;
+}
+
+long QuickTimeVideoPlayer::timeScale() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ PhononAutoReleasePool pool;
+ return [[m_QTMovie attributeForKey:@"QTMovieTimeScaleAttribute"] longValue];
+}
+
+QString QuickTimeVideoPlayer::timeToString(quint64 ms)
+{
+ int sec = ms/1000;
+ int min = sec/60;
+ int hour = min/60;
+ return QString(QLatin1String("%1:%2:%3:%4")).arg(hour%60).arg(min%60).arg(sec%60).arg(ms%1000);
+}
+
+QString QuickTimeVideoPlayer::currentTimeString()
+{
+ return timeToString(currentTime());
+}
+
+quint64 QuickTimeVideoPlayer::duration() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ PhononAutoReleasePool pool;
+ QTTime qtTime = [m_QTMovie duration];
+ return static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f);
+}
+
+void QuickTimeVideoPlayer::play()
+{
+ if (!canPlayMedia())
+ return;
+
+ PhononAutoReleasePool pool;
+ m_state = Playing;
+ enableAudio(m_audioEnabled);
+ setMute(m_mute);
+ [m_QTMovie setRate:m_playbackRate];
+}
+
+void QuickTimeVideoPlayer::pause()
+{
+ if (!canPlayMedia())
+ return;
+
+ PhononAutoReleasePool pool;
+ currentTime();
+ m_state = Paused;
+
+ if (isSeekable())
+ [m_QTMovie setRate:0];
+ else // pretend to be paused:
+ [m_QTMovie setMuted:0];
+}
+
+void QuickTimeVideoPlayer::seek(quint64 milliseconds)
+{
+ if (!canPlayMedia() || !isSeekable() || milliseconds == currentTime())
+ return;
+ if (milliseconds > duration())
+ milliseconds = duration();
+
+ PhononAutoReleasePool pool;
+ QTTime newQTTime = [m_QTMovie currentTime];
+ newQTTime.timeValue = (milliseconds / 1000.0f) * newQTTime.timeScale;
+ [m_QTMovie setCurrentTime:newQTTime];
+
+ // The movie might not have been able to seek
+ // to the exact point we told it to. So set
+ // the current time according to what the movie says:
+ newQTTime = [m_QTMovie currentTime];
+ m_currentTime = static_cast<quint64>
+ (float(newQTTime.timeValue) / float(newQTTime.timeScale) * 1000.0f);
+
+ if (m_state == Paused){
+ // We need (for reasons unknown) to task
+ // the movie twize to make sure that
+ // a subsequent call to frameAsCvTexture
+ // returns the correct frame:
+#ifdef QUICKTIME_C_API_AVAILABLE
+ MoviesTask(0, 0);
+ MoviesTask(0, 0);
+#elif defined(QT_MAC_USE_COCOA)
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+#endif
+ }
+}
+
+bool QuickTimeVideoPlayer::canPlayMedia() const
+{
+ if (!m_QTMovie)
+ return false;
+ return m_isDrmAuthorized;
+}
+
+bool QuickTimeVideoPlayer::isPlaying() const
+{
+ return m_state == Playing;
+}
+
+bool QuickTimeVideoPlayer::isSeekable() const
+{
+ return canPlayMedia() && (duration()-1) != INT_MAX;
+}
+
+float QuickTimeVideoPlayer::prefferedPlaybackRate() const
+{
+ if (!m_QTMovie)
+ return 0;
+
+ PhononAutoReleasePool pool;
+ return [[m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
+}
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+void MoviePrePrerollCompleteCallBack(Movie /*theMovie*/, OSErr /*thePrerollErr*/, void * /*userData*/)
+{
+ // QuickTimeVideoPlayer *player = static_cast<QuickTimeVideoPlayer *>(userData);
+}
+#endif
+
+bool QuickTimeVideoPlayer::preRollMovie(qint64 startTime)
+{
+ if (!canPlayMedia())
+ return false;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (PrePrerollMovie([m_QTMovie quickTimeMovie], startTime, FloatToFixed(m_playbackRate),
+ 0 /*MoviePrePrerollCompleteCallBack*/, this) != noErr) // No callback means wait (synch)
+ return false;
+
+ if (PrerollMovie([m_QTMovie quickTimeMovie], startTime, FloatToFixed(m_playbackRate)) != noErr)
+ return false;
+
+ return true;
+#else
+ Q_UNUSED(startTime);
+ return false;
+#endif
+}
+
+bool QuickTimeVideoPlayer::hasAudio() const
+{
+ if (!m_QTMovie)
+ return false;
+
+ PhononAutoReleasePool pool;
+ return [[m_QTMovie attributeForKey:@"QTMovieHasAudioAttribute"] boolValue] == YES;
+}
+
+bool QuickTimeVideoPlayer::hasVideo() const
+{
+ return m_hasVideo;
+}
+
+bool QuickTimeVideoPlayer::hasMovie() const
+{
+ return m_QTMovie != 0;
+}
+
+void QuickTimeVideoPlayer::checkIfVideoAwailable()
+{
+ PhononAutoReleasePool pool;
+ m_hasVideo = [[m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES;
+}
+
+bool QuickTimeVideoPlayer::isDrmProtected() const
+{
+ return m_isDrmProtected;
+}
+
+bool QuickTimeVideoPlayer::isDrmAuthorized() const
+{
+ return m_isDrmAuthorized;
+}
+/*
+void QuickTimeVideoPlayer::movieCodecIsMPEG()
+{
+ NSArray *tracks = [m_QTMovie tracks];
+ for (QTTrack *track in tracks)
+ if ([[track media] hasCharacteristic:QTMediaTypeMPEG])
+ return true;
+ return false;
+}
+*/
+
+static void QtGetTrackProtection(QTTrack *track, bool &isDrmProtected, bool &isDrmAuthorized)
+{
+ isDrmProtected = false;
+ isDrmAuthorized = true;
+
+#ifdef QUICKTIME_C_API_AVAILABLE
+ QTMedia *media = [track media];
+ MediaHandler mediaHandler = GetMediaHandler([media quickTimeMedia]);
+ if (mediaHandler){
+ // Regardless, skip message boxes pointing to iTunes regarding DRM:
+ Boolean boolFalse = false;
+ QTSetComponentProperty(mediaHandler,
+ kQTPropertyClass_DRM, kQTDRMPropertyID_InteractWithUser,
+ sizeof(boolFalse), &boolFalse);
+
+ // Check track:
+ Boolean value;
+ OSStatus err = QTGetComponentProperty(mediaHandler,
+ kQTPropertyClass_DRM, kQTDRMPropertyID_IsProtected,
+ sizeof(value), &value, 0);
+ isDrmProtected = (err == noErr) ? bool(value) : false;
+ err = QTGetComponentProperty(mediaHandler,
+ kQTPropertyClass_DRM, kQTDRMPropertyID_IsAuthorized,
+ sizeof(value), &value, 0);
+ isDrmAuthorized = (err == noErr) ? bool(value) : true;
+ }
+#else
+ Q_UNUSED(track);
+#endif // QUICKTIME_C_API_AVAILABLE
+}
+
+void QuickTimeVideoPlayer::readProtection()
+{
+ m_isDrmProtected = false;
+ m_isDrmAuthorized = true;
+
+ NSArray *tracks = [m_QTMovie tracks];
+ for (uint i=0; i<[tracks count]; ++i){
+ QTTrack *track = [tracks objectAtIndex:i];
+ bool isDrmProtected = false;
+ bool isDrmAuthorized = true;
+ QtGetTrackProtection(track, isDrmProtected, isDrmAuthorized);
+ if (isDrmProtected)
+ m_isDrmProtected = true;
+ if (!isDrmAuthorized)
+ m_isDrmAuthorized = false;
+ }
+}
+
+}}
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/videoeffect.h b/src/3rdparty/phonon/qt7/videoeffect.h
new file mode 100644
index 0000000..9189a6a
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoeffect.h
@@ -0,0 +1,63 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_VIDEOEFFECT_H
+#define Phonon_QT7_VIDEOEFFECT_H
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <phonon/effectinterface.h>
+#include "medianode.h"
+#include "videoframe.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class EffectParameter;
+
+namespace QT7
+{
+ class MediaNodeEvent;
+
+ class VideoEffect : public MediaNode, public Phonon::EffectInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::EffectInterface)
+
+ public:
+ VideoEffect(int effectId, QObject *parent);
+ virtual ~VideoEffect();
+
+ QList<EffectParameter> parameters() const;
+ QVariant parameterValue(const EffectParameter &) const;
+ void setParameterValue(const EffectParameter &, const QVariant &newValue);
+
+ void updateVideo(VideoFrame &frame);
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ private:
+ int effectId;
+ void *ciFilter;
+ QString filterName;
+ };
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_VIDEOEFFECT_H
diff --git a/src/3rdparty/phonon/qt7/videoeffect.mm b/src/3rdparty/phonon/qt7/videoeffect.mm
new file mode 100644
index 0000000..c33a919
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoeffect.mm
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "videoeffect.h"
+#include "backendheader.h"
+#include "objc_help.h"
+#include <phonon/effect.h>
+#include <phonon/effectparameter.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+VideoEffect::VideoEffect(int effectId, QObject *parent) : MediaNode(VideoSink | VideoSource, 0, parent), effectId(effectId)
+{
+ ciFilter = objc_createCiFilter(effectId);
+ if (ciFilter)
+ filterName = objc_getCiFilterInfo()->filterDisplayNames[effectId];
+}
+
+VideoEffect::~VideoEffect()
+{
+ if (ciFilter)
+ objc_releaseCiFilter(ciFilter);
+}
+
+QList<EffectParameter> VideoEffect::parameters() const
+{
+ IMPLEMENTED;
+ return objc_getCiFilterParameterInfo(ciFilter).parameters;
+}
+
+QVariant VideoEffect::parameterValue(const EffectParameter &parameter) const
+{
+ IMPLEMENTED;
+ return objc_getCiFilterParameter(ciFilter, parameter.id());
+}
+
+void VideoEffect::setParameterValue(const EffectParameter &parameter, const QVariant &newValue)
+{
+ IMPLEMENTED;
+ objc_setCiFilterParameter(ciFilter, parameter.id(), newValue);
+}
+
+void VideoEffect::mediaNodeEvent(const MediaNodeEvent */*event*/)
+{
+}
+
+void VideoEffect::updateVideo(VideoFrame &frame){
+ frame.applyCoreImageFilter(ciFilter);
+ MediaNode::updateVideo(frame);
+}
+
+}}
+
+QT_END_NAMESPACE
+
+#include "moc_videoeffect.cpp"
+
diff --git a/src/3rdparty/phonon/qt7/videoframe.h b/src/3rdparty/phonon/qt7/videoframe.h
new file mode 100644
index 0000000..5069607
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoframe.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_VIDEOFRAME_H
+#define Phonon_QT7_VIDEOFRAME_H
+
+#import <QuartzCore/CVOpenGLTexture.h>
+#import <AppKit/NSImage.h>
+#undef check // avoid name clash;
+
+#include <QtCore/QRect>
+#include <QtGui/QPainter>
+#include <QtGui/QImage>
+
+QT_BEGIN_NAMESPACE
+
+class QGLContext;
+
+namespace Phonon
+{
+namespace QT7
+{
+ class QuickTimeVideoPlayer;
+ class QNSBitmapImage;
+
+ class VideoFrame
+ {
+ public:
+ VideoFrame();
+ VideoFrame(QuickTimeVideoPlayer *videoPlayer);
+ VideoFrame(const VideoFrame& frame);
+ void operator=(const VideoFrame& frame);
+ ~VideoFrame();
+
+
+ CVOpenGLTextureRef cachedCVTexture() const;
+ void *cachedCIImage() const;
+ GLuint glTextureRef() const;
+
+ void drawQImage(QPainter *p, const QRect &rect) const;
+ void drawCIImage(const CGRect &rect, float opacity = 1.0f) const;
+ void drawCIImage(const QRect &rect, float opacity = 1.0f) const;
+ void drawCVTexture(const QRect &rect, float opacity = 1.0f) const;
+ void drawGLTexture(const QRect &rect, float opacity = 1.0f) const;
+
+ void applyCoreImageFilter(void *filter);
+ void setColors(qreal brightness, qreal contrast, qreal hue, qreal saturation);
+ bool hasColorAdjustments();
+ void setBaseOpacity(qreal opacity);
+ void setBackgroundFrame(const VideoFrame &frame);
+
+ bool isEmpty();
+ QRect frameRect() const;
+ QuickTimeVideoPlayer *videoPlayer();
+
+ void retain() const;
+ void release() const;
+
+ static CGRect QRectToCGRect(const QRect & qrect);
+
+ private:
+ CVOpenGLTextureRef m_cachedCVTextureRef;
+ void *m_cachedCIImage;
+ QImage m_cachedQImage;
+ NSBitmapImageRep *m_cachedNSBitmap;
+
+ QuickTimeVideoPlayer *m_videoPlayer;
+ VideoFrame *m_backgroundFrame;
+
+ qreal m_brightness;
+ qreal m_contrast;
+ qreal m_hue;
+ qreal m_saturation;
+ qreal m_opacity;
+
+ void initMembers();
+ void copyMembers(const VideoFrame& frame);
+ void invalidateImage() const;
+ };
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
+#endif // Phonon_QT7_VIDEOFRAME_H
diff --git a/src/3rdparty/phonon/qt7/videoframe.mm b/src/3rdparty/phonon/qt7/videoframe.mm
new file mode 100644
index 0000000..92a3cd5
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videoframe.mm
@@ -0,0 +1,378 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "videoframe.h"
+#include "quicktimevideoplayer.h"
+#import <QuartzCore/CIFilter.h>
+#import <QuartzCore/CIContext.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+ VideoFrame::VideoFrame()
+ {
+ initMembers();
+ }
+
+ VideoFrame::VideoFrame(QuickTimeVideoPlayer *videoPlayer)
+ {
+ initMembers();
+ m_videoPlayer = videoPlayer;
+ }
+
+ VideoFrame::VideoFrame(const VideoFrame& frame)
+ {
+ copyMembers(frame);
+ retain();
+ }
+
+ void VideoFrame::operator=(const VideoFrame& frame)
+ {
+ if (this == &frame)
+ return;
+
+ release();
+ copyMembers(frame);
+ retain();
+ }
+
+ void VideoFrame::initMembers()
+ {
+ m_cachedCVTextureRef = 0;
+ m_cachedCIImage = 0;
+ m_cachedNSBitmap = 0;
+ m_videoPlayer = 0;
+ m_brightness = 0;
+ m_contrast = 0;
+ m_hue = 0;
+ m_saturation = 0;
+ m_opacity = 1;
+ m_backgroundFrame = 0;
+ }
+
+ void VideoFrame::copyMembers(const VideoFrame& frame)
+ {
+ m_cachedCVTextureRef = frame.m_cachedCVTextureRef;
+ m_cachedCIImage = frame.m_cachedCIImage;
+ m_cachedQImage = frame.m_cachedQImage;
+ m_cachedNSBitmap = frame.m_cachedNSBitmap;
+ m_videoPlayer = frame.m_videoPlayer;
+ m_brightness = frame.m_brightness;
+ m_contrast = frame.m_contrast;
+ m_hue = frame.m_hue;
+ m_saturation = frame.m_saturation;
+ m_opacity = frame.m_opacity;
+ m_backgroundFrame = frame.m_backgroundFrame;
+ }
+
+ VideoFrame::~VideoFrame()
+ {
+ release();
+ }
+
+ QuickTimeVideoPlayer *VideoFrame::videoPlayer()
+ {
+ return m_videoPlayer;
+ }
+
+ void VideoFrame::setBackgroundFrame(const VideoFrame &frame)
+ {
+ m_backgroundFrame = new VideoFrame(frame);
+ }
+
+ QRect VideoFrame::frameRect() const
+ {
+ return m_videoPlayer->videoRect();
+ }
+
+ CVOpenGLTextureRef VideoFrame::cachedCVTexture() const
+ {
+ if (!m_cachedCVTextureRef && m_videoPlayer){
+ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
+ (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = m_videoPlayer->currentFrameAsCVTexture();
+ }
+ return m_cachedCVTextureRef;
+ }
+
+ void *VideoFrame::cachedCIImage() const
+ {
+ if (!m_cachedCIImage && m_videoPlayer){
+ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
+ (const_cast<VideoFrame *>(this))->m_cachedCIImage = m_videoPlayer->currentFrameAsCIImage();
+ }
+ return m_cachedCIImage;
+ }
+
+ GLuint VideoFrame::glTextureRef() const
+ {
+ return CVOpenGLTextureGetName(cachedCVTexture());
+ }
+
+ void VideoFrame::setColors(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ if (m_backgroundFrame)
+ m_backgroundFrame->setColors(brightness, contrast, hue, saturation);
+ if (m_brightness == brightness
+ && m_contrast == contrast
+ && m_hue == hue
+ && m_saturation == saturation)
+ return;
+
+ m_brightness = brightness;
+ m_contrast = contrast;
+ m_hue = hue;
+ m_saturation = saturation;
+
+ invalidateImage();
+ }
+
+ CGRect VideoFrame::QRectToCGRect(const QRect & qrect)
+ {
+ CGRect cgrect;
+ cgrect.origin.x = qrect.x();
+ cgrect.origin.y = qrect.y() + qrect.height();
+ cgrect.size.width = qrect.width();
+ cgrect.size.height = -qrect.height();
+ return cgrect;
+ }
+
+ bool VideoFrame::hasColorAdjustments()
+ {
+ return (m_brightness || m_contrast || m_saturation || m_hue);
+ }
+
+ void VideoFrame::setBaseOpacity(qreal opacity)
+ {
+ m_opacity = opacity;
+ }
+
+ void VideoFrame::drawQImage(QPainter *p, const QRect &rect) const
+ {
+ if (!m_videoPlayer)
+ return;
+#ifdef QUICKTIME_C_API_AVAILABLE
+ if (m_cachedQImage.isNull()){
+ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
+ (const_cast<VideoFrame *>(this))->m_cachedQImage = m_videoPlayer->currentFrameAsQImage();
+ }
+#else
+ // Since cocoa-64 doesn't give us OpenGL textures directly, the process of converting
+ // CIImges into QImages takes time. We could still call m_videoPlayer->currentFrameAsQImage(),
+ // but because of bitmap memory management issues, and the fact that we need to swap red and
+ // blue, we can optimize the process a bit here since we are going to draw immidiatly:
+ CIImage *img = (CIImage*)cachedCIImage();
+ if (!img)
+ return;
+
+ if (!m_cachedNSBitmap){
+ (const_cast<VideoFrame *>(this))->m_cachedNSBitmap =
+ [[NSBitmapImageRep alloc] initWithCIImage:img];
+ CGRect bounds = [img extent];
+ int w = bounds.size.width;
+ int h = bounds.size.height;
+ (const_cast<VideoFrame *>(this))->m_cachedQImage =
+ QImage([m_cachedNSBitmap bitmapData], w, h, QImage::Format_ARGB32);
+ // Swap red and blue (same as QImage::rgbSwapped, but without copy)
+ for (int i=0; i<h; ++i) {
+ uint *p = (uint*) m_cachedQImage.scanLine(i);
+ uint *end = p + w;
+ while (p < end) {
+ *p = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
+ p++;
+ }
+ }
+ }
+#endif
+ p->drawImage(rect, m_cachedQImage);
+ }
+
+ void VideoFrame::drawCIImage(const QRect &rect, float opacity) const
+ {
+ drawCIImage(QRectToCGRect(rect), opacity);
+ }
+
+ void VideoFrame::drawCIImage(const CGRect &rect, float opacity) const
+ {
+ Q_UNUSED(opacity);
+ CIImage *img = (CIImage *) cachedCIImage();
+ if (!img)
+ return;
+
+ CIContext* ciContext = [[NSGraphicsContext currentContext] CIContext];
+ [ciContext drawImage:img inRect:rect fromRect:[img extent]];
+ }
+
+ void VideoFrame::drawCVTexture(const QRect &rect, float opacity) const
+ {
+ if (!m_videoPlayer)
+ return;
+ if (m_backgroundFrame)
+ m_backgroundFrame->drawCVTexture(rect, opacity);
+
+ CVOpenGLTextureRef texRef = cachedCVTexture();
+ if (!texRef)
+ return;
+
+ glPushMatrix();
+ glDisable(GL_CULL_FACE);
+ GLenum target = CVOpenGLTextureGetTarget(texRef);
+ glEnable(target);
+
+ opacity *= m_opacity;
+ if (opacity < 1){
+ glEnable(GL_BLEND);
+ glColor4f(1, 1, 1, opacity);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glColor3f(1, 1, 1);
+ glDisable(GL_BLEND);
+ }
+
+ glBindTexture(target, CVOpenGLTextureGetName(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(texRef, lowerLeft, lowerRight, upperRight, upperLeft);
+
+ glBegin(GL_QUADS);
+ 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 VideoFrame::drawGLTexture(const QRect &rect, float opacity) const
+ {
+ if (!m_videoPlayer)
+ return;
+ if (m_backgroundFrame)
+ m_backgroundFrame->drawGLTexture(rect, opacity);
+
+ GLuint texture = m_videoPlayer->currentFrameAsGLTexture();
+ if (!texture)
+ return;
+
+ glPushMatrix();
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_RECTANGLE_EXT);
+
+ opacity *= m_opacity;
+ if (opacity < 1){
+ glEnable(GL_BLEND);
+ glColor4f(1, 1, 1, opacity);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glColor3f(1, 1, 1);
+ glDisable(GL_BLEND);
+ }
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);
+ glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ QRect videoRect = m_videoPlayer->videoRect();
+ GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2];
+ lowerLeft[0] = 0;
+ lowerLeft[1] = videoRect.height();
+ lowerRight[0] = videoRect.width();
+ lowerRight[1] = videoRect.height();
+ upperRight[0] = videoRect.width();
+ upperRight[1] = 0;
+ upperLeft[0] = 0;
+ upperLeft[1] = 0;
+
+ glBegin(GL_QUADS);
+ 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();
+
+
+ // FOR NOW. FREE THE TEXTURE:
+ glDeleteTextures(1, &texture);
+ }
+
+ bool VideoFrame::isEmpty()
+ {
+ return (m_videoPlayer == 0);
+ }
+
+ void VideoFrame::invalidateImage() const
+ {
+ if (m_cachedCVTextureRef){
+ CVOpenGLTextureRelease(m_cachedCVTextureRef);
+ (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
+ }
+ if (m_cachedCIImage){
+ [(CIImage *) m_cachedCIImage release];
+ (const_cast<VideoFrame *>(this))->m_cachedCIImage = 0;
+ }
+ if (m_cachedNSBitmap){
+ [m_cachedNSBitmap release];
+ (const_cast<VideoFrame *>(this))->m_cachedNSBitmap = 0;
+ }
+ (const_cast<VideoFrame *>(this))-> m_cachedQImage = QImage();
+ }
+
+ void VideoFrame::retain() const
+ {
+ if (m_cachedCVTextureRef)
+ CVOpenGLTextureRetain(m_cachedCVTextureRef);
+ if (m_cachedCIImage)
+ [(CIImage *) m_cachedCIImage retain];
+ if (m_backgroundFrame)
+ m_backgroundFrame->retain();
+ if (m_cachedNSBitmap)
+ [m_cachedNSBitmap retain];
+ }
+
+ void VideoFrame::release() const
+ {
+ if (m_cachedCVTextureRef)
+ CVOpenGLTextureRelease(m_cachedCVTextureRef);
+ if (m_cachedCIImage)
+ [(CIImage *) m_cachedCIImage release];
+ if (m_backgroundFrame)
+ m_backgroundFrame->release();
+ if (m_cachedNSBitmap)
+ [m_cachedNSBitmap release];
+
+ (const_cast<VideoFrame *>(this))->m_backgroundFrame = 0;
+ (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
+ (const_cast<VideoFrame *>(this))->m_cachedCIImage = 0;
+ (const_cast<VideoFrame *>(this))->m_cachedNSBitmap = 0;
+ }
+
+}} //namespace Phonon::QT7
+
+QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/videowidget.h b/src/3rdparty/phonon/qt7/videowidget.h
new file mode 100644
index 0000000..8d084ec
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videowidget.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_QT7_VIDEOWIDGET_H
+#define Phonon_QT7_VIDEOWIDGET_H
+
+#include <QtGui/QPaintEngine>
+#include <phonon/videowidgetinterface.h>
+#include "medianode.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+ class MediaNodeEvent;
+ class VideoRenderWidget;
+
+ class VideoWidget : public MediaNode, public Phonon::VideoWidgetInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VideoWidgetInterface)
+
+ public:
+ VideoWidget(QObject *parent);
+ virtual ~VideoWidget();
+
+ Phonon::VideoWidget::AspectRatio aspectRatio() const;
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio);
+ qreal brightness() const;
+ void setBrightness(qreal);
+ Phonon::VideoWidget::ScaleMode scaleMode() const;
+ void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode);
+ qreal contrast() const;
+ void setContrast(qreal);
+ qreal hue() const;
+ void setHue(qreal);
+ qreal saturation() const;
+ void setSaturation(qreal);
+
+ QWidget *widget();
+
+ void updateVideo(VideoFrame &frame);
+
+ protected:
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+ private:
+ VideoRenderWidget *m_videoRenderWidget;
+ };
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#endif // Phonon_QT7_VIDEOWIDGET_H
diff --git a/src/3rdparty/phonon/qt7/videowidget.mm b/src/3rdparty/phonon/qt7/videowidget.mm
new file mode 100644
index 0000000..0600268
--- /dev/null
+++ b/src/3rdparty/phonon/qt7/videowidget.mm
@@ -0,0 +1,885 @@
+/* This file is part of the KDE project.
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+ This library 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, either version 2.1 or 3 of the License.
+
+ This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QtCore/qglobal.h>
+#ifdef QT_MAC_USE_COCOA
+#import <QTKit/QTMovieLayer.h>
+#endif
+
+#include "videowidget.h"
+#include "backendheader.h"
+#include "quicktimevideoplayer.h"
+#include "medianode.h"
+#include "medianodeevent.h"
+#include "mediaobject.h"
+
+#include <QtOpenGL/QGLWidget>
+#include <QtCore/QTime>
+#include <QtCore/QEvent>
+#include <QtCore/QCoreApplication>
+
+#import <AppKit/NSImage.h>
+#import <QTKit/QTMovieView.h>
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef QT_MAC_USE_COCOA // Rendering to a QTMovieView can only be done in Cocoa
+
+#define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];}
+
+@interface SharedQTMovieView : QTMovieView
+{
+@private
+ Phonon::QT7::QuickTimeVideoPlayer *m_player;
+ QList<QWidget *> *m_parents;
+ QWidget *m_window;
+ QRect *m_drawRect;
+ bool m_newImageReady;
+ bool m_usingWindow;
+}
+
+- (SharedQTMovieView *) init;
+- (void) registerParent:(QWidget *)parent;
+- (void) unregisterParent:(QWidget *)parent;
+- (void) setDrawRect:(QRect &)rect;
+- (void) drawVideoFrame:(Phonon::QT7::VideoFrame &)frame forWidget:(QWidget *)widget shareImages:(bool)share;
+- (void) useOffscreenWindow:(bool)offscreen;
+- (void) applyDrawRectOnSelf;
+@end
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation SharedQTMovieView
+
+- (SharedQTMovieView *) init
+{
+ self = [super initWithFrame:NSZeroRect];
+ if (self){
+ [self setControllerVisible:NO];
+ m_parents = new QList<QWidget *>();
+ m_drawRect = new QRect(0, 0, 1, 1);
+ [self applyDrawRectOnSelf];
+ m_usingWindow = false;
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+ Phonon::QT7::PhononAutoReleasePool pool;
+ delete m_window;
+ delete m_drawRect;
+ delete m_parents;
+ [super dealloc];
+}
+
+- (void) applyDrawRectOnSelf
+{
+ 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];
+}
+
+- (void) setDrawRect:(QRect &)rect
+{
+ *m_drawRect = rect;
+ if (!m_usingWindow)
+ [self applyDrawRectOnSelf];
+}
+
+- (void) waitForFrame
+{
+ if (m_usingWindow){
+ QTMovie *movie = [self movie];
+ if (movie){
+ // CIImages are expected, but not received.
+ // Try to wait a couple of seconds for them:
+ m_newImageReady = false;
+ float rate = [movie rate];
+ if (!rate)
+ [movie setRate:1];
+ QTime t; t.start();
+ while (!m_newImageReady && t.elapsed() < 2000)
+ ;
+ [movie setRate:rate];
+ }
+ }
+}
+
+- (void) useOffscreenWindow:(bool)offscreen
+{
+ if (offscreen == m_usingWindow)
+ return;
+ if (offscreen){
+ if (!m_window){
+ m_window = new QWidget;
+ m_window->setWindowOpacity(0.0);
+ m_window->show();
+ m_window->hide();
+ }
+ m_usingWindow = true;
+ [self setDelegate:self];
+ [self waitForFrame];
+ foreach(QWidget *w, *m_parents)
+ w->repaint();
+ qApp->processEvents();
+ [self removeFromSuperview];
+ [(NSView *)m_window->winId() addSubview:self];
+ } else if (!m_parents->isEmpty()){
+ m_usingWindow = false;
+ [self removeFromSuperview];
+ [(NSView*)m_parents->first()->winId() addSubview:self];
+ [self setDelegate:0];
+ [self setDrawRect:*m_drawRect];
+ }
+}
+
+- (void) drawVideoFrame:(Phonon::QT7::VideoFrame &)frame forWidget:(QWidget *)widget shareImages:(bool)share;
+{
+ // Detect if the video that produces the frame has changed:
+ Phonon::QT7::QuickTimeVideoPlayer *player = frame.videoPlayer();
+ if (player && player->qtMovie() != [self movie]){
+ m_player = player;
+ [self setMovie:player->qtMovie()];
+ [self waitForFrame];
+ }
+
+ [self useOffscreenWindow:(share || m_parents->size() > 1)];
+ if (m_usingWindow)
+ widget->update();
+}
+
+// Override this method so that the movie doesn't stop if
+// the window becomes invisible
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow
+{
+ Q_UNUSED(newWindow);
+}
+
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img
+{
+ // This method is called from QTMovieView just
+ // before the image will be drawn.
+ Q_UNUSED(view);
+ m_player->setPrimaryRenderingCIImage(img);
+ m_newImageReady = true;
+ return img;
+}
+
+- (void) registerParent:(QWidget *)parent
+{
+ if (m_parents->contains(parent))
+ return;
+ m_parents->append(parent);
+ if (m_parents->size() == 1){
+ Phonon::QT7::PhononAutoReleasePool pool;
+ m_usingWindow = true;
+ [self applyDrawRectOnSelf];
+ [self useOffscreenWindow:NO];
+ }
+}
+
+- (void) unregisterParent:(QWidget *)parent
+{
+ m_parents->removeAll(parent);
+ if (m_parents->size() == 1)
+ [self applyDrawRectOnSelf];
+}
+
+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
+
+#endif // QT_MAC_USE_COCOA
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace QT7
+{
+
+class IVideoRenderDrawWidget
+{
+public:
+ virtual ~IVideoRenderDrawWidget(){}
+ virtual void setVideoFrame(VideoFrame &) = 0;
+ virtual void setDrawFrameRect(const QRect &) = 0;
+ virtual void updateVideoOutputCount(int){}
+ virtual void setMovieIsPaused(bool){}
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+QGLWidget *PhononSharedQGLWidget(){
+ static QGLWidget *glWidget = 0;
+ if (!glWidget)
+ glWidget = new QGLWidget();
+ return glWidget;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class RenderOpenGL : public QGLWidget, public IVideoRenderDrawWidget
+{
+public:
+ VideoFrame m_currentFrame;
+ QRect m_drawFrameRect;
+
+ RenderOpenGL(QWidget *parent, const QGLFormat &format, const QSize &size) : QGLWidget(format, parent, PhononSharedQGLWidget())
+ {
+ resize(size);
+ setAutoFillBackground(false);
+ show();
+ }
+
+ void initializeGL()
+ {
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ void resizeGL(int w, int h)
+ {
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glViewport(0, 0, GLsizei(w), GLsizei(h));
+ glOrtho(0, GLsizei(w), 0, GLsizei(h), -1, 1);
+ updateGL();
+ }
+
+ void paintGL()
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+ m_currentFrame.drawCVTexture(m_drawFrameRect);
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ m_currentFrame = frame;
+ makeCurrent();
+ paintGL();
+ swapBuffers();
+ }
+
+ void setDrawFrameRect(const QRect &rect)
+ {
+ m_drawFrameRect = rect;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class RenderQTMovieView : public QWidget, public IVideoRenderDrawWidget
+{
+public:
+#if defined(QT_MAC_USE_COCOA)
+ QRect m_drawRect;
+ VideoFrame m_videoFrame;
+ SharedQTMovieView *m_currentView;
+ bool m_setDrawRectPending;
+ bool m_share;
+
+ RenderQTMovieView(bool share, QWidget *parent, const QSize &size=QSize()) : QWidget(parent), m_currentView(0)
+ {
+ m_setDrawRectPending = true;
+ m_share = share;
+ setAutoFillBackground(false);
+ if (share){
+ // In 'share' mode, this widget will only make sure
+ // that CIIImages are produced, and not actually
+ // draw anything:
+ hide();
+ } else {
+ resize(size);
+ show();
+ }
+ }
+
+ ~RenderQTMovieView()
+ {
+ [m_currentView unregisterParent:this];
+ }
+
+ void showEvent(QShowEvent *)
+ {
+ if (m_share)
+ return;
+ [m_currentView registerParent:this];
+ }
+
+ void hideEvent(QHideEvent *)
+ {
+ if (m_share)
+ return;
+ [m_currentView unregisterParent:this];
+ }
+
+ void paintEvent(QPaintEvent *)
+ {
+ if (m_share)
+ return;
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ m_videoFrame.drawCIImage(m_drawRect);
+ }
+
+ void updateVideoOutputCount(int count)
+ {
+ Q_UNUSED(count);
+ }
+
+ void setMovieIsPaused(bool paused)
+ {
+ Q_UNUSED(paused);
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ m_videoFrame = frame;
+
+ if (!m_videoFrame.isEmpty()){
+ Phonon::QT7::QuickTimeVideoPlayer *player = m_videoFrame.videoPlayer();
+ if (!player->m_primaryRenderingTarget){
+ // First movie view. Create the shared resource:
+ SharedQTMovieView *view = [[[SharedQTMovieView alloc] init] autorelease];
+ player->setPrimaryRenderingTarget(view);
+ }
+
+ SharedQTMovieView *view = static_cast<SharedQTMovieView *>(player->m_primaryRenderingTarget);
+ if (!m_share && view != m_currentView){
+ [m_currentView unregisterParent:this];
+ m_currentView = view;
+ [m_currentView registerParent:this];
+ }
+
+ [view drawVideoFrame:m_videoFrame forWidget:this shareImages:m_share || m_videoFrame.hasColorAdjustments()];
+
+ if (m_setDrawRectPending){
+ m_setDrawRectPending = false;
+ [view setDrawRect:m_drawRect];
+ }
+ }
+ }
+
+ void setDrawFrameRect(const QRect &rect)
+ {
+ m_drawRect = rect;
+ Phonon::QT7::QuickTimeVideoPlayer *player = m_videoFrame.videoPlayer();
+ if (player && player->m_primaryRenderingTarget){
+ SharedQTMovieView *view = static_cast<SharedQTMovieView *>(player->m_primaryRenderingTarget);
+ [view setDrawRect:m_drawRect];
+ } else
+ m_setDrawRectPending = true;
+ }
+
+#else // QT_MAC_USE_COCOA == false
+ RenderQTMovieView(bool, QWidget *, const QSize& = QSize()){}
+ void setVideoFrame(VideoFrame &){}
+ void setDrawFrameRect(const QRect &){}
+#endif
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class RenderQTMovieLayer : public QWidget, public IVideoRenderDrawWidget
+{
+public:
+#ifdef QT_MAC_USE_COCOA
+ QTMovieLayer *m_movieLayer;
+
+ RenderQTMovieLayer(QWidget *parent, const QSize&) : QWidget(parent)
+ {
+ PhononAutoReleasePool pool;
+ setAutoFillBackground(false);
+ m_movieLayer = 0;
+ [(NSView *)winId() setWantsLayer:YES];
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ QuickTimeVideoPlayer *player = frame.videoPlayer();
+ if (!player || player->qtMovie() == [m_movieLayer movie])
+ return;
+
+ if (m_movieLayer)
+ [m_movieLayer setMovie:player->qtMovie()];
+ else {
+ m_movieLayer = [QTMovieLayer layerWithMovie:player->qtMovie()];
+ [(NSView *)winId() setLayer:m_movieLayer];
+ }
+ }
+
+ void setDrawFrameRect(const QRect &rect)
+ {
+ CGRect frame = m_movieLayer.frame;
+ frame.origin.x = rect.x();
+ frame.origin.y = rect.y();
+ frame.size.width = rect.width();
+ frame.size.height = rect.height();
+ m_movieLayer.frame = frame;
+ }
+
+#else // QT_MAC_USE_COCOA == false
+ RenderQTMovieLayer(QWidget *, const QSize&){}
+ void setVideoFrame(VideoFrame &){}
+ void setDrawFrameRect(const QRect &){}
+#endif
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class VideoRenderWidget : public QWidget
+{
+public:
+ enum RenderSystem { RS_NoRendering = 0,
+ RS_QGLWidget = 1,
+ RS_QPainter = 2,
+ RS_CIImage = 3,
+ RS_CVTexture = 4,
+ RS_QImage = 5,
+ RS_QTMovieView = 6,
+ RS_QTMovieLayer = 7
+ } m_renderSystem;
+
+ VideoFrame m_currentFrame;
+ QRect m_movieFrameRect;
+ QRect m_drawFrameRect;
+ Phonon::VideoWidget::ScaleMode m_scaleMode;
+ Phonon::VideoWidget::AspectRatio m_aspect;
+ IVideoRenderDrawWidget *m_renderDrawWidget;
+
+ qreal m_brightness;
+ qreal m_contrast;
+ qreal m_hue;
+ qreal m_saturation;
+ qreal m_opacity;
+
+ VideoRenderWidget() : QWidget(0),
+ m_scaleMode(Phonon::VideoWidget::FitInView), m_aspect(Phonon::VideoWidget::AspectRatioAuto)
+ {
+ PhononAutoReleasePool pool;
+ m_brightness = 0;
+ m_contrast = 0;
+ m_hue = 0;
+ m_saturation = 0;
+ m_opacity = 1;
+ m_renderDrawWidget = 0;
+ m_renderSystem = RS_NoRendering;
+
+ setAutoFillBackground(false);
+ updateDrawFrameRect();
+ }
+
+ RenderSystem selectBestRenderSystem(){
+ if (!isVisible())
+ return RS_NoRendering;
+ else if (window() && window()->testAttribute(Qt::WA_DontShowOnScreen))
+ return RS_QPainter;
+ else {
+#ifdef QUICKTIME_C_API_AVAILABLE
+ return RS_QGLWidget;
+#else
+ return RS_QTMovieView;
+#endif
+ }
+ }
+
+ void setRenderSystem(RenderSystem renderSystem){
+ PhononAutoReleasePool pool;
+ static QString userSystem = qgetenv("PHONON_RENDER_SYSTEM");
+ if (!userSystem.isEmpty())
+ renderSystem = RenderSystem(userSystem.toInt());
+
+ if (m_renderSystem == renderSystem)
+ return;
+
+ m_renderSystem = renderSystem;
+ if (m_renderDrawWidget){
+ delete m_renderDrawWidget;
+ m_renderDrawWidget = 0;
+ }
+
+ switch (m_renderSystem){
+ case RS_QGLWidget:{
+ QGLFormat format = QGLFormat::defaultFormat();
+ format.setSwapInterval(1); // Vertical sync (avoid tearing)
+ m_renderDrawWidget = new RenderOpenGL(this, format, size());
+ break;}
+ case RS_QTMovieView:{
+ m_renderDrawWidget = new RenderQTMovieView(false, this, size());
+ break;}
+ case RS_QTMovieLayer:{
+ m_renderDrawWidget = new RenderQTMovieLayer(this, size());
+ break;}
+ case RS_QPainter:
+ case RS_CIImage:
+ case RS_CVTexture:
+ case RS_QImage:
+#ifndef QUICKTIME_C_API_AVAILABLE
+ // On cocoa-64, let QTMovieView produce
+ // video frames for us:
+ m_renderDrawWidget = new RenderQTMovieView(true, this);
+#endif
+ break;
+ case RS_NoRendering:
+ break;
+ }
+
+ if (m_renderDrawWidget){
+ m_renderDrawWidget->setVideoFrame(m_currentFrame);
+ m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
+ }
+ }
+
+ QSize sizeHint() const
+ {
+ return m_movieFrameRect.size();
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()){
+ // Try to detect if one of this objects
+ // anchestors might have changed:
+ case QEvent::Resize:{
+ PhononAutoReleasePool pool;
+ updateDrawFrameRect();
+ if (m_renderDrawWidget)
+ dynamic_cast<QWidget *>(m_renderDrawWidget)->resize(size());
+ break; }
+ case QEvent::Paint:{
+ PhononAutoReleasePool pool;
+ float opacity = parentWidget() ? parentWidget()->windowOpacity() : 1;
+ switch (m_renderSystem){
+ case RS_QPainter:{
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ if (p.paintEngine()->type() == QPaintEngine::OpenGL)
+ m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
+ else
+ m_currentFrame.drawQImage(&p, m_drawFrameRect);
+ break; }
+ case RS_CIImage:
+ m_currentFrame.drawCIImage(m_drawFrameRect, opacity);
+ break;
+ case RS_CVTexture:
+ m_currentFrame.drawCVTexture(m_drawFrameRect, opacity);
+ break;
+ case RS_QImage:{
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ m_currentFrame.drawQImage(&p, m_drawFrameRect);
+ break; }
+ case RS_QGLWidget:
+ case RS_QTMovieView:
+ case RS_QTMovieLayer:
+ // draw in separate widget
+ break;
+ case RS_NoRendering:
+ QPainter p(this);
+ p.fillRect(rect(), Qt::black);
+ break;
+ }
+ break; }
+ default:
+ break;
+ }
+
+ return QWidget::event(event);
+ }
+
+ void setVideoFrame(VideoFrame &frame)
+ {
+ PhononAutoReleasePool pool;
+ m_currentFrame = frame;
+ m_currentFrame.setColors(m_brightness, m_contrast, m_hue, m_saturation);
+
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->setVideoFrame(m_currentFrame);
+
+ setRenderSystem(selectBestRenderSystem());
+ switch (m_renderSystem){
+ case RS_QGLWidget:
+ case RS_QTMovieView:
+ case RS_QTMovieLayer:
+ case RS_NoRendering:
+ break;
+ case RS_CIImage:
+ case RS_CVTexture:
+ case RS_QImage:
+ case RS_QPainter:
+ repaint();
+ break;
+ }
+ }
+
+ void updateVideoFrame()
+ {
+ setVideoFrame(m_currentFrame);
+ }
+
+ void setMovieRect(const QRect &mrect)
+ {
+ if (mrect == m_movieFrameRect)
+ return;
+ m_movieFrameRect = mrect;
+ updateDrawFrameRect();
+ updateGeometry();
+ if (isVisible())
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+ }
+
+ void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ m_scaleMode = scaleMode;
+ updateDrawFrameRect();
+ updateVideoFrame();
+ repaint();
+ }
+
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
+ {
+ m_aspect = aspect;
+ updateDrawFrameRect();
+ updateVideoFrame();
+ repaint();
+ }
+
+ void updateVideoOutputCount(int count)
+ {
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->updateVideoOutputCount(count);
+ }
+
+ void setMovieIsPaused(bool paused)
+ {
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->setMovieIsPaused(paused);
+ }
+
+ void updateDrawFrameRect()
+ {
+ if (m_movieFrameRect.width() <= 0 || m_movieFrameRect.height() <= 0)
+ m_movieFrameRect = QRect(0, 0, 640, 480);
+
+ // Set m_drawFrameRect to be the size of the smallest possible
+ // rect conforming to the aspect and containing the whole frame:
+ switch(m_aspect){
+ case Phonon::VideoWidget::AspectRatioWidget:
+ m_drawFrameRect = rect();
+ break;
+ case Phonon::VideoWidget::AspectRatio4_3:
+ m_drawFrameRect = scaleToAspect(m_movieFrameRect, 4, 3);
+ break;
+ case Phonon::VideoWidget::AspectRatio16_9:
+ m_drawFrameRect = scaleToAspect(m_movieFrameRect, 16, 9);
+ break;
+ case Phonon::VideoWidget::AspectRatioAuto:
+ default:
+ m_drawFrameRect = m_movieFrameRect;
+ break;
+ }
+
+ // Scale m_drawFrameRect to fill the widget
+ // without breaking aspect:
+ int widgetWidth = rect().width();
+ int widgetHeight = rect().height();
+ int frameWidth = widgetWidth;
+ int frameHeight = m_drawFrameRect.height() * float(widgetWidth) / float(m_drawFrameRect.width());
+
+ switch(m_scaleMode){
+ case Phonon::VideoWidget::ScaleAndCrop:
+ if (frameHeight < widgetHeight){
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ case Phonon::VideoWidget::FitInView:
+ default:
+ if (frameHeight > widgetHeight){
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ }
+
+ m_drawFrameRect.setSize(QSize(frameWidth, frameHeight));
+ m_drawFrameRect.moveTo((widgetWidth - frameWidth) / 2.0f, (widgetHeight - frameHeight) / 2.0f);
+
+ if (m_renderDrawWidget)
+ m_renderDrawWidget->setDrawFrameRect(m_drawFrameRect);
+ }
+
+ QRect scaleToAspect(QRect srcRect, int w, int h)
+ {
+ int width = srcRect.width();
+ int height = srcRect.width() * (float(h) / float(w));
+ if (height > srcRect.height()){
+ height = srcRect.height();
+ width = srcRect.height() * (float(w) / float(h));
+ }
+ return QRect(0, 0, width, height);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+VideoWidget::VideoWidget(QObject *parent) : MediaNode(VideoSink, parent)
+{
+ m_videoRenderWidget = new VideoRenderWidget();
+}
+
+VideoWidget::~VideoWidget()
+{
+ delete m_videoRenderWidget;
+}
+
+QWidget *VideoWidget::widget()
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget;
+}
+
+Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_aspect;
+}
+
+void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->setAspectRatio(aspect);
+}
+
+Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_scaleMode;
+}
+
+void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->setScaleMode(scaleMode);
+}
+
+qreal VideoWidget::brightness() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_brightness;
+}
+
+void VideoWidget::setBrightness(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_brightness = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+qreal VideoWidget::contrast() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_contrast;
+}
+
+void VideoWidget::setContrast(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_contrast = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+qreal VideoWidget::hue() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_hue;
+}
+
+void VideoWidget::setHue(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_hue = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+qreal VideoWidget::saturation() const
+{
+ IMPLEMENTED;
+ return m_videoRenderWidget->m_saturation;
+}
+
+void VideoWidget::setSaturation(qreal value)
+{
+ IMPLEMENTED;
+ m_videoRenderWidget->m_saturation = value;
+ if (m_owningMediaObject && m_owningMediaObject->state() == Phonon::PausedState)
+ m_videoRenderWidget->updateVideoFrame();
+}
+
+void VideoWidget::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ switch (event->type()){
+ case MediaNodeEvent::VideoFrameSizeChanged:
+ m_videoRenderWidget->setMovieRect(*static_cast<QRect *>(event->data()));
+ break;
+ case MediaNodeEvent::VideoOutputCountChanged:
+ m_videoRenderWidget->updateVideoOutputCount(*static_cast<int *>(event->data()));
+ break;
+ case MediaNodeEvent::MediaPlaying:
+ m_videoRenderWidget->setMovieIsPaused(!(*static_cast<bool *>(event->data())));
+ break;
+ default:
+ break;
+ }
+}
+
+void VideoWidget::updateVideo(VideoFrame &frame){
+ PhononAutoReleasePool pool;
+ m_videoRenderWidget->setVideoFrame(frame);
+ MediaNode::updateVideo(frame);
+}
+
+}} // namespace Phonon::QT7
+
+QT_END_NAMESPACE
+
+#include "moc_videowidget.cpp"
diff --git a/src/3rdparty/phonon/waveout/audiooutput.cpp b/src/3rdparty/phonon/waveout/audiooutput.cpp
new file mode 100644
index 0000000..f842dc9
--- /dev/null
+++ b/src/3rdparty/phonon/waveout/audiooutput.cpp
@@ -0,0 +1,78 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "audiooutput.h"
+#include "mediaobject.h"
+
+#include <QtCore/QVector>
+
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace WaveOut
+ {
+ AudioOutput::AudioOutput(Backend *, QObject *parent)
+ {
+ setParent(parent);
+ m_volume = 0xffff;
+ }
+
+ AudioOutput::~AudioOutput()
+ {
+ }
+
+ int AudioOutput::outputDevice() const
+ {
+ return 0;
+ }
+
+ void AudioOutput::setVolume(qreal newVolume)
+ {
+ m_volume = newVolume;
+ emit volumeChanged(newVolume);
+ }
+
+ void AudioOutput::setCrossFadingProgress(short currentIndex, qreal progress)
+ {
+ Q_UNUSED(currentIndex);
+ Q_UNUSED(progress);
+ }
+
+ bool AudioOutput::setOutputDevice(const AudioOutputDevice & newDevice)
+ {
+ return setOutputDevice(newDevice.index());
+ }
+
+ qreal AudioOutput::volume() const
+ {
+ return m_volume;
+ }
+
+ bool AudioOutput::setOutputDevice(int newDevice)
+ {
+
+ return (newDevice == 0);
+ }
+
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/3rdparty/phonon/waveout/audiooutput.h b/src/3rdparty/phonon/waveout/audiooutput.h
new file mode 100644
index 0000000..43f8222
--- /dev/null
+++ b/src/3rdparty/phonon/waveout/audiooutput.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_AUDIOOUTPUT_H
+#define PHONON_AUDIOOUTPUT_H
+
+#include <QtCore/QFile>
+#include <phonon/audiooutputinterface.h>
+
+#include "backend.h"
+
+struct IBaseFilter;
+struct IBasicAudio;
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace WaveOut
+ {
+ class AudioOutput : public QObject, public Phonon::AudioOutputInterface
+ {
+ Q_OBJECT
+
+ Q_INTERFACES(Phonon::AudioOutputInterface)
+ public:
+ AudioOutput(Backend *back, QObject *parent);
+ ~AudioOutput();
+
+ // Attributes Getters:
+ qreal volume() const;
+ int outputDevice() const;
+ void setVolume(qreal newVolume);
+ bool setOutputDevice(int newDevice);
+ bool setOutputDevice(const AudioOutputDevice & newDevice);
+ void setCrossFadingProgress(short currentIndex, qreal progress);
+
+ Q_SIGNALS:
+ void audioDeviceFailed();
+ void volumeChanged(qreal);
+ private:
+ unsigned int m_volume;
+
+
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_AUDIOOUTPUT_H
diff --git a/src/3rdparty/phonon/waveout/backend.cpp b/src/3rdparty/phonon/waveout/backend.cpp
new file mode 100644
index 0000000..8faa26e
--- /dev/null
+++ b/src/3rdparty/phonon/waveout/backend.cpp
@@ -0,0 +1,131 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backend.h"
+
+
+#include "audiooutput.h"
+#include "mediaobject.h"
+
+
+
+#include <QtCore/QSettings>
+#include <QtCore/QSet>
+#include <QtCore/QVariant>
+#include <QtCore/QStringList>
+
+#include <QtCore/QtPlugin>
+
+
+QT_BEGIN_NAMESPACE
+
+// export as Qt/KDE factory as required
+
+Q_EXPORT_PLUGIN2(phonon_waveout, Phonon::WaveOut::Backend);
+
+namespace Phonon
+{
+ namespace WaveOut
+ {
+
+ Backend::Backend(QObject *parent, const QVariantList &)
+ : QObject(parent)
+ {
+ }
+
+ Backend::~Backend()
+ {
+ }
+
+ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+ {
+ Q_UNUSED(args);
+ switch (c)
+ {
+ case MediaObjectClass:
+ return new MediaObject(parent);
+ case AudioOutputClass:
+ return new AudioOutput(this, parent);
+ default:
+ return 0;
+ }
+ }
+
+ bool Backend::supportsVideo() const
+ {
+ return false;
+ }
+
+ QStringList Backend::availableMimeTypes() const
+ {
+ QStringList ret;
+ return ret;
+ }
+
+
+ QList<int> Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const
+ {
+ QList<int> r;
+ if (type == Phonon::AudioOutputDeviceType)
+ r.append(0);
+ return r;
+ }
+
+ QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const
+ {
+ Q_UNUSED(index);
+ QHash<QByteArray, QVariant> r;
+ if (type == Phonon::AudioOutputDeviceType)
+ r["name"] = QLatin1String("default audio device");
+ return r;
+ }
+
+
+ bool Backend::connectNodes(QObject *node1, QObject *node2)
+ {
+ MediaObject *mediaObject = qobject_cast<MediaObject*> (node1);
+ AudioOutput *audioOutput = qobject_cast<AudioOutput*> (node2);
+
+ if (mediaObject && audioOutput)
+ mediaObject->setAudioOutput(audioOutput);
+ return true;
+ }
+
+ bool Backend::disconnectNodes(QObject *node1, QObject *node2)
+ {
+ Q_UNUSED(node1);
+ Q_UNUSED(node2);
+ return true;
+ }
+
+ //transaction management
+ bool Backend::startConnectionChange(QSet<QObject *>)
+ {
+ return true;
+ }
+
+ bool Backend::endConnectionChange(QSet<QObject *>)
+ {
+ return true;
+ }
+
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_backend.cpp"
diff --git a/src/3rdparty/phonon/waveout/backend.h b/src/3rdparty/phonon/waveout/backend.h
new file mode 100644
index 0000000..060d853
--- /dev/null
+++ b/src/3rdparty/phonon/waveout/backend.h
@@ -0,0 +1,69 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_BACKEND_H
+#define PHONON_BACKEND_H
+
+#include <phonon/backendinterface.h>
+#include <phonon/phononnamespace.h>
+
+#include <QtCore/QList>
+
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace WaveOut
+ {
+ class AudioOutput;
+ class MediaObject;
+
+ class Backend : public QObject, public Phonon::BackendInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::BackendInterface)
+ public:
+ Backend(QObject *parent = 0, const QVariantList & = QVariantList());
+ virtual ~Backend();
+
+ QObject *createObject(Phonon::BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
+
+ bool supportsVideo() const;
+ QStringList availableMimeTypes() const;
+
+ QList<int> objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const;
+
+ bool connectNodes(QObject *, QObject *);
+ bool disconnectNodes(QObject *, QObject *);
+
+ //transaction management
+ bool startConnectionChange(QSet<QObject *>);
+ bool endConnectionChange(QSet<QObject *>);
+
+ Q_SIGNALS:
+ void objectDescriptionChanged(ObjectDescriptionType);
+
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_BACKEND_H
diff --git a/src/3rdparty/phonon/waveout/mediaobject.cpp b/src/3rdparty/phonon/waveout/mediaobject.cpp
new file mode 100644
index 0000000..fdd81a7
--- /dev/null
+++ b/src/3rdparty/phonon/waveout/mediaobject.cpp
@@ -0,0 +1,686 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "mediaobject.h"
+#include "audiooutput.h"
+
+#include <QtCore/QVector>
+#include <QtCore/QTimerEvent>
+#include <QtCore/QTimer>
+#include <QtCore/QTime>
+#include <QtCore/QLibrary>
+#include <QtCore/QUrl>
+#include <QtCore/QWriteLocker>
+
+#include <phonon/streaminterface.h>
+
+
+#define WAVEHEADER_OFFSET_FORMATTAG 20
+#define WAVEHEADER_OFFSET_CHANNELS 22
+#define WAVEHEADER_OFFSET_SAMPLESPERSEC 24
+#define WAVEHEADER_OFFSET_AVGBYTESPERSEC 28
+#define WAVEHEADER_OFFSET_BLOCKALIGN 32
+#define WAVEHEADER_OFFSET_BITSPERSAMPLE 34
+#define WAVEHEADER_OFFSET_DATA 44
+#define WAVEHEADER_SIZE WAVEHEADER_OFFSET_DATA
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ namespace WaveOut
+ {
+ static unsigned int buffer_size = (16 * 1024 * 4);
+
+ QString getErrorText(MMRESULT error)
+ {
+ ushort b[256];
+ waveOutGetErrorText(error, (LPWSTR)b, 256);
+ return QString((const QChar *)b);
+ }
+
+ class WorkerThread : public QThread
+ {
+ Q_OBJECT
+ public slots:
+ void stream(QIODevice *file, QByteArray *buffer, bool *finished);
+ };
+
+ void WorkerThread::stream(QIODevice *ioStream, QByteArray *buffer, bool *finished)
+ {
+ (*finished) = false;
+ memset((void*) buffer->data(), 0, buffer->size());
+ qint64 i = ioStream->read(buffer->data(), buffer_size);
+ buffer->resize(i);
+ (*finished) = true;
+ }
+
+
+ void QT_WIN_CALLBACK MediaObject::WaveOutCallBack(HWAVEOUT m_hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
+ {
+ Q_UNUSED(m_hWaveOut);
+ Q_UNUSED(dwInstance);
+ Q_UNUSED(dwParam2);
+
+ switch(uMsg)
+ {
+ case WOM_OPEN:
+ break;
+ case WOM_DONE:
+ {
+ WAVEHDR *waveHeader = (WAVEHDR*)dwParam1;
+ MediaObject* mediaObject = reinterpret_cast<MediaObject *>(waveHeader->dwUser);
+ if (mediaObject) {
+ mediaObject->swapBuffers();
+ }
+ }
+ break;
+ case WOM_CLOSE:
+ break;
+ }
+ }
+
+ class StreamReader : public Phonon::StreamInterface
+ {
+ public:
+ StreamReader(QObject *parent, const Phonon::MediaSource &source) :
+ m_seekable(false), m_pos(0), m_size(-1)
+ {
+ Q_UNUSED(parent);
+ connectToSource(source);
+ }
+
+ //for Phonon::StreamInterface
+ void writeData(const QByteArray &data)
+ {
+ QWriteLocker locker(&m_lock);
+ m_pos += data.size();
+ m_buffer += data;
+ }
+
+ void endOfData()
+ {
+ }
+
+ void setStreamSize(qint64 newSize)
+ {
+ QWriteLocker locker(&m_lock);
+ m_size = newSize;
+ }
+
+ qint64 streamSize() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_size;
+ }
+
+ void setStreamSeekable(bool s)
+ {
+ QWriteLocker locker(&m_lock);
+ m_seekable = s;
+ }
+
+ bool streamSeekable() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_seekable;
+ }
+
+ void setCurrentPos(qint64 pos)
+ {
+ QWriteLocker locker(&m_lock);
+ m_pos = pos;
+ seekStream(pos);
+ m_buffer.clear();
+ }
+
+ qint64 currentPos() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_pos;
+ }
+
+ int currentBufferSize() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_buffer.size();
+ }
+
+ //for Phonon::StreamInterface
+ QByteArray m_buffer;
+ bool m_seekable;
+ qint64 m_pos;
+ qint64 m_size;
+ mutable QReadWriteLock m_lock;
+ };
+
+ class IOWrapper : public QIODevice {
+ public:
+ IOWrapper(QObject *parent, const Phonon::MediaSource &source) : m_streamReader(this, source)
+ {
+ Q_UNUSED(parent);
+ setOpenMode(QIODevice::ReadOnly);
+ }
+ bool seek(qint64 pos);
+ qint64 size() const;
+ qint64 pos();
+ bool isReadable() const;
+ protected:
+ qint64 readData (char * data, qint64 maxSize);
+ qint64 writeData(const char *,qint64);
+ private:
+ StreamReader m_streamReader;
+ };
+
+ bool IOWrapper::isReadable () const
+ {
+ return true;
+ }
+
+ qint64 IOWrapper::pos()
+ {
+ return (m_streamReader.streamSeekable() ? m_streamReader.currentPos() : 0);
+ }
+
+ bool IOWrapper::seek( qint64 pos)
+ {
+ if (!m_streamReader.streamSeekable())
+ return false;
+ m_streamReader.setCurrentPos(pos);
+ return true;
+ }
+
+ qint64 IOWrapper::size() const
+ {
+ return m_streamReader.streamSize();
+ }
+
+ qint64 IOWrapper::readData(char * data, qint64 maxSize)
+ {
+ int oldSize = m_streamReader.currentBufferSize();
+ while (m_streamReader.currentBufferSize() < maxSize) {
+ m_streamReader.needData();
+ if (oldSize == m_streamReader.currentBufferSize()) {
+ break; //we didn't get any data
+ }
+ oldSize = m_streamReader.currentBufferSize();
+ }
+
+ qint64 bytesRead = qMin(qint64(m_streamReader.currentBufferSize()), maxSize);
+ {
+ QWriteLocker locker(&m_streamReader.m_lock);
+ qMemCopy(data, m_streamReader.m_buffer.data(), bytesRead);
+ //truncate the buffer
+ m_streamReader.m_buffer = m_streamReader.m_buffer.mid(bytesRead);
+ }
+ return bytesRead;
+ }
+
+ qint64 IOWrapper::writeData(const char *,qint64)
+ {
+ return 0;
+ }
+
+ MediaObject::MediaObject(QObject *parent) : m_file(0), m_stream(0),
+ m_hWaveOut(0), m_nextBufferIndex(1),
+ m_mediaSize(-1), m_bufferingFinished(0),
+ m_paused(0), m_tickInterval(0),
+ m_hasNextSource(0), m_hasSource(0),
+ m_sourceIsValid(0), m_errorType(Phonon::NoError),
+ m_currentTime(0), m_transitionTime(0),
+ m_tick(0), m_volume(100), m_prefinishMark(0),
+ m_tickIntervalResolution(0), m_bufferPrepared(0),
+ m_stopped(0)
+ {
+ m_thread = new WorkerThread();
+ connect(this, SIGNAL(outOfData(QIODevice*,QByteArray*,bool*)), m_thread, SLOT(stream(QIODevice*,QByteArray*,bool*)));
+ m_thread->start();
+ m_soundBuffer1.waveHeader = new WAVEHDR;
+ m_soundBuffer2.waveHeader = new WAVEHDR;
+ setParent(parent);
+ setState(Phonon::LoadingState);
+ }
+
+ MediaObject::~MediaObject()
+ {
+ stop();
+ disconnect(this, SIGNAL(outOfData(QIODevice*,QByteArray*,bool*)), m_thread, SLOT(stream(QIODevice*,QByteArray*,bool*)));
+ do { //The event loop of m_thread might not be started, yet
+ m_thread->quit(); //If the event loop is not started yet quit() does nothing
+ m_thread->wait(100);
+ } while (m_thread->isRunning());
+ delete m_thread;
+ deleteValidWaveOutDevice();
+ delete m_soundBuffer1.waveHeader;
+ delete m_soundBuffer2.waveHeader;
+ }
+
+ Phonon::State MediaObject::state() const
+ {
+ return m_state;
+ }
+
+ bool MediaObject::hasVideo() const
+ {
+ return false;
+ }
+
+ bool MediaObject::isSeekable() const
+ {
+ if (!m_stream)
+ return false;
+ return !m_stream->isSequential();
+ }
+
+ qint64 MediaObject::totalTime() const
+ {
+ return m_totalTime;
+ }
+
+ qint64 MediaObject::currentTime() const
+ {
+ //this handles inaccuracy when stopping on a title
+ return m_currentTime;
+ }
+
+ qint32 MediaObject::tickInterval() const
+ {
+ return m_tickInterval * m_tickIntervalResolution;
+ }
+
+ void MediaObject::setTickInterval(qint32 newTickInterval)
+ {
+ if ((m_tickIntervalResolution == 0) || (newTickInterval == 0))
+ return;
+ m_tickInterval = newTickInterval / m_tickIntervalResolution;
+ if ((newTickInterval > 0) && (m_tickInterval == 0))
+ m_tickInterval = 1;
+ }
+
+ void MediaObject::pause()
+ {
+ if (!m_paused) {
+ m_paused = true;
+ setState(Phonon::PausedState);
+ if (!(waveOutPause(m_hWaveOut) == MMSYSERR_NOERROR))
+ {
+ setError(Phonon::NormalError, QLatin1String("cannot pause (system error)"));
+ }
+ }
+ }
+
+ void MediaObject::stop()
+ {
+ setState(Phonon::StoppedState);
+ m_stopped = true;
+ m_paused = false;
+ seek(0);
+ if (!(waveOutReset(m_hWaveOut) == MMSYSERR_NOERROR))
+ setError(Phonon::NormalError, QLatin1String("cannot stop (system error)"));
+ }
+
+ void MediaObject::play()
+ {
+ if ((m_state == Phonon::PlayingState) && !m_paused && !m_stopped)
+ return;
+ if ((m_state == Phonon::LoadingState) ||
+ (m_state == Phonon::BufferingState) ||
+ (m_state == Phonon::ErrorState)) {
+ setError(Phonon::FatalError, QLatin1String("illegale state for playback"));
+ return;
+ }
+
+ if (m_state == Phonon::StoppedState)
+ stop();
+ if (m_sourceIsValid) {
+ setState(Phonon::PlayingState);
+ if (!m_paused) {
+ m_nextBufferIndex = true;
+ m_stopped = false;
+ playBuffer(m_soundBuffer1.waveHeader);
+ playBuffer(m_soundBuffer2.waveHeader);
+ } else {
+ if (!(waveOutRestart(m_hWaveOut) == MMSYSERR_NOERROR))
+ setError(Phonon::NormalError, QLatin1String("cannot resume (system)"));
+ }
+ } else {
+ setError(Phonon::FatalError, QLatin1String("cannot playback invalid source"));
+ }
+ m_paused = false;
+ }
+
+ QString MediaObject::errorString() const
+ {
+
+ return m_errorString;
+ }
+
+ Phonon::ErrorType MediaObject::errorType() const
+ {
+ return Phonon::ErrorType();
+ }
+
+ qint32 MediaObject::prefinishMark() const
+ {
+ return m_prefinishMark;
+ }
+
+ void MediaObject::setPrefinishMark(qint32 newPrefinishMark)
+ {
+ m_prefinishMark = newPrefinishMark;
+ }
+
+ qint32 MediaObject::transitionTime() const
+ {
+ return m_transitionTime;
+ }
+
+ void MediaObject::setTransitionTime(qint32 time)
+ {
+ m_transitionTime = time;
+ }
+
+ qint64 MediaObject::remainingTime() const
+ {
+ return m_totalTime - m_currentTime;
+ }
+
+ Phonon::MediaSource MediaObject::source() const
+ {
+ return Phonon::MediaSource();
+ }
+
+ void MediaObject::setNextSource(const Phonon::MediaSource &source)
+ {
+ m_nextSource = source;
+ m_hasNextSource = true;
+ }
+
+ void MediaObject::setSource(const Phonon::MediaSource &source)
+ {
+ if (m_state == Phonon::PlayingState)
+ {
+ setError(Phonon::NormalError, QLatin1String("source changed while playing"));
+ stop();
+ }
+
+ m_source = source;
+ m_hasSource = true;
+ m_sourceIsValid = false;
+
+ emit currentSourceChanged(source);
+
+ if (source.type() == Phonon::MediaSource::LocalFile) {
+ if (!openWaveFile(source.fileName())) {
+ setError(Phonon::FatalError, QLatin1String("cannot open media file"));
+ return ;
+ }
+ } else if (source.type() == Phonon::MediaSource::Stream) {
+ if (m_stream)
+ delete m_stream;
+ m_stream = new IOWrapper(this, source);
+ m_mediaSize = m_stream->size();
+ } else if (source.type() == Phonon::MediaSource::Url) {
+ if (!openWaveFile(source.url().toLocalFile())) {
+ setError(Phonon::FatalError, QLatin1String("cannot open media file"));
+ return ;
+ }
+ } else {
+ setError(Phonon::FatalError, QLatin1String("type of source not supported"));
+ return ;
+ }
+ setState(Phonon::LoadingState);
+
+ if (!readHeader())
+ setError(Phonon::FatalError, QLatin1String("invalid header"));
+ else if (!getWaveOutDevice())
+ setError(Phonon::FatalError, QLatin1String("No waveOut device available"));
+ else if (!fillBuffers())
+ setError(Phonon::FatalError, QLatin1String("no data for buffering"));
+ else if (!prepareBuffers())
+ setError(Phonon::FatalError, QLatin1String("cannot prepare buffers"));
+ else
+ m_sourceIsValid = true;
+
+ if (m_sourceIsValid)
+ setState(Phonon::StoppedState);
+ }
+
+ void MediaObject::seek(qint64 time)
+ {
+ if (!m_sourceIsValid) {
+ setError(Phonon::NormalError, QLatin1String("source is not valid"));
+ return;
+ }
+ if ((time >= 0) && (time < m_totalTime)) {
+ int counter = 0;
+ while (!m_bufferingFinished && (counter < 200)) {
+ Sleep(20);
+ counter ++;
+ }
+ if (counter >= 200) {
+ setError(Phonon::NormalError, QLatin1String("buffering timed out"));
+ return;
+ }
+
+ m_stream->seek(WAVEHEADER_SIZE + time * m_waveFormatEx.nSamplesPerSec * m_waveFormatEx.wBitsPerSample * m_waveFormatEx.nChannels / 8 / 1000);
+ m_currentTime = time;
+ if (m_state == Phonon::PlayingState)
+ play();
+ } else {
+ setError(Phonon::NormalError, QLatin1String("seeking out of range"));
+ }
+ }
+
+ void MediaObject::unPrepareBuffers()
+ {
+ if (m_bufferPrepared) {
+ DWORD err1 = waveOutUnprepareHeader(m_hWaveOut, m_soundBuffer1.waveHeader, sizeof(WAVEHDR));
+ DWORD err2 = waveOutUnprepareHeader(m_hWaveOut, m_soundBuffer2.waveHeader, sizeof(WAVEHDR));
+ if (!(err1 == MMSYSERR_NOERROR) || !(err2 == MMSYSERR_NOERROR))
+ setError(Phonon::NormalError, QLatin1String("cannot unprepare buffer") + getErrorText(err1) + getErrorText(err2));
+ }
+ m_bufferPrepared = false;
+ }
+
+ bool MediaObject::prepareBuffers()
+ {
+ memset((void*)m_soundBuffer1.waveHeader, 0, sizeof(WAVEHDR));
+ m_soundBuffer1.waveHeader->lpData = m_soundBuffer1.data.data();
+ m_soundBuffer1.waveHeader->dwBufferLength = m_soundBuffer1.data.size();
+ m_soundBuffer1.waveHeader->dwUser = (DWORD_PTR) this;
+
+ ZeroMemory((void*)m_soundBuffer2.waveHeader, sizeof(WAVEHDR));
+ m_soundBuffer2.waveHeader->lpData = m_soundBuffer2.data.data();
+ m_soundBuffer2.waveHeader->dwBufferLength = m_soundBuffer1.data.size();
+ m_soundBuffer2.waveHeader->dwUser = (DWORD_PTR) this;
+
+ m_bufferPrepared = (waveOutPrepareHeader(m_hWaveOut, m_soundBuffer1.waveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
+ && (waveOutPrepareHeader(m_hWaveOut, m_soundBuffer2.waveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR);
+ return m_bufferPrepared;
+ }
+
+ void MediaObject::deleteValidWaveOutDevice()
+ {
+ if (m_hWaveOut) {
+ unPrepareBuffers();
+ if (!(waveOutClose(m_hWaveOut) == MMSYSERR_NOERROR))
+ setError(Phonon::NormalError, QLatin1String("cannot close wave device"));
+ }
+ }
+
+ bool MediaObject::getWaveOutDevice()
+ {
+ deleteValidWaveOutDevice();
+
+ for(UINT deviceId = 0; deviceId < waveOutGetNumDevs(); deviceId++)
+ {
+ if(deviceId == waveOutGetNumDevs())
+ return false;
+ if(waveOutOpen(&m_hWaveOut, WAVE_MAPPER, &m_waveFormatEx, (DWORD)WaveOutCallBack, 0, CALLBACK_FUNCTION) == MMSYSERR_NOERROR)
+ return m_hWaveOut; //m_hWaveOut !=0;
+ }
+ return false;
+ }
+
+ bool MediaObject::openWaveFile(QString fileName)
+ {
+ if (m_file)
+ delete m_file;
+ m_file = new QFile(fileName);
+ m_file->setParent(this);
+ m_stream = m_file;
+ m_mediaSize = m_file->size();
+ return (m_file->open(QIODevice::ReadOnly));
+ }
+
+ bool MediaObject::readHeader()
+ {
+ QByteArray header = m_stream->read(WAVEHEADER_SIZE);
+
+ if (header.size() == WAVEHEADER_SIZE) {
+
+ m_waveFormatEx.wFormatTag = *((WORD* )(header.data() + WAVEHEADER_OFFSET_FORMATTAG ));
+ m_waveFormatEx.nChannels = *((WORD* )(header.data() + WAVEHEADER_OFFSET_CHANNELS ));
+ m_waveFormatEx.nSamplesPerSec = *((DWORD*)(header.data() + WAVEHEADER_OFFSET_SAMPLESPERSEC ));
+ m_waveFormatEx.nAvgBytesPerSec = *((DWORD*)(header.data() + WAVEHEADER_OFFSET_AVGBYTESPERSEC));
+ m_waveFormatEx.nBlockAlign = *((WORD* )(header.data() + WAVEHEADER_OFFSET_BLOCKALIGN ));
+ m_waveFormatEx.wBitsPerSample = *((WORD* )(header.data() + WAVEHEADER_OFFSET_BITSPERSAMPLE ));
+
+ m_tickIntervalResolution = (qint64(buffer_size) * 8 * 1000) / m_waveFormatEx.nSamplesPerSec / m_waveFormatEx.wBitsPerSample / m_waveFormatEx.nChannels;
+ if (m_mediaSize > 0)
+ m_totalTime = ((m_mediaSize - WAVEHEADER_SIZE) * 8 * 1000) / m_waveFormatEx.nSamplesPerSec / m_waveFormatEx.wBitsPerSample / m_waveFormatEx.nChannels;
+ else
+ m_totalTime = -1;
+ emit totalTimeChanged(m_totalTime);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool MediaObject::fillBuffers()
+ {
+
+ m_soundBuffer1.data = m_stream->read(buffer_size);
+ m_soundBuffer2.data = m_stream->read(buffer_size);
+
+ m_bufferingFinished = true;
+
+ if (!(m_soundBuffer1.data.size() > 0))
+ setError(Phonon::NormalError, QLatin1String("cannot read source"));
+ return true;
+ }
+
+ void MediaObject::setState(Phonon::State newState)
+ {
+ if (m_state == newState)
+ return;
+ emit stateChanged(newState, m_state);
+ m_state = newState;
+ }
+
+ void MediaObject::setError(ErrorType errorType, QString errorMessage)
+ {
+ m_errorType = errorType;
+ setState(Phonon::ErrorState);
+ m_errorString = errorMessage;
+ }
+
+ void MediaObject::setAudioOutput(QObject *audioOutput)
+ {
+ m_audioOutput = qobject_cast<AudioOutput*>(audioOutput);
+
+ if (m_audioOutput) {
+ m_volume = m_audioOutput->volume();
+ connect(m_audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(setVolume(qreal)));
+ }
+ }
+
+ void MediaObject::setVolume(qreal newVolume)
+ {
+ m_volume = newVolume;
+ }
+
+ void MediaObject::swapBuffers()
+ {
+ if (m_stopped || m_paused)
+ return;
+
+ m_currentTime += m_tickIntervalResolution;
+ if (m_tickInterval) {
+ m_tick ++;
+ if (m_tick > (m_tickInterval - 1)) {
+ emit tick(m_currentTime);
+ m_tick = 0;
+ }
+ }
+ if ((m_prefinishMark > 0)&& (m_prefinishMark < m_currentTime))
+ emit prefinishMarkReached(m_totalTime - m_currentTime);
+
+ while (!m_bufferingFinished) {
+ setState(Phonon::BufferingState);
+ qWarning() << QLatin1String("buffer underun");
+ Sleep(20);
+ }
+
+ setState(Phonon::PlayingState);
+
+ //if size == o then stop...
+ if (m_nextBufferIndex) {
+ int size = m_soundBuffer1.waveHeader->dwBufferLength = m_soundBuffer1.data.size();
+ if (size == buffer_size) {
+ playBuffer(m_soundBuffer1.waveHeader);
+ emit outOfData(m_stream, &m_soundBuffer1.data, &m_bufferingFinished);
+ } else {
+ playBuffer(m_soundBuffer1.waveHeader);
+ m_stopped = true;
+ setState(Phonon::StoppedState);
+ emit finished();
+ seek(0);
+ }
+ } else {
+ int size = m_soundBuffer2.waveHeader->dwBufferLength = m_soundBuffer2.data.size();
+ if (size == buffer_size) {
+ playBuffer(m_soundBuffer2.waveHeader);
+ emit outOfData(m_stream, &m_soundBuffer2.data, &m_bufferingFinished);
+ } else {
+ playBuffer(m_soundBuffer2.waveHeader);
+ m_stopped = true;
+ setState(Phonon::StoppedState);
+ emit finished();
+ seek(0);
+ }
+ }
+ m_nextBufferIndex =! m_nextBufferIndex;
+ }
+
+
+ void MediaObject::playBuffer(WAVEHDR *waveHeader)
+ {
+ DWORD err = waveOutWrite(m_hWaveOut, waveHeader, sizeof(WAVEHDR));
+ if (!err == MMSYSERR_NOERROR) {
+ setError(Phonon::FatalError, QLatin1String("cannot play sound buffer (system) ") + getErrorText(err));
+ m_stopped = true;
+ }
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "mediaobject.moc"
diff --git a/src/3rdparty/phonon/waveout/mediaobject.h b/src/3rdparty/phonon/waveout/mediaobject.h
new file mode 100644
index 0000000..bb1410a
--- /dev/null
+++ b/src/3rdparty/phonon/waveout/mediaobject.h
@@ -0,0 +1,162 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library 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, either version 2.1 or 3 of the License.
+
+This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PHONON_MEDIAOBJECT_H
+#define PHONON_MEDIAOBJECT_H
+
+#include <phonon/mediaobjectinterface.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QObject>
+#include <QtCore/QQueue>
+#include <QtCore/QBasicTimer>
+#include <QtCore/QWaitCondition>
+#include <QtCore/QMutex>
+#include <QtCore/QThread>
+#include <QFile>
+#include <QIODevice>
+
+#include <windows.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class MediaSource;
+
+ namespace WaveOut
+ {
+ class WorkerThread;
+ class AudioOutput;
+
+ class MediaObject : public QObject, public Phonon::MediaObjectInterface
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::MediaObjectInterface)
+
+ public:
+ MediaObject(QObject *parent);
+ ~MediaObject();
+ Phonon::State state() const;
+ bool hasVideo() const;
+ bool isSeekable() const;
+ qint64 currentTime() const;
+ qint32 tickInterval() const;
+
+ void setTickInterval(qint32 newTickInterval);
+ void play();
+ void pause();
+ void stop();
+ void seek(qint64 time);
+
+ QString errorString() const;
+ Phonon::ErrorType errorType() const;
+ qint64 totalTime() const;
+ qint32 prefinishMark() const;
+ void setPrefinishMark(qint32 newPrefinishMark);
+ qint32 transitionTime() const;
+ void setTransitionTime(qint32);
+ qint64 remainingTime() const;
+ MediaSource source() const;
+ void setSource(const MediaSource &source);
+ void setNextSource(const MediaSource &source);
+
+
+ Q_SIGNALS:
+ void stateChanged(Phonon::State newstate, Phonon::State oldstate);
+ void tick(qint64 time);
+ void metaDataChanged(QMultiMap<QString, QString>);
+ void seekableChanged(bool);
+ void hasVideoChanged(bool);
+ void bufferStatus(int);
+ void finished();
+ void prefinishMarkReached(qint32);
+ void aboutToFinish();
+ void totalTimeChanged(qint64 length) const;
+ void currentSourceChanged(const MediaSource &);
+ void outOfData(QIODevice *ioStream, QByteArray *buffer, bool *m_bufferingFinshed);
+
+ protected:
+ void setAudioOutput(QObject *audioOutput);
+
+ private Q_SLOTS:
+ void setVolume(qreal newVolume);
+
+ private:
+ bool m_nextBufferIndex;
+ bool prepareBuffers();
+ void unPrepareBuffers();
+ bool getWaveOutDevice();
+ bool openWaveFile(QString fileName);
+ bool readHeader();
+ bool boolUpdateBuffer();
+ bool fillBuffers();
+ void swapBuffers();
+ void setState(Phonon::State newState);
+ void setError(ErrorType errorType, QString errorMessage);
+ void deleteValidWaveOutDevice();
+ void playBuffer(WAVEHDR *waveHeader);
+
+ static void QT_WIN_CALLBACK WaveOutCallBack(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
+
+ struct {
+ WAVEHDR *waveHeader;
+ QByteArray data;
+ } m_soundBuffer1, m_soundBuffer2;
+
+ WAVEFORMATEX m_waveFormatEx;
+ HWAVEOUT m_hWaveOut;
+
+ QFile *m_file;
+ QIODevice *m_stream;
+ QString m_errorString;
+
+ WorkerThread *m_thread;
+
+ MediaSource m_source;
+ MediaSource m_nextSource;
+ AudioOutput *m_audioOutput;
+ ErrorType m_errorType;
+
+ qreal m_volume;
+ qint64 m_mediaSize;
+ qint64 m_totalTime;
+ qint64 m_currentTime;
+ qint64 m_transitionTime;
+ qint64 m_prefinishMark;
+ qint64 m_tickIntervalResolution;
+ qint32 m_tickInterval;
+ qint32 m_tick;
+ Phonon::State m_state;
+
+ bool m_bufferingFinished;
+ bool m_paused;
+ bool m_stopped;
+ bool m_hasNextSource;
+ bool m_hasSource;
+ bool m_sourceIsValid;
+ bool m_bufferPrepared;
+
+ friend class Backend;
+ };
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // PHONON_MEDIAOBJECT_H
diff --git a/src/phonon/phonon.pro b/src/phonon/phonon.pro
new file mode 100644
index 0000000..b16c5a1
--- /dev/null
+++ b/src/phonon/phonon.pro
@@ -0,0 +1,145 @@
+TARGET = phonon
+include(../qbase.pri)
+
+PHONON_MAJOR_VERSION = $${QT_MAJOR_VERSION}
+PHONON_MINOR_VERSION = 4
+PHONON_PATCH_VERSION = 0
+VERSION = $${PHONON_MAJOR_VERSION}.$${PHONON_MINOR_VERSION}.$${PHONON_PATCH_VERSION}
+
+DEPENDPATH += .
+DEFINES += MAKE_PHONON_LIB
+
+PHONON_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/phonon
+
+unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui QtNetwork
+
+# Input
+HEADERS += $$PHONON_DIR/abstractaudiooutput.h \
+ $$PHONON_DIR/abstractaudiooutput_p.h \
+ $$PHONON_DIR/abstractmediastream.h \
+ $$PHONON_DIR/abstractmediastream_p.h \
+ $$PHONON_DIR/abstractvideooutput.h \
+ $$PHONON_DIR/abstractvideooutput_p.h \
+ $$PHONON_DIR/addoninterface.h \
+ $$PHONON_DIR/audiodataoutput_p.h \
+ $$PHONON_DIR/audiodataoutput.h \
+ $$PHONON_DIR/audiodataoutputinterface.h \
+ $$PHONON_DIR/audiooutput.h \
+ $$PHONON_DIR/audiooutput_p.h \
+ $$PHONON_DIR/audiooutputinterface.h \
+ $$PHONON_DIR/backendcapabilities.h \
+ $$PHONON_DIR/backendcapabilities_p.h \
+ $$PHONON_DIR/backendinterface.h \
+ $$PHONON_DIR/effect.h \
+ $$PHONON_DIR/effect_p.h \
+ $$PHONON_DIR/effectinterface.h \
+ $$PHONON_DIR/effectparameter.h \
+ $$PHONON_DIR/effectparameter_p.h \
+ $$PHONON_DIR/effectwidget.h \
+ $$PHONON_DIR/effectwidget_p.h \
+ $$PHONON_DIR/factory_p.h \
+ $$PHONON_DIR/frontendinterface_p.h \
+ $$PHONON_DIR/globalconfig.h \
+ $$PHONON_DIR/globalconfig_p.h \
+ $$PHONON_DIR/iodevicestream_p.h \
+ $$PHONON_DIR/mediacontroller.h \
+ $$PHONON_DIR/medianode.h \
+ $$PHONON_DIR/medianode_p.h \
+ $$PHONON_DIR/medianodedestructionhandler_p.h \
+ $$PHONON_DIR/mediaobject.h \
+ $$PHONON_DIR/mediaobject_p.h \
+ $$PHONON_DIR/mediaobjectinterface.h \
+ $$PHONON_DIR/mediasource.h \
+ $$PHONON_DIR/mediasource_p.h \
+ $$PHONON_DIR/objectdescription.h \
+ $$PHONON_DIR/objectdescription_p.h \
+ $$PHONON_DIR/objectdescriptionmodel.h \
+ $$PHONON_DIR/objectdescriptionmodel_p.h \
+ $$PHONON_DIR/path.h \
+ $$PHONON_DIR/path_p.h \
+ $$PHONON_DIR/pulsesupport.h \
+ $$PHONON_DIR/phonondefs.h \
+ $$PHONON_DIR/phonondefs_p.h \
+ $$PHONON_DIR/phononnamespace.h \
+ $$PHONON_DIR/phononnamespace_p.h \
+ $$PHONON_DIR/platform_p.h \
+ $$PHONON_DIR/platformplugin.h \
+ $$PHONON_DIR/qsettingsgroup_p.h \
+ $$PHONON_DIR/seekslider.h \
+ $$PHONON_DIR/seekslider_p.h \
+ $$PHONON_DIR/streaminterface.h \
+ $$PHONON_DIR/streaminterface_p.h \
+ $$PHONON_DIR/swiftslider_p.h \
+ $$PHONON_DIR/videoplayer.h \
+ $$PHONON_DIR/videowidget.h \
+ $$PHONON_DIR/videowidget_p.h \
+ $$PHONON_DIR/videowidgetinterface.h \
+ $$PHONON_DIR/volumefadereffect.h \
+ $$PHONON_DIR/volumefadereffect_p.h \
+ $$PHONON_DIR/volumefaderinterface.h \
+ $$PHONON_DIR/volumeslider.h \
+ $$PHONON_DIR/volumeslider_p.h
+
+SOURCES += $$PHONON_DIR/abstractaudiooutput.cpp \
+ $$PHONON_DIR/abstractaudiooutput_p.cpp \
+ $$PHONON_DIR/abstractmediastream.cpp \
+ $$PHONON_DIR/abstractvideooutput.cpp \
+ $$PHONON_DIR/abstractvideooutput_p.cpp \
+ $$PHONON_DIR/audiodataoutput.cpp \
+ $$PHONON_DIR/audiooutput.cpp \
+ $$PHONON_DIR/audiooutputinterface.cpp \
+ $$PHONON_DIR/backendcapabilities.cpp \
+ $$PHONON_DIR/effect.cpp \
+ $$PHONON_DIR/effectparameter.cpp \
+ $$PHONON_DIR/effectwidget.cpp \
+ $$PHONON_DIR/factory.cpp \
+ $$PHONON_DIR/globalconfig.cpp \
+ $$PHONON_DIR/iodevicestream.cpp \
+ $$PHONON_DIR/mediacontroller.cpp \
+ $$PHONON_DIR/medianode.cpp \
+ $$PHONON_DIR/mediaobject.cpp \
+ $$PHONON_DIR/mediasource.cpp \
+ $$PHONON_DIR/objectdescription.cpp \
+ $$PHONON_DIR/objectdescriptionmodel.cpp \
+ $$PHONON_DIR/path.cpp \
+ $$PHONON_DIR/phononnamespace.cpp \
+ $$PHONON_DIR/platform.cpp \
+ $$PHONON_DIR/pulsesupport.cpp \
+ $$PHONON_DIR/seekslider.cpp \
+ $$PHONON_DIR/streaminterface.cpp \
+ $$PHONON_DIR/swiftslider.cpp \
+ $$PHONON_DIR/videoplayer.cpp \
+ $$PHONON_DIR/videowidget.cpp \
+ $$PHONON_DIR/volumefadereffect.cpp \
+ $$PHONON_DIR/volumeslider.cpp
+
+contains(QT_CONFIG, dbus) {
+ QT += dbus
+ HEADERS += $$PHONON_DIR/audiooutputadaptor_p.h
+ SOURCES += $$PHONON_DIR/audiooutputadaptor.cpp
+ unix:QMAKE_PKGCONFIG_REQUIRES += QtDBus
+} else {
+ DEFINES += QT_NO_DBUS
+}
+
+contains(QT_CONFIG, reduce_exports): CONFIG += hide_symbols
+
+unix:!isEmpty(QT_CFLAGS_PULSEAUDIO) {
+ DEFINES += HAVE_PULSEAUDIO
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_PULSEAUDIO
+ LIBS += $$QT_LIBS_PULSEAUDIO
+}
+
+symbian: {
+ # Phonon depends on numeric_limits. Enabling STL support in Qt
+ # would bring in link dependencies, and we don't need that for
+ # numeric_limits, hence we here merely ensure we bring in the necessary
+ # header.
+ INCLUDEPATH *= $$OS_LAYER_STDCPP_SYSTEMINCLUDE
+
+ # Without this setting, code using numeric_limits will fail
+ # for winscw, although armv5 works fine no matter what.
+ QMAKE_CXXFLAGS.CW *= $$STLLIB_USAGE_CW_FLAGS
+
+ TARGET.UID3 = 0x2001E624
+}
diff --git a/src/plugins/phonon/ds9/ds9.pro b/src/plugins/phonon/ds9/ds9.pro
new file mode 100644
index 0000000..301808e
--- /dev/null
+++ b/src/plugins/phonon/ds9/ds9.pro
@@ -0,0 +1,66 @@
+DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend
+QT += phonon
+win32:!wince*:contains(QT_CONFIG,opengl):LIBS += -lopengl32
+win32:!wince*:LIBS += -lgdi32
+win32-msvc2005:DEFINES += _CRT_SECURE_NO_WARNINGS
+LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32
+TARGET = phonon_ds9
+
+DEFINES += PHONON_MAKE_QT_ONLY_BACKEND
+PHONON_DS9_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/ds9
+
+# Input
+HEADERS += \
+ $$PHONON_DS9_DIR/abstractvideorenderer.h \
+ $$PHONON_DS9_DIR/audiooutput.h \
+ $$PHONON_DS9_DIR/backend.h \
+ $$PHONON_DS9_DIR/backendnode.h \
+ $$PHONON_DS9_DIR/effect.h \
+ $$PHONON_DS9_DIR/fakesource.h \
+ $$PHONON_DS9_DIR/iodevicereader.h \
+ $$PHONON_DS9_DIR/mediagraph.h \
+ $$PHONON_DS9_DIR/mediaobject.h \
+ $$PHONON_DS9_DIR/videowidget.h \
+ $$PHONON_DS9_DIR/videorenderer_soft.h \
+ $$PHONON_DS9_DIR/volumeeffect.h \
+ $$PHONON_DS9_DIR/qbasefilter.h \
+ $$PHONON_DS9_DIR/qpin.h \
+ $$PHONON_DS9_DIR/qasyncreader.h \
+ $$PHONON_DS9_DIR/qaudiocdreader.h \
+ $$PHONON_DS9_DIR/qmeminputpin.h \
+ $$PHONON_DS9_DIR/compointer.h \
+ $$PHONON_DS9_DIR/phononds9_namespace.h
+
+
+SOURCES += \
+ $$PHONON_DS9_DIR/abstractvideorenderer.cpp \
+ $$PHONON_DS9_DIR/audiooutput.cpp \
+ $$PHONON_DS9_DIR/backend.cpp \
+ $$PHONON_DS9_DIR/backendnode.cpp \
+ $$PHONON_DS9_DIR/effect.cpp \
+ $$PHONON_DS9_DIR/fakesource.cpp \
+ $$PHONON_DS9_DIR/iodevicereader.cpp \
+ $$PHONON_DS9_DIR/mediagraph.cpp \
+ $$PHONON_DS9_DIR/mediaobject.cpp \
+ $$PHONON_DS9_DIR/videowidget.cpp \
+ $$PHONON_DS9_DIR/videorenderer_soft.cpp \
+ $$PHONON_DS9_DIR/volumeeffect.cpp \
+ $$PHONON_DS9_DIR/qbasefilter.cpp \
+ $$PHONON_DS9_DIR/qpin.cpp \
+ $$PHONON_DS9_DIR/qasyncreader.cpp \
+ $$PHONON_DS9_DIR/qaudiocdreader.cpp \
+ $$PHONON_DS9_DIR/qmeminputpin.cpp
+
+#the EVR renderer (only available on desktop)
+!wince*:SOURCES += $$PHONON_DS9_DIR/videorenderer_evr.cpp \
+ $$PHONON_DS9_DIR/videorenderer_vmr9.cpp
+!wince*:HEADERS += $$PHONON_DS9_DIR/qevr9.h \
+ $$PHONON_DS9_DIR/videorenderer_evr.h \
+ $$PHONON_DS9_DIR/videorenderer_vmr9.h
+wince*:SOURCES += $$PHONON_DS9_DIR/videorenderer_default.cpp
+wince*:HEADERS += $$PHONON_DS9_DIR/videorenderer_default.h
+
+target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend
+INSTALLS += target
+
+include(../../qpluginbase.pri)
diff --git a/src/plugins/phonon/gstreamer/gstreamer.pro b/src/plugins/phonon/gstreamer/gstreamer.pro
new file mode 100644
index 0000000..c0d2604
--- /dev/null
+++ b/src/plugins/phonon/gstreamer/gstreamer.pro
@@ -0,0 +1,69 @@
+TARGET = phonon_gstreamer
+DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend
+
+DEPENDPATH += .
+INCLUDEPATH += .
+
+QT += phonon
+contains(QT_CONFIG, opengl):QT += opengl
+
+# GStreamer
+QMAKE_CXXFLAGS += $$QT_CFLAGS_GSTREAMER
+LIBS += $$QT_LIBS_GSTREAMER -lgstinterfaces-0.10 -lgstvideo-0.10 -lgstbase-0.10 -lgstaudio-0.10
+
+PHONON_GSTREAMER_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/gstreamer
+
+HEADERS += $$PHONON_GSTREAMER_DIR/common.h \
+ $$PHONON_GSTREAMER_DIR/audiooutput.h \
+ $$PHONON_GSTREAMER_DIR/audiodataoutput.h \
+ $$PHONON_GSTREAMER_DIR/artssink.h \
+ $$PHONON_GSTREAMER_DIR/abstractrenderer.h \
+ $$PHONON_GSTREAMER_DIR/backend.h \
+ $$PHONON_GSTREAMER_DIR/devicemanager.h \
+ $$PHONON_GSTREAMER_DIR/effect.h \
+ $$PHONON_GSTREAMER_DIR/effectmanager.h \
+ $$PHONON_GSTREAMER_DIR/gsthelper.h \
+ $$PHONON_GSTREAMER_DIR/mediaobject.h \
+ $$PHONON_GSTREAMER_DIR/medianode.h \
+ $$PHONON_GSTREAMER_DIR/medianodeevent.h \
+ $$PHONON_GSTREAMER_DIR/widgetrenderer.h \
+ $$PHONON_GSTREAMER_DIR/videowidget.h \
+ $$PHONON_GSTREAMER_DIR/glrenderer.h \
+ $$PHONON_GSTREAMER_DIR/qwidgetvideosink.h \
+ $$PHONON_GSTREAMER_DIR/phononsrc.h \
+ $$PHONON_GSTREAMER_DIR/streamreader.h \
+ $$PHONON_GSTREAMER_DIR/message.h \
+ $$PHONON_GSTREAMER_DIR/audioeffect.h \
+ $$PHONON_GSTREAMER_DIR/volumefadereffect.h
+
+SOURCES += $$PHONON_GSTREAMER_DIR/abstractrenderer.cpp \
+ $$PHONON_GSTREAMER_DIR/artssink.cpp \
+ $$PHONON_GSTREAMER_DIR/audioeffect.cpp \
+ $$PHONON_GSTREAMER_DIR/audiooutput.cpp \
+ $$PHONON_GSTREAMER_DIR/audiodataoutput.cpp \
+ $$PHONON_GSTREAMER_DIR/backend.cpp \
+ $$PHONON_GSTREAMER_DIR/devicemanager.cpp \
+ $$PHONON_GSTREAMER_DIR/effect.cpp \
+ $$PHONON_GSTREAMER_DIR/effectmanager.cpp \
+ $$PHONON_GSTREAMER_DIR/glrenderer.cpp \
+ $$PHONON_GSTREAMER_DIR/gsthelper.cpp \
+ $$PHONON_GSTREAMER_DIR/medianode.cpp \
+ $$PHONON_GSTREAMER_DIR/medianodeevent.cpp \
+ $$PHONON_GSTREAMER_DIR/mediaobject.cpp \
+ $$PHONON_GSTREAMER_DIR/message.cpp \
+ $$PHONON_GSTREAMER_DIR/phononsrc.cpp \
+ $$PHONON_GSTREAMER_DIR/qwidgetvideosink.cpp \
+ $$PHONON_GSTREAMER_DIR/streamreader.cpp \
+ $$PHONON_GSTREAMER_DIR/videowidget.cpp \
+ $$PHONON_GSTREAMER_DIR/volumefadereffect.cpp \
+ $$PHONON_GSTREAMER_DIR/widgetrenderer.cpp
+
+!qpa:!embedded{
+ HEADERS += $$PHONON_GSTREAMER_DIR/x11renderer.h
+ SOURCES += $$PHONON_GSTREAMER_DIR/x11renderer.cpp
+}
+
+target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend
+INSTALLS += target
+
+include(../../qpluginbase.pri)
diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro
new file mode 100644
index 0000000..7c7c1d7
--- /dev/null
+++ b/src/plugins/phonon/mmf/mmf.pro
@@ -0,0 +1,146 @@
+# MMF Phonon backend
+symbian {
+ QT += phonon
+ TARGET = phonon_mmf
+ PHONON_MMF_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/mmf
+
+ # Uncomment the following line in order to use the CDrmPlayerUtility client
+ # API for audio playback, rather than CMdaAudioPlayerUtility.
+ #CONFIG += phonon_mmf_audio_drm
+
+ phonon_mmf_audio_drm {
+ LIBS += -lDrmAudioPlayUtility
+ DEFINES += QT_PHONON_MMF_AUDIO_DRM
+ } else {
+ LIBS += -lmediaclientaudio
+ }
+
+ # This is necessary because both epoc32/include and Phonon contain videoplayer.h.
+ # By making /epoc32/include the first SYSTEMINCLUDE, we ensure that
+ # '#include <videoplayer.h>' picks up the Symbian header, as intended.
+ PREPEND_INCLUDEPATH = $${EPOCROOT}epoc32/include
+
+ PREPEND_INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty
+
+ INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+
+ HEADERS += \
+ $$PHONON_MMF_DIR/abstractaudioeffect.h \
+ $$PHONON_MMF_DIR/abstractmediaplayer.h \
+ $$PHONON_MMF_DIR/abstractplayer.h \
+ $$PHONON_MMF_DIR/abstractvideooutput.h \
+ $$PHONON_MMF_DIR/abstractvideoplayer.h \
+ $$PHONON_MMF_DIR/audioequalizer.h \
+ $$PHONON_MMF_DIR/audiooutput.h \
+ $$PHONON_MMF_DIR/audioplayer.h \
+ $$PHONON_MMF_DIR/backend.h \
+ $$PHONON_MMF_DIR/bassboost.h \
+ $$PHONON_MMF_DIR/defs.h \
+ $$PHONON_MMF_DIR/dummyplayer.h \
+ $$PHONON_MMF_DIR/effectfactory.h \
+ $$PHONON_MMF_DIR/effectparameter.h \
+ $$PHONON_MMF_DIR/environmentalreverb.h \
+ $$PHONON_MMF_DIR/loudness.h \
+ $$PHONON_MMF_DIR/mediaobject.h \
+ $$PHONON_MMF_DIR/mmf_medianode.h \
+ $$PHONON_MMF_DIR/stereowidening.h \
+ $$PHONON_MMF_DIR/objectdump.h \
+ $$PHONON_MMF_DIR/objectdump_symbian.h \
+ $$PHONON_MMF_DIR/objecttree.h \
+ $$PHONON_MMF_DIR/utils.h \
+ $$PHONON_MMF_DIR/videowidget.h
+
+ SOURCES += \
+ $$PHONON_MMF_DIR/abstractaudioeffect.cpp \
+ $$PHONON_MMF_DIR/abstractmediaplayer.cpp \
+ $$PHONON_MMF_DIR/abstractplayer.cpp \
+ $$PHONON_MMF_DIR/audioequalizer.cpp \
+ $$PHONON_MMF_DIR/audiooutput.cpp \
+ $$PHONON_MMF_DIR/audioplayer.cpp \
+ $$PHONON_MMF_DIR/abstractvideooutput.cpp \
+ $$PHONON_MMF_DIR/abstractvideoplayer.cpp \
+ $$PHONON_MMF_DIR/backend.cpp \
+ $$PHONON_MMF_DIR/bassboost.cpp \
+ $$PHONON_MMF_DIR/dummyplayer.cpp \
+ $$PHONON_MMF_DIR/effectfactory.cpp \
+ $$PHONON_MMF_DIR/effectparameter.cpp \
+ $$PHONON_MMF_DIR/environmentalreverb.cpp \
+ $$PHONON_MMF_DIR/loudness.cpp \
+ $$PHONON_MMF_DIR/mediaobject.cpp \
+ $$PHONON_MMF_DIR/mmf_medianode.cpp \
+ $$PHONON_MMF_DIR/stereowidening.cpp \
+ $$PHONON_MMF_DIR/objectdump.cpp \
+ $$PHONON_MMF_DIR/objectdump_symbian.cpp \
+ $$PHONON_MMF_DIR/objecttree.cpp \
+ $$PHONON_MMF_DIR/utils.cpp \
+ $$PHONON_MMF_DIR/videowidget.cpp
+
+ symbian {
+ # Test for whether the build environment supports video rendering to graphics
+ # surfaces.
+ exists($${EPOCROOT}epoc32/include/platform/videoplayer2.h) {
+ HEADERS += \
+ $$PHONON_MMF_DIR/videooutput_surface.h \
+ $$PHONON_MMF_DIR/videoplayer_surface.h
+ SOURCES += \
+ $$PHONON_MMF_DIR/videooutput_surface.cpp \
+ $$PHONON_MMF_DIR/videoplayer_surface.cpp
+ DEFINES += PHONON_MMF_VIDEO_SURFACES
+ } else {
+ HEADERS += \
+ $$PHONON_MMF_DIR/ancestormovemonitor.h \
+ $$PHONON_MMF_DIR/videooutput_dsa.h \
+ $$PHONON_MMF_DIR/videoplayer_dsa.h
+ SOURCES += \
+ $$PHONON_MMF_DIR/ancestormovemonitor.cpp \
+ $$PHONON_MMF_DIR/videooutput_dsa.cpp \
+ $$PHONON_MMF_DIR/videoplayer_dsa.cpp \
+ }
+
+ # Test whether the build environment includes support for the Download Manager
+ # API, required for Progressive Download
+ exists($${EPOCROOT}epoc32/include/downloadmgrclient.h) | \
+ exists($${EPOCROOT}epoc32/include/mw/downloadmgrclient.h) {
+ HEADERS += $$PHONON_MMF_DIR/download.h
+ SOURCES += $$PHONON_MMF_DIR/download.cpp
+ LIBS += -lDownloadMgr
+ DEFINES += PHONON_MMF_PROGRESSIVE_DOWNLOAD
+ }
+ }
+
+ LIBS += -lcone
+ LIBS += -lws32
+
+ # This is only needed for debug builds, but is always linked against.
+ LIBS += -lhal
+
+ TARGET.CAPABILITY = all -tcb
+
+ LIBS += -lmediaclientvideo # For CVideoPlayerUtility
+ LIBS += -lcone # For CCoeEnv
+ LIBS += -lws32 # For RWindow
+ LIBS += -lefsrv # For file server
+ LIBS += -lapgrfx -lapmime # For recognizer
+ LIBS += -lmmfcontrollerframework # For CMMFMetaDataEntry
+ LIBS += -lmediaclientaudiostream # For CMdaAudioOutputStream
+
+ # These are for effects.
+ is_using_gnupoc {
+ LIBS += -laudioequalizereffect -lbassboosteffect -ldistanceattenuationeffect -ldopplerbase -leffectbase -lenvironmentalreverbeffect -llistenerdopplereffect -llistenerlocationeffect -llistenerorientationeffect -llocationbase -lloudnesseffect -lorientationbase -lsourcedopplereffect -lsourcelocationeffect -lsourceorientationeffect -lstereowideningeffect
+ } else {
+ LIBS += -lAudioEqualizerEffect -lBassBoostEffect -lDistanceAttenuationEffect -lDopplerbase -lEffectBase -lEnvironmentalReverbEffect -lListenerDopplerEffect -lListenerLocationEffect -lListenerOrientationEffect -lLocationBase -lLoudnessEffect -lOrientationBase -lSourceDopplerEffect -lSourceLocationEffect -lSourceOrientationEffect -lStereoWideningEffect
+ }
+
+ # This is to allow IAP to be specified
+ LIBS += -lcommdb
+
+ # This is needed for having the .qtplugin file properly created on Symbian.
+ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend
+
+ target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend
+ INSTALLS += target
+
+ include(../../qpluginbase.pri)
+
+ TARGET.UID3=0x2001E629
+}
diff --git a/src/plugins/phonon/phonon.pro b/src/plugins/phonon/phonon.pro
new file mode 100644
index 0000000..803d8f9
--- /dev/null
+++ b/src/plugins/phonon/phonon.pro
@@ -0,0 +1,14 @@
+TEMPLATE = subdirs
+
+SUBDIRS =
+
+unix:contains(QT_CONFIG, gstreamer): SUBDIRS *= gstreamer
+mac:contains(QT_CONFIG, phonon-backend): SUBDIRS *= qt7
+win32:!wince*:contains(QT_CONFIG, phonon-backend): SUBDIRS *= ds9
+wince*:contains(QT_CONFIG, phonon-backend): SUBDIRS *= waveout
+wince*:contains(QT_CONFIG, directshow): SUBDIRS *= ds9
+
+# Note that the MMF backend is in some scenarios an important complement to the
+# Helix backend: the latter requires Symbian signed capabilities, hence MMF
+# provides multimedia for self signed scenarios.
+symbian:contains(QT_CONFIG, phonon-backend): SUBDIRS *= mmf
diff --git a/src/plugins/phonon/qt7/qt7.pro b/src/plugins/phonon/qt7/qt7.pro
new file mode 100644
index 0000000..53407db
--- /dev/null
+++ b/src/plugins/phonon/qt7/qt7.pro
@@ -0,0 +1,76 @@
+QT += opengl phonon
+TARGET = phonon_qt7
+DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend
+
+# 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
+}
+
+LIBS += -framework AppKit -framework AudioUnit \
+ -framework AudioToolbox -framework CoreAudio \
+ -framework QuartzCore -framework QTKit
+
+DEPENDPATH += .
+INCLUDEPATH += .
+
+PHONON_QUICKTIME_DIR=$$QT_SOURCE_TREE/src/3rdparty/phonon/qt7
+
+# Input
+HEADERS += $$PHONON_QUICKTIME_DIR/medianode.h \
+ $$PHONON_QUICKTIME_DIR/backend.h \
+ $$PHONON_QUICKTIME_DIR/videowidget.h \
+ $$PHONON_QUICKTIME_DIR/mediaobject.h \
+ $$PHONON_QUICKTIME_DIR/quicktimevideoplayer.h \
+ $$PHONON_QUICKTIME_DIR/backendheader.h \
+ $$PHONON_QUICKTIME_DIR/medianodevideopart.h \
+ $$PHONON_QUICKTIME_DIR/medianodeevent.h \
+ $$PHONON_QUICKTIME_DIR/quicktimeaudioplayer.h \
+ $$PHONON_QUICKTIME_DIR/audionode.h \
+ $$PHONON_QUICKTIME_DIR/audiograph.h \
+ $$PHONON_QUICKTIME_DIR/audiooutput.h \
+ $$PHONON_QUICKTIME_DIR/quicktimemetadata.h \
+ $$PHONON_QUICKTIME_DIR/audiomixer.h \
+ $$PHONON_QUICKTIME_DIR/audiodevice.h \
+ $$PHONON_QUICKTIME_DIR/backendinfo.h \
+ $$PHONON_QUICKTIME_DIR/audioconnection.h \
+ $$PHONON_QUICKTIME_DIR/audiopartoutput.h \
+ $$PHONON_QUICKTIME_DIR/videoframe.h \
+ $$PHONON_QUICKTIME_DIR/audiosplitter.h \
+ $$PHONON_QUICKTIME_DIR/audioeffects.h \
+ $$PHONON_QUICKTIME_DIR/quicktimestreamreader.h \
+ $$PHONON_QUICKTIME_DIR/mediaobjectaudionode.h
+# HEADERS += objc_help.h videoeffect.h
+
+OBJECTIVE_SOURCES += $$PHONON_QUICKTIME_DIR/quicktimevideoplayer.mm \
+ $$PHONON_QUICKTIME_DIR/backendheader.mm \
+ $$PHONON_QUICKTIME_DIR/medianodevideopart.mm \
+ $$PHONON_QUICKTIME_DIR/medianodeevent.mm \
+ $$PHONON_QUICKTIME_DIR/audiooutput.mm \
+ $$PHONON_QUICKTIME_DIR/backendinfo.mm \
+ $$PHONON_QUICKTIME_DIR/audiosplitter.mm \
+ $$PHONON_QUICKTIME_DIR/audioeffects.mm \
+ $$PHONON_QUICKTIME_DIR/quicktimestreamreader.mm \
+ $$PHONON_QUICKTIME_DIR/medianode.mm \
+ $$PHONON_QUICKTIME_DIR/backend.mm \
+ $$PHONON_QUICKTIME_DIR/mediaobject.mm \
+ $$PHONON_QUICKTIME_DIR/mediaobjectaudionode.mm \
+ $$PHONON_QUICKTIME_DIR/audiomixer.mm \
+ $$PHONON_QUICKTIME_DIR/quicktimeaudioplayer.mm \
+ $$PHONON_QUICKTIME_DIR/videoframe.mm \
+ $$PHONON_QUICKTIME_DIR/quicktimemetadata.mm \
+ $$PHONON_QUICKTIME_DIR/audiodevice.mm \
+ $$PHONON_QUICKTIME_DIR/audioconnection.mm \
+ $$PHONON_QUICKTIME_DIR/audiograph.mm \
+ $$PHONON_QUICKTIME_DIR/audionode.mm \
+ $$PHONON_QUICKTIME_DIR/videowidget.mm
+
+target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend
+INSTALLS += target
+
+include(../../qpluginbase.pri)
diff --git a/src/plugins/phonon/waveout/waveout.pro b/src/plugins/phonon/waveout/waveout.pro
new file mode 100644
index 0000000..1e2bd33
--- /dev/null
+++ b/src/plugins/phonon/waveout/waveout.pro
@@ -0,0 +1,23 @@
+DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend
+QT += phonon
+win32-msvc2005:DEFINES += _CRT_SECURE_NO_WARNINGS
+TARGET = phonon_waveout
+
+DEFINES += PHONON_MAKE_QT_ONLY_BACKEND
+PHONON_WAVEOUT_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/waveout
+
+# Input
+HEADERS += $$PHONON_WAVEOUT_DIR/audiooutput.h \
+ $$PHONON_WAVEOUT_DIR/backend.h \
+ $$PHONON_WAVEOUT_DIR/mediaobject.h
+
+
+SOURCES += $$PHONON_WAVEOUT_DIR/audiooutput.cpp \
+ $$PHONON_WAVEOUT_DIR/backend.cpp \
+ $$PHONON_WAVEOUT_DIR/mediaobject.cpp
+
+
+target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend
+INSTALLS += target
+
+include(../../qpluginbase.pri)
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..f94d5a2
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,18 @@
+This directory contains autotests and benchmarks based on QTestlib. In order
+to run the autotests reliably, you need to configure a desktop to match the
+test environment that these tests are written for.
+
+Linux X11:
+
+ * The user must be logged in to an active desktop; you can't run the
+ autotests without a valid DISPLAY that allows X11 connections.
+
+ * The tests are run against a KDE3 or KDE4 desktop.
+
+ * Window manager uses "click to focus", and not "focus follows mouse". Many
+ tests move the mouse cursor around and expect this to not affect focus
+ and activation.
+
+ * Disable "click to activate", i.e., when a window is opened, the window
+ manager should automatically activate it (give it input focus) and not
+ wait for the user to click the window.
diff --git a/tests/auto/bic/.gitignore b/tests/auto/bic/.gitignore
new file mode 100644
index 0000000..6f26b86
--- /dev/null
+++ b/tests/auto/bic/.gitignore
@@ -0,0 +1,2 @@
+qt_temp.*.*lass
+test.cpp
diff --git a/tests/auto/bic/data/phonon.4.5.0.linux-gcc-amd64.txt b/tests/auto/bic/data/phonon.4.5.0.linux-gcc-amd64.txt
new file mode 100644
index 0000000..08dbee8
--- /dev/null
+++ b/tests/auto/bic/data/phonon.4.5.0.linux-gcc-amd64.txt
@@ -0,0 +1,1931 @@
+
+Class QSysInfo
+ size=1 align=1
+ base size=0 base align=1
+QSysInfo (0x7f09e42d13f0) 0 empty
+
+Class QBool
+ size=1 align=1
+ base size=1 base align=1
+QBool (0x7f09e42e80e0) 0
+
+Class qIsNull(double)::U
+ size=8 align=8
+ base size=8 base align=8
+qIsNull(double)::U (0x7f09e42fd4d0) 0
+
+Class qIsNull(float)::U
+ size=4 align=4
+ base size=4 base align=4
+qIsNull(float)::U (0x7f09e42fd770) 0
+
+Class QFlag
+ size=4 align=4
+ base size=4 base align=4
+QFlag (0x7f09e3a1c5b0) 0
+
+Class QIncompatibleFlag
+ size=4 align=4
+ base size=4 base align=4
+QIncompatibleFlag (0x7f09e3a1cd90) 0
+
+Class QBasicAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QBasicAtomicInt (0x7f09e3a483f0) 0
+
+Class QAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QAtomicInt (0x7f09e3a9dd90) 0
+ QBasicAtomicInt (0x7f09e3a9de00) 0
+
+Class QSharedData
+ size=4 align=4
+ base size=4 base align=4
+QSharedData (0x7f09e3ac0230) 0
+
+Class QLatin1Char
+ size=1 align=1
+ base size=1 base align=1
+QLatin1Char (0x7f09e3928700) 0
+
+Class QChar
+ size=2 align=2
+ base size=2 base align=2
+QChar (0x7f09e3950af0) 0
+
+Vtable for std::exception
+std::exception::_ZTVSt9exception: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9exception)
+16 std::exception::~exception
+24 std::exception::~exception
+32 std::exception::what
+
+Class std::exception
+ size=8 align=8
+ base size=8 base align=8
+std::exception (0x7f09e39bbbd0) 0 nearly-empty
+ vptr=((& std::exception::_ZTVSt9exception) + 16u)
+
+Vtable for std::bad_exception
+std::bad_exception::_ZTVSt13bad_exception: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt13bad_exception)
+16 std::bad_exception::~bad_exception
+24 std::bad_exception::~bad_exception
+32 std::bad_exception::what
+
+Class std::bad_exception
+ size=8 align=8
+ base size=8 base align=8
+std::bad_exception (0x7f09e39c8150) 0 nearly-empty
+ vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u)
+ std::exception (0x7f09e39c81c0) 0 nearly-empty
+ primary-for std::bad_exception (0x7f09e39c8150)
+
+Vtable for std::bad_alloc
+std::bad_alloc::_ZTVSt9bad_alloc: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9bad_alloc)
+16 std::bad_alloc::~bad_alloc
+24 std::bad_alloc::~bad_alloc
+32 std::bad_alloc::what
+
+Class std::bad_alloc
+ size=8 align=8
+ base size=8 base align=8
+std::bad_alloc (0x7f09e39c8a10) 0 nearly-empty
+ vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u)
+ std::exception (0x7f09e39c8a80) 0 nearly-empty
+ primary-for std::bad_alloc (0x7f09e39c8a10)
+
+Class std::nothrow_t
+ size=1 align=1
+ base size=0 base align=1
+std::nothrow_t (0x7f09e39db230) 0 empty
+
+Class QListData::Data
+ size=32 align=8
+ base size=32 base align=8
+QListData::Data (0x7f09e39db770) 0
+
+Class QListData
+ size=8 align=8
+ base size=8 base align=8
+QListData (0x7f09e39db700) 0
+
+Class QInternal
+ size=1 align=1
+ base size=0 base align=1
+QInternal (0x7f09e3699e00) 0 empty
+
+Class QGenericArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericArgument (0x7f09e36b3150) 0
+
+Class QGenericReturnArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericReturnArgument (0x7f09e36b3cb0) 0
+ QGenericArgument (0x7f09e36b3d20) 0
+
+Class QMetaObject
+ size=32 align=8
+ base size=32 base align=8
+QMetaObject (0x7f09e36bf5b0) 0
+
+Class QMetaObjectExtraData
+ size=16 align=8
+ base size=16 base align=8
+QMetaObjectExtraData (0x7f09e36e65b0) 0
+
+Class __locale_struct
+ size=232 align=8
+ base size=232 base align=8
+__locale_struct (0x7f09e36f9000) 0
+
+Class QByteArray::Data
+ size=32 align=8
+ base size=32 base align=8
+QByteArray::Data (0x7f09e3564620) 0
+
+Class QByteArray
+ size=8 align=8
+ base size=8 base align=8
+QByteArray (0x7f09e3523380) 0
+
+Class QByteRef
+ size=16 align=8
+ base size=12 base align=8
+QByteRef (0x7f09e35ba8c0) 0
+
+Class QString::Null
+ size=1 align=1
+ base size=0 base align=1
+QString::Null (0x7f09e34c3540) 0 empty
+
+Class QString::Data
+ size=32 align=8
+ base size=32 base align=8
+QString::Data (0x7f09e34d2d20) 0
+
+Class QString
+ size=8 align=8
+ base size=8 base align=8
+QString (0x7f09e34443f0) 0
+
+Class QLatin1String
+ size=8 align=8
+ base size=8 base align=8
+QLatin1String (0x7f09e33a7e00) 0
+
+Class QCharRef
+ size=16 align=8
+ base size=12 base align=8
+QCharRef (0x7f09e3243460) 0
+
+Class QConstString
+ size=8 align=8
+ base size=8 base align=8
+QConstString (0x7f09e318dcb0) 0
+ QString (0x7f09e318dd20) 0
+
+Class QStringRef
+ size=16 align=8
+ base size=16 base align=8
+QStringRef (0x7f09e31ab9a0) 0
+
+Vtable for QObjectData
+QObjectData::_ZTV11QObjectData: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QObjectData)
+16 __cxa_pure_virtual
+24 __cxa_pure_virtual
+
+Class QObjectData
+ size=40 align=8
+ base size=40 base align=8
+QObjectData (0x7f09e3029cb0) 0
+ vptr=((& QObjectData::_ZTV11QObjectData) + 16u)
+
+Vtable for QObject
+QObject::_ZTV7QObject: 14u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QObject)
+16 QObject::metaObject
+24 QObject::qt_metacast
+32 QObject::qt_metacall
+40 QObject::~QObject
+48 QObject::~QObject
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+
+Class QObject
+ size=16 align=8
+ base size=16 base align=8
+QObject (0x7f09e3029f50) 0
+ vptr=((& QObject::_ZTV7QObject) + 16u)
+
+Vtable for QObjectUserData
+QObjectUserData::_ZTV15QObjectUserData: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QObjectUserData)
+16 QObjectUserData::~QObjectUserData
+24 QObjectUserData::~QObjectUserData
+
+Class QObjectUserData
+ size=8 align=8
+ base size=8 base align=8
+QObjectUserData (0x7f09e30a64d0) 0 nearly-empty
+ vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u)
+
+Vtable for QIODevice
+QIODevice::_ZTV9QIODevice: 30u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QIODevice)
+16 QIODevice::metaObject
+24 QIODevice::qt_metacast
+32 QIODevice::qt_metacall
+40 QIODevice::~QIODevice
+48 QIODevice::~QIODevice
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QIODevice::isSequential
+120 QIODevice::open
+128 QIODevice::close
+136 QIODevice::pos
+144 QIODevice::size
+152 QIODevice::seek
+160 QIODevice::atEnd
+168 QIODevice::reset
+176 QIODevice::bytesAvailable
+184 QIODevice::bytesToWrite
+192 QIODevice::canReadLine
+200 QIODevice::waitForReadyRead
+208 QIODevice::waitForBytesWritten
+216 __cxa_pure_virtual
+224 QIODevice::readLineData
+232 __cxa_pure_virtual
+
+Class QIODevice
+ size=16 align=8
+ base size=16 base align=8
+QIODevice (0x7f09e30a6a10) 0
+ vptr=((& QIODevice::_ZTV9QIODevice) + 16u)
+ QObject (0x7f09e30a6a80) 0
+ primary-for QIODevice (0x7f09e30a6a10)
+
+Vtable for QDataStream
+QDataStream::_ZTV11QDataStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QDataStream)
+16 QDataStream::~QDataStream
+24 QDataStream::~QDataStream
+
+Class QDataStream
+ size=40 align=8
+ base size=40 base align=8
+QDataStream (0x7f09e2f0d380) 0
+ vptr=((& QDataStream::_ZTV11QDataStream) + 16u)
+
+Class QHashData::Node
+ size=16 align=8
+ base size=16 base align=8
+QHashData::Node (0x7f09e2f91230) 0
+
+Class QHashData
+ size=40 align=8
+ base size=40 base align=8
+QHashData (0x7f09e2f911c0) 0
+
+Class QHashDummyValue
+ size=1 align=1
+ base size=0 base align=1
+QHashDummyValue (0x7f09e2fa6000) 0 empty
+
+Class QMapData::Node
+ size=16 align=8
+ base size=16 base align=8
+QMapData::Node (0x7f09e2eb4770) 0
+
+Class QMapData
+ size=128 align=8
+ base size=128 base align=8
+QMapData (0x7f09e2eb4700) 0
+
+Vtable for QSystemLocale
+QSystemLocale::_ZTV13QSystemLocale: 6u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QSystemLocale)
+16 QSystemLocale::~QSystemLocale
+24 QSystemLocale::~QSystemLocale
+32 QSystemLocale::query
+40 QSystemLocale::fallbackLocale
+
+Class QSystemLocale
+ size=8 align=8
+ base size=8 base align=8
+QSystemLocale (0x7f09e2dc3ee0) 0 nearly-empty
+ vptr=((& QSystemLocale::_ZTV13QSystemLocale) + 16u)
+
+Class QLocale::Data
+ size=4 align=2
+ base size=4 base align=2
+QLocale::Data (0x7f09e2c274d0) 0
+
+Class QLocale
+ size=8 align=8
+ base size=8 base align=8
+QLocale (0x7f09e2de71c0) 0
+
+Class QTextCodec::ConverterState
+ size=32 align=8
+ base size=32 base align=8
+QTextCodec::ConverterState (0x7f09e2c75f50) 0
+
+Vtable for QTextCodec
+QTextCodec::_ZTV10QTextCodec: 9u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QTextCodec)
+16 __cxa_pure_virtual
+24 QTextCodec::aliases
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 QTextCodec::~QTextCodec
+64 QTextCodec::~QTextCodec
+
+Class QTextCodec
+ size=8 align=8
+ base size=8 base align=8
+QTextCodec (0x7f09e2c5fb60) 0 nearly-empty
+ vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u)
+
+Class QTextEncoder
+ size=40 align=8
+ base size=40 base align=8
+QTextEncoder (0x7f09e2ce14d0) 0
+
+Class QTextDecoder
+ size=40 align=8
+ base size=40 base align=8
+QTextDecoder (0x7f09e2aea310) 0
+
+Class _IO_marker
+ size=24 align=8
+ base size=24 base align=8
+_IO_marker (0x7f09e2af3380) 0
+
+Class _IO_FILE
+ size=216 align=8
+ base size=216 base align=8
+_IO_FILE (0x7f09e2af33f0) 0
+
+Vtable for QTextStream
+QTextStream::_ZTV11QTextStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTextStream)
+16 QTextStream::~QTextStream
+24 QTextStream::~QTextStream
+
+Class QTextStream
+ size=16 align=8
+ base size=16 base align=8
+QTextStream (0x7f09e2af34d0) 0
+ vptr=((& QTextStream::_ZTV11QTextStream) + 16u)
+
+Class QTextStreamManipulator
+ size=40 align=8
+ base size=38 base align=8
+QTextStreamManipulator (0x7f09e2b98000) 0
+
+Vtable for QTextIStream
+QTextIStream::_ZTV12QTextIStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI12QTextIStream)
+16 QTextIStream::~QTextIStream
+24 QTextIStream::~QTextIStream
+
+Class QTextIStream
+ size=16 align=8
+ base size=16 base align=8
+QTextIStream (0x7f09e2bb62a0) 0
+ vptr=((& QTextIStream::_ZTV12QTextIStream) + 16u)
+ QTextStream (0x7f09e2bb6310) 0
+ primary-for QTextIStream (0x7f09e2bb62a0)
+
+Vtable for QTextOStream
+QTextOStream::_ZTV12QTextOStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI12QTextOStream)
+16 QTextOStream::~QTextOStream
+24 QTextOStream::~QTextOStream
+
+Class QTextOStream
+ size=16 align=8
+ base size=16 base align=8
+QTextOStream (0x7f09e2bcd150) 0
+ vptr=((& QTextOStream::_ZTV12QTextOStream) + 16u)
+ QTextStream (0x7f09e2bcd1c0) 0
+ primary-for QTextOStream (0x7f09e2bcd150)
+
+Class wait
+ size=4 align=4
+ base size=4 base align=4
+wait (0x7f09e2be0000) 0
+
+Class timespec
+ size=16 align=8
+ base size=16 base align=8
+timespec (0x7f09e2be0310) 0
+
+Class timeval
+ size=16 align=8
+ base size=16 base align=8
+timeval (0x7f09e2be0380) 0
+
+Class __pthread_internal_list
+ size=16 align=8
+ base size=16 base align=8
+__pthread_internal_list (0x7f09e2be04d0) 0
+
+Class random_data
+ size=48 align=8
+ base size=48 base align=8
+random_data (0x7f09e2be0a80) 0
+
+Class drand48_data
+ size=24 align=8
+ base size=24 base align=8
+drand48_data (0x7f09e2be0af0) 0
+
+Class QVectorData
+ size=16 align=4
+ base size=16 base align=4
+QVectorData (0x7f09e2be0b60) 0
+
+Class QDebug::Stream
+ size=40 align=8
+ base size=34 base align=8
+QDebug::Stream (0x7f09e2961310) 0
+
+Class QDebug
+ size=8 align=8
+ base size=8 base align=8
+QDebug (0x7f09e29612a0) 0
+
+Class QNoDebug
+ size=1 align=1
+ base size=0 base align=1
+QNoDebug (0x7f09e27fe150) 0 empty
+
+Class QMetaType
+ size=1 align=1
+ base size=0 base align=1
+QMetaType (0x7f09e2810700) 0 empty
+
+Class QVariant::PrivateShared
+ size=16 align=8
+ base size=12 base align=8
+QVariant::PrivateShared (0x7f09e26fac40) 0
+
+Class QVariant::Private::Data
+ size=8 align=8
+ base size=8 base align=8
+QVariant::Private::Data (0x7f09e26faf50) 0
+
+Class QVariant::Private
+ size=16 align=8
+ base size=12 base align=8
+QVariant::Private (0x7f09e26fad20) 0
+
+Class QVariant::Handler
+ size=72 align=8
+ base size=72 base align=8
+QVariant::Handler (0x7f09e270ec40) 0
+
+Class QVariant
+ size=16 align=8
+ base size=16 base align=8
+QVariant (0x7f09e28d0e00) 0
+
+Class QVariantComparisonHelper
+ size=8 align=8
+ base size=8 base align=8
+QVariantComparisonHelper (0x7f09e27cb000) 0
+
+Class Phonon::ObjectDescriptionData
+ size=16 align=8
+ base size=16 base align=8
+Phonon::ObjectDescriptionData (0x7f09e25e1000) 0
+ QSharedData (0x7f09e25e1070) 0
+
+Class Phonon::Path
+ size=8 align=8
+ base size=8 base align=8
+Phonon::Path (0x7f09e262ed20) 0
+
+Vtable for Phonon::MediaNode
+Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon9MediaNodeE)
+16 Phonon::MediaNode::~MediaNode
+24 Phonon::MediaNode::~MediaNode
+
+Class Phonon::MediaNode
+ size=16 align=8
+ base size=16 base align=8
+Phonon::MediaNode (0x7f09e2650540) 0
+ vptr=((& Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE) + 16u)
+
+Vtable for Phonon::AbstractVideoOutput
+Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19AbstractVideoOutputE)
+16 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+24 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+
+Class Phonon::AbstractVideoOutput
+ size=16 align=8
+ base size=16 base align=8
+Phonon::AbstractVideoOutput (0x7f09e2650cb0) 0
+ vptr=((& Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE) + 16u)
+ Phonon::MediaNode (0x7f09e2650d20) 0
+ primary-for Phonon::AbstractVideoOutput (0x7f09e2650cb0)
+
+Class Phonon::MediaSource
+ size=8 align=8
+ base size=8 base align=8
+Phonon::MediaSource (0x7f09e266bbd0) 0
+
+Vtable for Phonon::EffectInterface
+Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon15EffectInterfaceE)
+16 Phonon::EffectInterface::~EffectInterface
+24 Phonon::EffectInterface::~EffectInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+
+Class Phonon::EffectInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::EffectInterface (0x7f09e268c770) 0 nearly-empty
+ vptr=((& Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE) + 16u)
+
+Vtable for Phonon::AddonInterface
+Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE: 6u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon14AddonInterfaceE)
+16 Phonon::AddonInterface::~AddonInterface
+24 Phonon::AddonInterface::~AddonInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+
+Class Phonon::AddonInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::AddonInterface (0x7f09e26a67e0) 0 nearly-empty
+ vptr=((& Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE) + 16u)
+
+Class QSize
+ size=8 align=4
+ base size=8 base align=4
+QSize (0x7f09e26bea80) 0
+
+Class QSizeF
+ size=16 align=8
+ base size=16 base align=8
+QSizeF (0x7f09e250c8c0) 0
+
+Class QPoint
+ size=8 align=4
+ base size=8 base align=4
+QPoint (0x7f09e255cee0) 0
+
+Class QPointF
+ size=16 align=8
+ base size=16 base align=8
+QPointF (0x7f09e2591b60) 0
+
+Class QRect
+ size=16 align=4
+ base size=16 base align=4
+QRect (0x7f09e25d09a0) 0
+
+Class QRectF
+ size=32 align=8
+ base size=32 base align=8
+QRectF (0x7f09e2463380) 0
+
+Vtable for QPaintDevice
+QPaintDevice::_ZTV12QPaintDevice: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI12QPaintDevice)
+16 QPaintDevice::~QPaintDevice
+24 QPaintDevice::~QPaintDevice
+32 QPaintDevice::devType
+40 __cxa_pure_virtual
+48 QPaintDevice::metric
+
+Class QPaintDevice
+ size=16 align=8
+ base size=10 base align=8
+QPaintDevice (0x7f09e230e150) 0
+ vptr=((& QPaintDevice::_ZTV12QPaintDevice) + 16u)
+
+Class QRegExp
+ size=8 align=8
+ base size=8 base align=8
+QRegExp (0x7f09e233d4d0) 0
+
+Class QStringMatcher
+ size=1048 align=8
+ base size=1048 base align=8
+QStringMatcher (0x7f09e236b310) 0
+
+Class QStringList
+ size=8 align=8
+ base size=8 base align=8
+QStringList (0x7f09e236bd90) 0
+ QList<QString> (0x7f09e236be00) 0
+
+Class QColor
+ size=16 align=4
+ base size=14 base align=4
+QColor (0x7f09e220ea10) 0
+
+Class QPolygon
+ size=8 align=8
+ base size=8 base align=8
+QPolygon (0x7f09e225de00) 0
+ QVector<QPoint> (0x7f09e225de70) 0
+
+Class QPolygonF
+ size=8 align=8
+ base size=8 base align=8
+QPolygonF (0x7f09e22a3f50) 0
+ QVector<QPointF> (0x7f09e22a3ee0) 0
+
+Class QRegion::QRegionData
+ size=32 align=8
+ base size=32 base align=8
+QRegion::QRegionData (0x7f09e2104460) 0
+
+Class QRegion
+ size=8 align=8
+ base size=8 base align=8
+QRegion (0x7f09e20e3bd0) 0
+
+Class QLine
+ size=16 align=4
+ base size=16 base align=4
+QLine (0x7f09e2119d20) 0
+
+Class QLineF
+ size=32 align=8
+ base size=32 base align=8
+QLineF (0x7f09e2154bd0) 0
+
+Class QMatrix
+ size=48 align=8
+ base size=48 base align=8
+QMatrix (0x7f09e21b1690) 0
+
+Class QPainterPath::Element
+ size=24 align=8
+ base size=24 base align=8
+QPainterPath::Element (0x7f09e1fe40e0) 0
+
+Class QPainterPath
+ size=8 align=8
+ base size=8 base align=8
+QPainterPath (0x7f09e1fe4070) 0
+
+Class QPainterPathPrivate
+ size=16 align=8
+ base size=16 base align=8
+QPainterPathPrivate (0x7f09e2027460) 0
+
+Class QPainterPathStroker
+ size=8 align=8
+ base size=8 base align=8
+QPainterPathStroker (0x7f09e2027c40) 0
+
+Class QTransform
+ size=88 align=8
+ base size=88 base align=8
+QTransform (0x7f09e2088b60) 0
+
+Class QImageTextKeyLang
+ size=16 align=8
+ base size=16 base align=8
+QImageTextKeyLang (0x7f09e1f04e70) 0
+
+Vtable for QImage
+QImage::_ZTV6QImage: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QImage)
+16 QImage::~QImage
+24 QImage::~QImage
+32 QImage::devType
+40 QImage::paintEngine
+48 QImage::metric
+
+Class QImage
+ size=24 align=8
+ base size=24 base align=8
+QImage (0x7f09e1f38700) 0
+ vptr=((& QImage::_ZTV6QImage) + 16u)
+ QPaintDevice (0x7f09e1f38770) 0
+ primary-for QImage (0x7f09e1f38700)
+
+Vtable for QPixmap
+QPixmap::_ZTV7QPixmap: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QPixmap)
+16 QPixmap::~QPixmap
+24 QPixmap::~QPixmap
+32 QPixmap::devType
+40 QPixmap::paintEngine
+48 QPixmap::metric
+
+Class QPixmap
+ size=24 align=8
+ base size=24 base align=8
+QPixmap (0x7f09e1dd8150) 0
+ vptr=((& QPixmap::_ZTV7QPixmap) + 16u)
+ QPaintDevice (0x7f09e1dd81c0) 0
+ primary-for QPixmap (0x7f09e1dd8150)
+
+Class QBrush
+ size=8 align=8
+ base size=8 base align=8
+QBrush (0x7f09e1e26310) 0
+
+Class QBrushData
+ size=112 align=8
+ base size=112 base align=8
+QBrushData (0x7f09e1e3dee0) 0
+
+Class QGradient
+ size=64 align=8
+ base size=64 base align=8
+QGradient (0x7f09e1e580e0) 0
+
+Class QLinearGradient
+ size=64 align=8
+ base size=64 base align=8
+QLinearGradient (0x7f09e1e88b60) 0
+ QGradient (0x7f09e1e88bd0) 0
+
+Class QRadialGradient
+ size=64 align=8
+ base size=64 base align=8
+QRadialGradient (0x7f09e1e95070) 0
+ QGradient (0x7f09e1e950e0) 0
+
+Class QConicalGradient
+ size=64 align=8
+ base size=64 base align=8
+QConicalGradient (0x7f09e1e95620) 0
+ QGradient (0x7f09e1e95690) 0
+
+Class QPalette
+ size=16 align=8
+ base size=12 base align=8
+QPalette (0x7f09e1e959a0) 0
+
+Class QColorGroup
+ size=16 align=8
+ base size=12 base align=8
+QColorGroup (0x7f09e1cb1310) 0
+ QPalette (0x7f09e1cb1380) 0
+
+Class QFont
+ size=16 align=8
+ base size=12 base align=8
+QFont (0x7f09e1ce9620) 0
+
+Class QFontMetrics
+ size=8 align=8
+ base size=8 base align=8
+QFontMetrics (0x7f09e1d242a0) 0
+
+Class QFontMetricsF
+ size=8 align=8
+ base size=8 base align=8
+QFontMetricsF (0x7f09e1d38700) 0
+
+Class QFontInfo
+ size=8 align=8
+ base size=8 base align=8
+QFontInfo (0x7f09e1d4f620) 0
+
+Class QSizePolicy
+ size=4 align=4
+ base size=4 base align=4
+QSizePolicy (0x7f09e1d5a150) 0
+
+Class QCursor
+ size=8 align=8
+ base size=8 base align=8
+QCursor (0x7f09e1c03e70) 0
+
+Class QKeySequence
+ size=8 align=8
+ base size=8 base align=8
+QKeySequence (0x7f09e1c06690) 0
+
+Class QWidgetData
+ size=88 align=8
+ base size=88 base align=8
+QWidgetData (0x7f09e1c4f2a0) 0
+
+Vtable for QWidget
+QWidget::_ZTV7QWidget: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QWidget)
+16 QWidget::metaObject
+24 QWidget::qt_metacast
+32 QWidget::qt_metacall
+40 QWidget::~QWidget
+48 QWidget::~QWidget
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTI7QWidget)
+464 QWidget::_ZThn16_N7QWidgetD1Ev
+472 QWidget::_ZThn16_N7QWidgetD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class QWidget
+ size=40 align=8
+ base size=40 base align=8
+QWidget (0x7f09e1c4a780) 0
+ vptr=((& QWidget::_ZTV7QWidget) + 16u)
+ QObject (0x7f09e1c4f310) 0
+ primary-for QWidget (0x7f09e1c4a780)
+ QPaintDevice (0x7f09e1c4f380) 16
+ vptr=((& QWidget::_ZTV7QWidget) + 464u)
+
+Vtable for Phonon::VideoPlayer
+Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+16 Phonon::VideoPlayer::metaObject
+24 Phonon::VideoPlayer::qt_metacast
+32 Phonon::VideoPlayer::qt_metacall
+40 Phonon::VideoPlayer::~VideoPlayer
+48 Phonon::VideoPlayer::~VideoPlayer
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+464 Phonon::VideoPlayer::_ZThn16_N6Phonon11VideoPlayerD1Ev
+472 Phonon::VideoPlayer::_ZThn16_N6Phonon11VideoPlayerD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VideoPlayer
+ size=48 align=8
+ base size=48 base align=8
+Phonon::VideoPlayer (0x7f09e19a80e0) 0
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 16u)
+ QWidget (0x7f09e19a9180) 0
+ primary-for Phonon::VideoPlayer (0x7f09e19a80e0)
+ QObject (0x7f09e19a8150) 0
+ primary-for QWidget (0x7f09e19a9180)
+ QPaintDevice (0x7f09e19a81c0) 16
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 464u)
+
+Vtable for Phonon::Effect
+Phonon::Effect::_ZTVN6Phonon6EffectE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+16 Phonon::Effect::metaObject
+24 Phonon::Effect::qt_metacast
+32 Phonon::Effect::qt_metacall
+40 Phonon::Effect::~Effect
+48 Phonon::Effect::~Effect
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+128 Phonon::Effect::_ZThn16_N6Phonon6EffectD1Ev
+136 Phonon::Effect::_ZThn16_N6Phonon6EffectD0Ev
+
+Class Phonon::Effect
+ size=32 align=8
+ base size=32 base align=8
+Phonon::Effect (0x7f09e19a9880) 0
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 16u)
+ QObject (0x7f09e19c4150) 0
+ primary-for Phonon::Effect (0x7f09e19a9880)
+ Phonon::MediaNode (0x7f09e19c41c0) 16
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 128u)
+
+Vtable for Phonon::VolumeFaderEffect
+Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+16 Phonon::VolumeFaderEffect::metaObject
+24 Phonon::VolumeFaderEffect::qt_metacast
+32 Phonon::VolumeFaderEffect::qt_metacall
+40 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+48 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+128 Phonon::VolumeFaderEffect::_ZThn16_N6Phonon17VolumeFaderEffectD1Ev
+136 Phonon::VolumeFaderEffect::_ZThn16_N6Phonon17VolumeFaderEffectD0Ev
+
+Class Phonon::VolumeFaderEffect
+ size=32 align=8
+ base size=32 base align=8
+Phonon::VolumeFaderEffect (0x7f09e19d6620) 0
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 16u)
+ Phonon::Effect (0x7f09e19d7180) 0
+ primary-for Phonon::VolumeFaderEffect (0x7f09e19d6620)
+ QObject (0x7f09e19d6690) 0
+ primary-for Phonon::Effect (0x7f09e19d7180)
+ Phonon::MediaNode (0x7f09e19d6700) 16
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 128u)
+
+Class QModelIndex
+ size=24 align=8
+ base size=24 base align=8
+QModelIndex (0x7f09e19e8c40) 0
+
+Class QPersistentModelIndex
+ size=8 align=8
+ base size=8 base align=8
+QPersistentModelIndex (0x7f09e1a12700) 0
+
+Vtable for QAbstractItemModel
+QAbstractItemModel::_ZTV18QAbstractItemModel: 42u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractItemModel)
+16 QAbstractItemModel::metaObject
+24 QAbstractItemModel::qt_metacast
+32 QAbstractItemModel::qt_metacall
+40 QAbstractItemModel::~QAbstractItemModel
+48 QAbstractItemModel::~QAbstractItemModel
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 __cxa_pure_virtual
+136 __cxa_pure_virtual
+144 QAbstractItemModel::hasChildren
+152 __cxa_pure_virtual
+160 QAbstractItemModel::setData
+168 QAbstractItemModel::headerData
+176 QAbstractItemModel::setHeaderData
+184 QAbstractItemModel::itemData
+192 QAbstractItemModel::setItemData
+200 QAbstractItemModel::mimeTypes
+208 QAbstractItemModel::mimeData
+216 QAbstractItemModel::dropMimeData
+224 QAbstractItemModel::supportedDropActions
+232 QAbstractItemModel::insertRows
+240 QAbstractItemModel::insertColumns
+248 QAbstractItemModel::removeRows
+256 QAbstractItemModel::removeColumns
+264 QAbstractItemModel::fetchMore
+272 QAbstractItemModel::canFetchMore
+280 QAbstractItemModel::flags
+288 QAbstractItemModel::sort
+296 QAbstractItemModel::buddy
+304 QAbstractItemModel::match
+312 QAbstractItemModel::span
+320 QAbstractItemModel::submit
+328 QAbstractItemModel::revert
+
+Class QAbstractItemModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractItemModel (0x7f09e1a1da10) 0
+ vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u)
+ QObject (0x7f09e1a1da80) 0
+ primary-for QAbstractItemModel (0x7f09e1a1da10)
+
+Vtable for QAbstractTableModel
+QAbstractTableModel::_ZTV19QAbstractTableModel: 42u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractTableModel)
+16 QAbstractTableModel::metaObject
+24 QAbstractTableModel::qt_metacast
+32 QAbstractTableModel::qt_metacall
+40 QAbstractTableModel::~QAbstractTableModel
+48 QAbstractTableModel::~QAbstractTableModel
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QAbstractTableModel::index
+120 QAbstractTableModel::parent
+128 __cxa_pure_virtual
+136 __cxa_pure_virtual
+144 QAbstractTableModel::hasChildren
+152 __cxa_pure_virtual
+160 QAbstractItemModel::setData
+168 QAbstractItemModel::headerData
+176 QAbstractItemModel::setHeaderData
+184 QAbstractItemModel::itemData
+192 QAbstractItemModel::setItemData
+200 QAbstractItemModel::mimeTypes
+208 QAbstractItemModel::mimeData
+216 QAbstractTableModel::dropMimeData
+224 QAbstractItemModel::supportedDropActions
+232 QAbstractItemModel::insertRows
+240 QAbstractItemModel::insertColumns
+248 QAbstractItemModel::removeRows
+256 QAbstractItemModel::removeColumns
+264 QAbstractItemModel::fetchMore
+272 QAbstractItemModel::canFetchMore
+280 QAbstractItemModel::flags
+288 QAbstractItemModel::sort
+296 QAbstractItemModel::buddy
+304 QAbstractItemModel::match
+312 QAbstractItemModel::span
+320 QAbstractItemModel::submit
+328 QAbstractItemModel::revert
+
+Class QAbstractTableModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractTableModel (0x7f09e1871d20) 0
+ vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u)
+ QAbstractItemModel (0x7f09e1871d90) 0
+ primary-for QAbstractTableModel (0x7f09e1871d20)
+ QObject (0x7f09e1871e00) 0
+ primary-for QAbstractItemModel (0x7f09e1871d90)
+
+Vtable for QAbstractListModel
+QAbstractListModel::_ZTV18QAbstractListModel: 42u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractListModel)
+16 QAbstractListModel::metaObject
+24 QAbstractListModel::qt_metacast
+32 QAbstractListModel::qt_metacall
+40 QAbstractListModel::~QAbstractListModel
+48 QAbstractListModel::~QAbstractListModel
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QAbstractListModel::index
+120 QAbstractListModel::parent
+128 __cxa_pure_virtual
+136 QAbstractListModel::columnCount
+144 QAbstractListModel::hasChildren
+152 __cxa_pure_virtual
+160 QAbstractItemModel::setData
+168 QAbstractItemModel::headerData
+176 QAbstractItemModel::setHeaderData
+184 QAbstractItemModel::itemData
+192 QAbstractItemModel::setItemData
+200 QAbstractItemModel::mimeTypes
+208 QAbstractItemModel::mimeData
+216 QAbstractListModel::dropMimeData
+224 QAbstractItemModel::supportedDropActions
+232 QAbstractItemModel::insertRows
+240 QAbstractItemModel::insertColumns
+248 QAbstractItemModel::removeRows
+256 QAbstractItemModel::removeColumns
+264 QAbstractItemModel::fetchMore
+272 QAbstractItemModel::canFetchMore
+280 QAbstractItemModel::flags
+288 QAbstractItemModel::sort
+296 QAbstractItemModel::buddy
+304 QAbstractItemModel::match
+312 QAbstractItemModel::span
+320 QAbstractItemModel::submit
+328 QAbstractItemModel::revert
+
+Class QAbstractListModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractListModel (0x7f09e188c2a0) 0
+ vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u)
+ QAbstractItemModel (0x7f09e188c310) 0
+ primary-for QAbstractListModel (0x7f09e188c2a0)
+ QObject (0x7f09e188c380) 0
+ primary-for QAbstractItemModel (0x7f09e188c310)
+
+Class Phonon::ObjectDescriptionModelData
+ size=8 align=8
+ base size=8 base align=8
+Phonon::ObjectDescriptionModelData (0x7f09e18bd3f0) 0
+
+Vtable for Phonon::StreamInterface
+Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE: 8u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon15StreamInterfaceE)
+16 Phonon::StreamInterface::~StreamInterface
+24 Phonon::StreamInterface::~StreamInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+
+Class Phonon::StreamInterface
+ size=16 align=8
+ base size=16 base align=8
+Phonon::StreamInterface (0x7f09e1906540) 0
+ vptr=((& Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE) + 16u)
+
+Vtable for Phonon::SeekSlider
+Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+16 Phonon::SeekSlider::metaObject
+24 Phonon::SeekSlider::qt_metacast
+32 Phonon::SeekSlider::qt_metacall
+40 Phonon::SeekSlider::~SeekSlider
+48 Phonon::SeekSlider::~SeekSlider
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+464 Phonon::SeekSlider::_ZThn16_N6Phonon10SeekSliderD1Ev
+472 Phonon::SeekSlider::_ZThn16_N6Phonon10SeekSliderD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::SeekSlider
+ size=48 align=8
+ base size=48 base align=8
+Phonon::SeekSlider (0x7f09e1906e00) 0
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 16u)
+ QWidget (0x7f09e194e080) 0
+ primary-for Phonon::SeekSlider (0x7f09e1906e00)
+ QObject (0x7f09e1906e70) 0
+ primary-for QWidget (0x7f09e194e080)
+ QPaintDevice (0x7f09e1906ee0) 16
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 464u)
+
+Vtable for Phonon::PlatformPlugin
+Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE: 16u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon14PlatformPluginE)
+16 Phonon::PlatformPlugin::~PlatformPlugin
+24 Phonon::PlatformPlugin::~PlatformPlugin
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+96 __cxa_pure_virtual
+104 __cxa_pure_virtual
+112 __cxa_pure_virtual
+120 Phonon::PlatformPlugin::deviceAccessListFor
+
+Class Phonon::PlatformPlugin
+ size=8 align=8
+ base size=8 base align=8
+Phonon::PlatformPlugin (0x7f09e17692a0) 0 nearly-empty
+ vptr=((& Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE) + 16u)
+
+Vtable for Phonon::MediaController
+Phonon::MediaController::_ZTVN6Phonon15MediaControllerE: 14u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon15MediaControllerE)
+16 Phonon::MediaController::metaObject
+24 Phonon::MediaController::qt_metacast
+32 Phonon::MediaController::qt_metacall
+40 Phonon::MediaController::~MediaController
+48 Phonon::MediaController::~MediaController
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+
+Class Phonon::MediaController
+ size=24 align=8
+ base size=24 base align=8
+Phonon::MediaController (0x7f09e179c700) 0
+ vptr=((& Phonon::MediaController::_ZTVN6Phonon15MediaControllerE) + 16u)
+ QObject (0x7f09e179c770) 0
+ primary-for Phonon::MediaController (0x7f09e179c700)
+
+Vtable for Phonon::VolumeSlider
+Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+16 Phonon::VolumeSlider::metaObject
+24 Phonon::VolumeSlider::qt_metacast
+32 Phonon::VolumeSlider::qt_metacall
+40 Phonon::VolumeSlider::~VolumeSlider
+48 Phonon::VolumeSlider::~VolumeSlider
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+464 Phonon::VolumeSlider::_ZThn16_N6Phonon12VolumeSliderD1Ev
+472 Phonon::VolumeSlider::_ZThn16_N6Phonon12VolumeSliderD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VolumeSlider
+ size=48 align=8
+ base size=48 base align=8
+Phonon::VolumeSlider (0x7f09e17d2620) 0
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 16u)
+ QWidget (0x7f09e17e0080) 0
+ primary-for Phonon::VolumeSlider (0x7f09e17d2620)
+ QObject (0x7f09e17d2690) 0
+ primary-for QWidget (0x7f09e17e0080)
+ QPaintDevice (0x7f09e17d2700) 16
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 464u)
+
+Vtable for Phonon::MediaObject
+Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+16 Phonon::MediaObject::metaObject
+24 Phonon::MediaObject::qt_metacast
+32 Phonon::MediaObject::qt_metacall
+40 Phonon::MediaObject::~MediaObject
+48 Phonon::MediaObject::~MediaObject
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+128 Phonon::MediaObject::_ZThn16_N6Phonon11MediaObjectD1Ev
+136 Phonon::MediaObject::_ZThn16_N6Phonon11MediaObjectD0Ev
+
+Class Phonon::MediaObject
+ size=32 align=8
+ base size=32 base align=8
+Phonon::MediaObject (0x7f09e17e0980) 0
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 16u)
+ QObject (0x7f09e17f5af0) 0
+ primary-for Phonon::MediaObject (0x7f09e17e0980)
+ Phonon::MediaNode (0x7f09e17f5b60) 16
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 128u)
+
+Vtable for Phonon::EffectWidget
+Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+16 Phonon::EffectWidget::metaObject
+24 Phonon::EffectWidget::qt_metacast
+32 Phonon::EffectWidget::qt_metacall
+40 Phonon::EffectWidget::~EffectWidget
+48 Phonon::EffectWidget::~EffectWidget
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+464 Phonon::EffectWidget::_ZThn16_N6Phonon12EffectWidgetD1Ev
+472 Phonon::EffectWidget::_ZThn16_N6Phonon12EffectWidgetD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::EffectWidget
+ size=48 align=8
+ base size=48 base align=8
+Phonon::EffectWidget (0x7f09e181d0e0) 0
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 16u)
+ QWidget (0x7f09e1819280) 0
+ primary-for Phonon::EffectWidget (0x7f09e181d0e0)
+ QObject (0x7f09e181d150) 0
+ primary-for QWidget (0x7f09e1819280)
+ QPaintDevice (0x7f09e181d1c0) 16
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 464u)
+
+Class Phonon::EffectParameter
+ size=8 align=8
+ base size=8 base align=8
+Phonon::EffectParameter (0x7f09e1830460) 0
+
+Vtable for Phonon::VolumeFaderInterface
+Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE: 9u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon20VolumeFaderInterfaceE)
+16 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+24 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+32 Phonon::VolumeFaderInterface::volume
+40 Phonon::VolumeFaderInterface::setVolume
+48 Phonon::VolumeFaderInterface::fadeCurve
+56 Phonon::VolumeFaderInterface::setFadeCurve
+64 Phonon::VolumeFaderInterface::fadeTo
+
+Class Phonon::VolumeFaderInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::VolumeFaderInterface (0x7f09e166d070) 0 nearly-empty
+ vptr=((& Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE) + 16u)
+
+Vtable for Phonon::AbstractAudioOutput
+Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+16 Phonon::AbstractAudioOutput::metaObject
+24 Phonon::AbstractAudioOutput::qt_metacast
+32 Phonon::AbstractAudioOutput::qt_metacall
+40 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+48 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+128 Phonon::AbstractAudioOutput::_ZThn16_N6Phonon19AbstractAudioOutputD1Ev
+136 Phonon::AbstractAudioOutput::_ZThn16_N6Phonon19AbstractAudioOutputD0Ev
+
+Class Phonon::AbstractAudioOutput
+ size=32 align=8
+ base size=32 base align=8
+Phonon::AbstractAudioOutput (0x7f09e1676f00) 0
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 16u)
+ QObject (0x7f09e1677930) 0
+ primary-for Phonon::AbstractAudioOutput (0x7f09e1676f00)
+ Phonon::MediaNode (0x7f09e16779a0) 16
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 128u)
+
+Vtable for Phonon::AudioOutput
+Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+16 Phonon::AudioOutput::metaObject
+24 Phonon::AudioOutput::qt_metacast
+32 Phonon::AudioOutput::qt_metacall
+40 Phonon::AudioOutput::~AudioOutput
+48 Phonon::AudioOutput::~AudioOutput
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+128 Phonon::AudioOutput::_ZThn16_N6Phonon11AudioOutputD1Ev
+136 Phonon::AudioOutput::_ZThn16_N6Phonon11AudioOutputD0Ev
+
+Class Phonon::AudioOutput
+ size=32 align=8
+ base size=32 base align=8
+Phonon::AudioOutput (0x7f09e168bd20) 0
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 16u)
+ Phonon::AbstractAudioOutput (0x7f09e1680800) 0
+ primary-for Phonon::AudioOutput (0x7f09e168bd20)
+ QObject (0x7f09e168bd90) 0
+ primary-for Phonon::AbstractAudioOutput (0x7f09e1680800)
+ Phonon::MediaNode (0x7f09e168be00) 16
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 128u)
+
+Vtable for Phonon::AudioOutputInterface40
+Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E: 8u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface40E)
+16 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+24 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface40
+ size=8 align=8
+ base size=8 base align=8
+Phonon::AudioOutputInterface40 (0x7f09e16ac2a0) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E) + 16u)
+
+Vtable for Phonon::AudioOutputInterface42
+Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E: 9u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface42E)
+16 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+24 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface42
+ size=8 align=8
+ base size=8 base align=8
+Phonon::AudioOutputInterface42 (0x7f09e16accb0) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E) + 16u)
+ Phonon::AudioOutputInterface40 (0x7f09e16acd20) 0 nearly-empty
+ primary-for Phonon::AudioOutputInterface42 (0x7f09e16accb0)
+
+Vtable for Phonon::BackendCapabilities::Notifier
+Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE: 14u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19BackendCapabilities8NotifierE)
+16 Phonon::BackendCapabilities::Notifier::metaObject
+24 Phonon::BackendCapabilities::Notifier::qt_metacast
+32 Phonon::BackendCapabilities::Notifier::qt_metacall
+40 Phonon::BackendCapabilities::Notifier::~Notifier
+48 Phonon::BackendCapabilities::Notifier::~Notifier
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+
+Class Phonon::BackendCapabilities::Notifier
+ size=16 align=8
+ base size=16 base align=8
+Phonon::BackendCapabilities::Notifier (0x7f09e16bac40) 0
+ vptr=((& Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE) + 16u)
+ QObject (0x7f09e16bacb0) 0
+ primary-for Phonon::BackendCapabilities::Notifier (0x7f09e16bac40)
+
+Vtable for Phonon::BackendInterface
+Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE: 12u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon16BackendInterfaceE)
+16 Phonon::BackendInterface::~BackendInterface
+24 Phonon::BackendInterface::~BackendInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+
+Class Phonon::BackendInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::BackendInterface (0x7f09e16ce9a0) 0 nearly-empty
+ vptr=((& Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE) + 16u)
+
+Vtable for Phonon::AbstractMediaStream
+Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19AbstractMediaStreamE)
+16 Phonon::AbstractMediaStream::metaObject
+24 Phonon::AbstractMediaStream::qt_metacast
+32 Phonon::AbstractMediaStream::qt_metacall
+40 Phonon::AbstractMediaStream::~AbstractMediaStream
+48 Phonon::AbstractMediaStream::~AbstractMediaStream
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 Phonon::AbstractMediaStream::enoughData
+136 Phonon::AbstractMediaStream::seekStream
+
+Class Phonon::AbstractMediaStream
+ size=24 align=8
+ base size=24 base align=8
+Phonon::AbstractMediaStream (0x7f09e16dfc40) 0
+ vptr=((& Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE) + 16u)
+ QObject (0x7f09e16dfcb0) 0
+ primary-for Phonon::AbstractMediaStream (0x7f09e16dfc40)
+
+Vtable for Phonon::VideoWidget
+Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE: 67u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+16 Phonon::VideoWidget::metaObject
+24 Phonon::VideoWidget::qt_metacast
+32 Phonon::VideoWidget::qt_metacall
+40 Phonon::VideoWidget::~VideoWidget
+48 Phonon::VideoWidget::~VideoWidget
+56 Phonon::VideoWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 Phonon::VideoWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+464 Phonon::VideoWidget::_ZThn16_N6Phonon11VideoWidgetD1Ev
+472 Phonon::VideoWidget::_ZThn16_N6Phonon11VideoWidgetD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+504 (int (*)(...))-0x00000000000000028
+512 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+520 Phonon::VideoWidget::_ZThn40_N6Phonon11VideoWidgetD1Ev
+528 Phonon::VideoWidget::_ZThn40_N6Phonon11VideoWidgetD0Ev
+
+Class Phonon::VideoWidget
+ size=56 align=8
+ base size=56 base align=8
+Phonon::VideoWidget (0x7f09e16e8900) 0
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 16u)
+ QWidget (0x7f09e16e8980) 0
+ primary-for Phonon::VideoWidget (0x7f09e16e8900)
+ QObject (0x7f09e16fd0e0) 0
+ primary-for QWidget (0x7f09e16e8980)
+ QPaintDevice (0x7f09e16fd150) 16
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 464u)
+ Phonon::AbstractVideoOutput (0x7f09e16fd1c0) 40
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 520u)
+ Phonon::MediaNode (0x7f09e16fd230) 40
+ primary-for Phonon::AbstractVideoOutput (0x7f09e16fd1c0)
+
+Vtable for Phonon::VideoWidgetInterface
+Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE: 17u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon20VideoWidgetInterfaceE)
+16 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+24 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+96 __cxa_pure_virtual
+104 __cxa_pure_virtual
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 __cxa_pure_virtual
+
+Class Phonon::VideoWidgetInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::VideoWidgetInterface (0x7f09e1717a80) 0 nearly-empty
+ vptr=((& Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE) + 16u)
+
+Vtable for Phonon::MediaObjectInterface
+Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE: 25u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon20MediaObjectInterfaceE)
+16 Phonon::MediaObjectInterface::~MediaObjectInterface
+24 Phonon::MediaObjectInterface::~MediaObjectInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+96 __cxa_pure_virtual
+104 __cxa_pure_virtual
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 __cxa_pure_virtual
+136 __cxa_pure_virtual
+144 __cxa_pure_virtual
+152 __cxa_pure_virtual
+160 Phonon::MediaObjectInterface::remainingTime
+168 __cxa_pure_virtual
+176 __cxa_pure_virtual
+184 __cxa_pure_virtual
+192 __cxa_pure_virtual
+
+Class Phonon::MediaObjectInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::MediaObjectInterface (0x7f09e1727ee0) 0 nearly-empty
+ vptr=((& Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE) + 16u)
+
diff --git a/tests/auto/bic/data/phonon.4.5.0.linux-gcc-ia32.txt b/tests/auto/bic/data/phonon.4.5.0.linux-gcc-ia32.txt
new file mode 100644
index 0000000..31aff5e
--- /dev/null
+++ b/tests/auto/bic/data/phonon.4.5.0.linux-gcc-ia32.txt
@@ -0,0 +1,1930 @@
+Class QSysInfo
+ size=1 align=1
+ base size=0 base align=1
+QSysInfo (0xb6f02e88) 0 empty
+
+Class QBool
+ size=1 align=1
+ base size=1 base align=1
+QBool (0xb6e5503c) 0
+
+Class qIsNull(double)::U
+ size=8 align=4
+ base size=8 base align=4
+qIsNull(double)::U (0xb6e55708) 0
+
+Class qIsNull(float)::U
+ size=4 align=4
+ base size=4 base align=4
+qIsNull(float)::U (0xb6e557bc) 0
+
+Class QFlag
+ size=4 align=4
+ base size=4 base align=4
+QFlag (0xb6e83000) 0
+
+Class QIncompatibleFlag
+ size=4 align=4
+ base size=4 base align=4
+QIncompatibleFlag (0xb6e8312c) 0
+
+Class QBasicAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QBasicAtomicInt (0xb6e83384) 0
+
+Class QAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QAtomicInt (0xb6eb3f80) 0
+ QBasicAtomicInt (0xb6e83a8c) 0
+
+Class QSharedData
+ size=4 align=4
+ base size=4 base align=4
+QSharedData (0xb6e83f78) 0
+
+Class QLatin1Char
+ size=1 align=1
+ base size=1 base align=1
+QLatin1Char (0xb694830c) 0
+
+Class QChar
+ size=2 align=2
+ base size=2 base align=2
+QChar (0xb69484ec) 0
+
+Vtable for std::exception
+std::exception::_ZTVSt9exception: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt9exception)
+8 std::exception::~exception
+12 std::exception::~exception
+16 std::exception::what
+
+Class std::exception
+ size=4 align=4
+ base size=4 base align=4
+std::exception (0xb69bec30) 0 nearly-empty
+ vptr=((& std::exception::_ZTVSt9exception) + 8u)
+
+Vtable for std::bad_exception
+std::bad_exception::_ZTVSt13bad_exception: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt13bad_exception)
+8 std::bad_exception::~bad_exception
+12 std::bad_exception::~bad_exception
+16 std::bad_exception::what
+
+Class std::bad_exception
+ size=4 align=4
+ base size=4 base align=4
+std::bad_exception (0xb69c3740) 0 nearly-empty
+ vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 8u)
+ std::exception (0xb69bed20) 0 nearly-empty
+ primary-for std::bad_exception (0xb69c3740)
+
+Vtable for std::bad_alloc
+std::bad_alloc::_ZTVSt9bad_alloc: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt9bad_alloc)
+8 std::bad_alloc::~bad_alloc
+12 std::bad_alloc::~bad_alloc
+16 std::bad_alloc::what
+
+Class std::bad_alloc
+ size=4 align=4
+ base size=4 base align=4
+std::bad_alloc (0xb69c38c0) 0 nearly-empty
+ vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 8u)
+ std::exception (0xb69bef78) 0 nearly-empty
+ primary-for std::bad_alloc (0xb69c38c0)
+
+Class std::nothrow_t
+ size=1 align=1
+ base size=0 base align=1
+std::nothrow_t (0xb69d61e0) 0 empty
+
+Class QListData::Data
+ size=24 align=4
+ base size=24 base align=4
+QListData::Data (0xb69d62d0) 0
+
+Class QListData
+ size=4 align=4
+ base size=4 base align=4
+QListData (0xb69d6294) 0
+
+Class QInternal
+ size=1 align=1
+ base size=0 base align=1
+QInternal (0xb68ff690) 0 empty
+
+Class QGenericArgument
+ size=8 align=4
+ base size=8 base align=4
+QGenericArgument (0xb68ff6cc) 0
+
+Class QGenericReturnArgument
+ size=8 align=4
+ base size=8 base align=4
+QGenericReturnArgument (0xb6768140) 0
+ QGenericArgument (0xb68ff8e8) 0
+
+Class QMetaObject
+ size=16 align=4
+ base size=16 base align=4
+QMetaObject (0xb68ffa50) 0
+
+Class QMetaObjectExtraData
+ size=8 align=4
+ base size=8 base align=4
+QMetaObjectExtraData (0xb68ffb7c) 0
+
+Class __locale_struct
+ size=116 align=4
+ base size=116 base align=4
+__locale_struct (0xb68ffd5c) 0
+
+Class QByteArray::Data
+ size=20 align=4
+ base size=20 base align=4
+QByteArray::Data (0xb679d1e0) 0
+
+Class QByteArray
+ size=4 align=4
+ base size=4 base align=4
+QByteArray (0xb679d1a4) 0
+
+Class QByteRef
+ size=8 align=4
+ base size=8 base align=4
+QByteRef (0xb67f20b4) 0
+
+Class QString::Null
+ size=1 align=1
+ base size=0 base align=1
+QString::Null (0xb6826960) 0 empty
+
+Class QString::Data
+ size=20 align=4
+ base size=20 base align=4
+QString::Data (0xb682699c) 0
+
+Class QString
+ size=4 align=4
+ base size=4 base align=4
+QString (0xb6826924) 0
+
+Class QLatin1String
+ size=4 align=4
+ base size=4 base align=4
+QLatin1String (0xb66f24ec) 0
+
+Class QCharRef
+ size=8 align=4
+ base size=8 base align=4
+QCharRef (0xb654f1e0) 0
+
+Class QConstString
+ size=4 align=4
+ base size=4 base align=4
+QConstString (0xb65cf840) 0
+ QString (0xb65f1924) 0
+
+Class QStringRef
+ size=12 align=4
+ base size=12 base align=4
+QStringRef (0xb65f1d5c) 0
+
+Vtable for QObjectData
+QObjectData::_ZTV11QObjectData: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QObjectData)
+8 __cxa_pure_virtual
+12 __cxa_pure_virtual
+
+Class QObjectData
+ size=24 align=4
+ base size=24 base align=4
+QObjectData (0xb642dca8) 0
+ vptr=((& QObjectData::_ZTV11QObjectData) + 8u)
+
+Vtable for QObject
+QObject::_ZTV7QObject: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QObject)
+8 QObject::metaObject
+12 QObject::qt_metacast
+16 QObject::qt_metacall
+20 QObject::~QObject
+24 QObject::~QObject
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class QObject
+ size=8 align=4
+ base size=8 base align=4
+QObject (0xb642dd5c) 0
+ vptr=((& QObject::_ZTV7QObject) + 8u)
+
+Vtable for QObjectUserData
+QObjectUserData::_ZTV15QObjectUserData: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI15QObjectUserData)
+8 QObjectUserData::~QObjectUserData
+12 QObjectUserData::~QObjectUserData
+
+Class QObjectUserData
+ size=4 align=4
+ base size=4 base align=4
+QObjectUserData (0xb64915a0) 0 nearly-empty
+ vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 8u)
+
+Vtable for QIODevice
+QIODevice::_ZTV9QIODevice: 30u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI9QIODevice)
+8 QIODevice::metaObject
+12 QIODevice::qt_metacast
+16 QIODevice::qt_metacall
+20 QIODevice::~QIODevice
+24 QIODevice::~QIODevice
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QIODevice::isSequential
+60 QIODevice::open
+64 QIODevice::close
+68 QIODevice::pos
+72 QIODevice::size
+76 QIODevice::seek
+80 QIODevice::atEnd
+84 QIODevice::reset
+88 QIODevice::bytesAvailable
+92 QIODevice::bytesToWrite
+96 QIODevice::canReadLine
+100 QIODevice::waitForReadyRead
+104 QIODevice::waitForBytesWritten
+108 __cxa_pure_virtual
+112 QIODevice::readLineData
+116 __cxa_pure_virtual
+
+Class QIODevice
+ size=8 align=4
+ base size=8 base align=4
+QIODevice (0xb645bf80) 0
+ vptr=((& QIODevice::_ZTV9QIODevice) + 8u)
+ QObject (0xb64916cc) 0
+ primary-for QIODevice (0xb645bf80)
+
+Vtable for QDataStream
+QDataStream::_ZTV11QDataStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QDataStream)
+8 QDataStream::~QDataStream
+12 QDataStream::~QDataStream
+
+Class QDataStream
+ size=28 align=4
+ base size=28 base align=4
+QDataStream (0xb64cc438) 0
+ vptr=((& QDataStream::_ZTV11QDataStream) + 8u)
+
+Class QHashData::Node
+ size=8 align=4
+ base size=8 base align=4
+QHashData::Node (0xb64ccfb4) 0
+
+Class QHashData
+ size=32 align=4
+ base size=32 base align=4
+QHashData (0xb64ccf78) 0
+
+Class QHashDummyValue
+ size=1 align=1
+ base size=0 base align=1
+QHashDummyValue (0xb6526654) 0 empty
+
+Class QMapData::Node
+ size=8 align=4
+ base size=8 base align=4
+QMapData::Node (0xb6526d98) 0
+
+Class QMapData
+ size=72 align=4
+ base size=72 base align=4
+QMapData (0xb6526d5c) 0
+
+Vtable for QSystemLocale
+QSystemLocale::_ZTV13QSystemLocale: 6u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI13QSystemLocale)
+8 QSystemLocale::~QSystemLocale
+12 QSystemLocale::~QSystemLocale
+16 QSystemLocale::query
+20 QSystemLocale::fallbackLocale
+
+Class QSystemLocale
+ size=4 align=4
+ base size=4 base align=4
+QSystemLocale (0xb62370b4) 0 nearly-empty
+ vptr=((& QSystemLocale::_ZTV13QSystemLocale) + 8u)
+
+Class QLocale::Data
+ size=4 align=2
+ base size=4 base align=2
+QLocale::Data (0xb623712c) 0
+
+Class QLocale
+ size=4 align=4
+ base size=4 base align=4
+QLocale (0xb62370f0) 0
+
+Class QTextCodec::ConverterState
+ size=28 align=4
+ base size=28 base align=4
+QTextCodec::ConverterState (0xb6237780) 0
+
+Vtable for QTextCodec
+QTextCodec::_ZTV10QTextCodec: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI10QTextCodec)
+8 __cxa_pure_virtual
+12 QTextCodec::aliases
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 QTextCodec::~QTextCodec
+32 QTextCodec::~QTextCodec
+
+Class QTextCodec
+ size=4 align=4
+ base size=4 base align=4
+QTextCodec (0xb6237744) 0 nearly-empty
+ vptr=((& QTextCodec::_ZTV10QTextCodec) + 8u)
+
+Class QTextEncoder
+ size=32 align=4
+ base size=32 base align=4
+QTextEncoder (0xb62c0384) 0
+
+Class QTextDecoder
+ size=32 align=4
+ base size=32 base align=4
+QTextDecoder (0xb62c05dc) 0
+
+Class _IO_marker
+ size=12 align=4
+ base size=12 base align=4
+_IO_marker (0xb62c0960) 0
+
+Class _IO_FILE
+ size=148 align=4
+ base size=148 base align=4
+_IO_FILE (0xb62c099c) 0
+
+Vtable for QTextStream
+QTextStream::_ZTV11QTextStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QTextStream)
+8 QTextStream::~QTextStream
+12 QTextStream::~QTextStream
+
+Class QTextStream
+ size=8 align=4
+ base size=8 base align=4
+QTextStream (0xb62c0a14) 0
+ vptr=((& QTextStream::_ZTV11QTextStream) + 8u)
+
+Class QTextStreamManipulator
+ size=24 align=4
+ base size=22 base align=4
+QTextStreamManipulator (0xb6144000) 0
+
+Vtable for QTextIStream
+QTextIStream::_ZTV12QTextIStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QTextIStream)
+8 QTextIStream::~QTextIStream
+12 QTextIStream::~QTextIStream
+
+Class QTextIStream
+ size=8 align=4
+ base size=8 base align=4
+QTextIStream (0xb61494c0) 0
+ vptr=((& QTextIStream::_ZTV12QTextIStream) + 8u)
+ QTextStream (0xb615212c) 0
+ primary-for QTextIStream (0xb61494c0)
+
+Vtable for QTextOStream
+QTextOStream::_ZTV12QTextOStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QTextOStream)
+8 QTextOStream::~QTextOStream
+12 QTextOStream::~QTextOStream
+
+Class QTextOStream
+ size=8 align=4
+ base size=8 base align=4
+QTextOStream (0xb6149780) 0
+ vptr=((& QTextOStream::_ZTV12QTextOStream) + 8u)
+ QTextStream (0xb61527bc) 0
+ primary-for QTextOStream (0xb6149780)
+
+Class wait
+ size=4 align=4
+ base size=4 base align=4
+wait (0xb6152e4c) 0
+
+Class timespec
+ size=8 align=4
+ base size=8 base align=4
+timespec (0xb6175000) 0
+
+Class timeval
+ size=8 align=4
+ base size=8 base align=4
+timeval (0xb617503c) 0
+
+Class __pthread_internal_slist
+ size=4 align=4
+ base size=4 base align=4
+__pthread_internal_slist (0xb61750f0) 0
+
+Class random_data
+ size=28 align=4
+ base size=28 base align=4
+random_data (0xb61753fc) 0
+
+Class drand48_data
+ size=24 align=4
+ base size=24 base align=4
+drand48_data (0xb6175438) 0
+
+Class QVectorData
+ size=16 align=4
+ base size=16 base align=4
+QVectorData (0xb6175474) 0
+
+Class QDebug::Stream
+ size=24 align=4
+ base size=22 base align=4
+QDebug::Stream (0xb61757bc) 0
+
+Class QDebug
+ size=4 align=4
+ base size=4 base align=4
+QDebug (0xb6175780) 0
+
+Class QNoDebug
+ size=1 align=1
+ base size=0 base align=1
+QNoDebug (0xb608b294) 0 empty
+
+Class QMetaType
+ size=1 align=1
+ base size=0 base align=1
+QMetaType (0xb608b528) 0 empty
+
+Class QVariant::PrivateShared
+ size=8 align=4
+ base size=8 base align=4
+QVariant::PrivateShared (0xb60d6f78) 0
+
+Class QVariant::Private::Data
+ size=8 align=4
+ base size=8 base align=4
+QVariant::Private::Data (0xb611f000) 0
+
+Class QVariant::Private
+ size=12 align=4
+ base size=12 base align=4
+QVariant::Private (0xb60d6fb4) 0
+
+Class QVariant::Handler
+ size=36 align=4
+ base size=36 base align=4
+QVariant::Handler (0xb611f03c) 0
+
+Class QVariant
+ size=12 align=4
+ base size=12 base align=4
+QVariant (0xb60d6f3c) 0
+
+Class QVariantComparisonHelper
+ size=4 align=4
+ base size=4 base align=4
+QVariantComparisonHelper (0xb5f72618) 0
+
+Class Phonon::ObjectDescriptionData
+ size=8 align=4
+ base size=8 base align=4
+Phonon::ObjectDescriptionData (0xb5f75dc0) 0
+ QSharedData (0xb5f72ac8) 0
+
+Class Phonon::Path
+ size=4 align=4
+ base size=4 base align=4
+Phonon::Path (0xb5fbe3c0) 0
+
+Vtable for Phonon::MediaNode
+Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon9MediaNodeE)
+8 Phonon::MediaNode::~MediaNode
+12 Phonon::MediaNode::~MediaNode
+
+Class Phonon::MediaNode
+ size=8 align=4
+ base size=8 base align=4
+Phonon::MediaNode (0xb5fbe438) 0
+ vptr=((& Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE) + 8u)
+
+Vtable for Phonon::AbstractVideoOutput
+Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractVideoOutputE)
+8 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+12 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+
+Class Phonon::AbstractVideoOutput
+ size=8 align=4
+ base size=8 base align=4
+Phonon::AbstractVideoOutput (0xb5fcc180) 0
+ vptr=((& Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE) + 8u)
+ Phonon::MediaNode (0xb5fbe4ec) 0
+ primary-for Phonon::AbstractVideoOutput (0xb5fcc180)
+
+Class Phonon::MediaSource
+ size=4 align=4
+ base size=4 base align=4
+Phonon::MediaSource (0xb5fbe834) 0
+
+Vtable for Phonon::EffectInterface
+Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15EffectInterfaceE)
+8 Phonon::EffectInterface::~EffectInterface
+12 Phonon::EffectInterface::~EffectInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+
+Class Phonon::EffectInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::EffectInterface (0xb5fbe8ac) 0 nearly-empty
+ vptr=((& Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE) + 8u)
+
+Vtable for Phonon::AddonInterface
+Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE: 6u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon14AddonInterfaceE)
+8 Phonon::AddonInterface::~AddonInterface
+12 Phonon::AddonInterface::~AddonInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+
+Class Phonon::AddonInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AddonInterface (0xb5fbed98) 0 nearly-empty
+ vptr=((& Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE) + 8u)
+
+Class QSize
+ size=8 align=4
+ base size=8 base align=4
+QSize (0xb600c294) 0
+
+Class QSizeF
+ size=16 align=4
+ base size=16 base align=4
+QSizeF (0xb5e27d20) 0
+
+Class QPoint
+ size=8 align=4
+ base size=8 base align=4
+QPoint (0xb5e54924) 0
+
+Class QPointF
+ size=16 align=4
+ base size=16 base align=4
+QPointF (0xb5e6eec4) 0
+
+Class QRect
+ size=16 align=4
+ base size=16 base align=4
+QRect (0xb5e965dc) 0
+
+Class QRectF
+ size=32 align=4
+ base size=32 base align=4
+QRectF (0xb5ef821c) 0
+
+Vtable for QPaintDevice
+QPaintDevice::_ZTV12QPaintDevice: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QPaintDevice)
+8 QPaintDevice::~QPaintDevice
+12 QPaintDevice::~QPaintDevice
+16 QPaintDevice::devType
+20 __cxa_pure_virtual
+24 QPaintDevice::metric
+
+Class QPaintDevice
+ size=8 align=4
+ base size=6 base align=4
+QPaintDevice (0xb5d2ff78) 0
+ vptr=((& QPaintDevice::_ZTV12QPaintDevice) + 8u)
+
+Class QRegExp
+ size=4 align=4
+ base size=4 base align=4
+QRegExp (0xb5d4ea8c) 0
+
+Class QStringMatcher
+ size=1036 align=4
+ base size=1036 base align=4
+QStringMatcher (0xb5d72438) 0
+
+Class QStringList
+ size=4 align=4
+ base size=4 base align=4
+QStringList (0xb5d5ba40) 0
+ QList<QString> (0xb5d725a0) 0
+
+Class QColor
+ size=16 align=4
+ base size=14 base align=4
+QColor (0xb5da5b04) 0
+
+Class QPolygon
+ size=4 align=4
+ base size=4 base align=4
+QPolygon (0xb5df61c0) 0
+ QVector<QPoint> (0xb5df7168) 0
+
+Class QPolygonF
+ size=4 align=4
+ base size=4 base align=4
+QPolygonF (0xb5df67c0) 0
+ QVector<QPointF> (0xb5df7b04) 0
+
+Class QRegion::QRegionData
+ size=16 align=4
+ base size=16 base align=4
+QRegion::QRegionData (0xb5c39438) 0
+
+Class QRegion
+ size=4 align=4
+ base size=4 base align=4
+QRegion (0xb5c393fc) 0
+
+Class QLine
+ size=16 align=4
+ base size=16 base align=4
+QLine (0xb5c39780) 0
+
+Class QLineF
+ size=32 align=4
+ base size=32 base align=4
+QLineF (0xb5c6f4b0) 0
+
+Class QMatrix
+ size=48 align=4
+ base size=48 base align=4
+QMatrix (0xb5c9f5a0) 0
+
+Class QPainterPath::Element
+ size=20 align=4
+ base size=20 base align=4
+QPainterPath::Element (0xb5c9fd20) 0
+
+Class QPainterPath
+ size=4 align=4
+ base size=4 base align=4
+QPainterPath (0xb5c9fce4) 0
+
+Class QPainterPathPrivate
+ size=8 align=4
+ base size=8 base align=4
+QPainterPathPrivate (0xb5cea1a4) 0
+
+Class QPainterPathStroker
+ size=4 align=4
+ base size=4 base align=4
+QPainterPathStroker (0xb5cea2d0) 0
+
+Class QTransform
+ size=80 align=4
+ base size=80 base align=4
+QTransform (0xb5b1a168) 0
+
+Class QImageTextKeyLang
+ size=8 align=4
+ base size=8 base align=4
+QImageTextKeyLang (0xb5b5c780) 0
+
+Vtable for QImage
+QImage::_ZTV6QImage: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI6QImage)
+8 QImage::~QImage
+12 QImage::~QImage
+16 QImage::devType
+20 QImage::paintEngine
+24 QImage::metric
+
+Class QImage
+ size=12 align=4
+ base size=12 base align=4
+QImage (0xb5b4cb40) 0
+ vptr=((& QImage::_ZTV6QImage) + 8u)
+ QPaintDevice (0xb5b87168) 0
+ primary-for QImage (0xb5b4cb40)
+
+Vtable for QPixmap
+QPixmap::_ZTV7QPixmap: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QPixmap)
+8 QPixmap::~QPixmap
+12 QPixmap::~QPixmap
+16 QPixmap::devType
+20 QPixmap::paintEngine
+24 QPixmap::metric
+
+Class QPixmap
+ size=12 align=4
+ base size=12 base align=4
+QPixmap (0xb5bc4480) 0
+ vptr=((& QPixmap::_ZTV7QPixmap) + 8u)
+ QPaintDevice (0xb5b87e10) 0
+ primary-for QPixmap (0xb5bc4480)
+
+Class QBrush
+ size=4 align=4
+ base size=4 base align=4
+QBrush (0xb5bf0474) 0
+
+Class QBrushData
+ size=104 align=4
+ base size=104 base align=4
+QBrushData (0xb5bf06cc) 0
+
+Class QGradient
+ size=56 align=4
+ base size=56 base align=4
+QGradient (0xb5bf0a8c) 0
+
+Class QLinearGradient
+ size=56 align=4
+ base size=56 base align=4
+QLinearGradient (0xb5a1a2c0) 0
+ QGradient (0xb5bf0d20) 0
+
+Class QRadialGradient
+ size=56 align=4
+ base size=56 base align=4
+QRadialGradient (0xb5a1a3c0) 0
+ QGradient (0xb5bf0d5c) 0
+
+Class QConicalGradient
+ size=56 align=4
+ base size=56 base align=4
+QConicalGradient (0xb5a1a4c0) 0
+ QGradient (0xb5bf0d98) 0
+
+Class QPalette
+ size=8 align=4
+ base size=8 base align=4
+QPalette (0xb5bf0dd4) 0
+
+Class QColorGroup
+ size=8 align=4
+ base size=8 base align=4
+QColorGroup (0xb5a1af00) 0
+ QPalette (0xb5a546cc) 0
+
+Class QFont
+ size=8 align=4
+ base size=8 base align=4
+QFont (0xb5a77834) 0
+
+Class QFontMetrics
+ size=4 align=4
+ base size=4 base align=4
+QFontMetrics (0xb5a77a14) 0
+
+Class QFontMetricsF
+ size=4 align=4
+ base size=4 base align=4
+QFontMetricsF (0xb5a77c6c) 0
+
+Class QFontInfo
+ size=4 align=4
+ base size=4 base align=4
+QFontInfo (0xb5a77d20) 0
+
+Class QSizePolicy
+ size=4 align=4
+ base size=4 base align=4
+QSizePolicy (0xb5a77d5c) 0
+
+Class QCursor
+ size=4 align=4
+ base size=4 base align=4
+QCursor (0xb5af9c30) 0
+
+Class QKeySequence
+ size=4 align=4
+ base size=4 base align=4
+QKeySequence (0xb5af9c6c) 0
+
+Class QWidgetData
+ size=64 align=4
+ base size=64 base align=4
+QWidgetData (0xb5af9f78) 0
+
+Vtable for QWidget
+QWidget::_ZTV7QWidget: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QWidget)
+8 QWidget::metaObject
+12 QWidget::qt_metacast
+16 QWidget::qt_metacall
+20 QWidget::~QWidget
+24 QWidget::~QWidget
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTI7QWidget)
+232 QWidget::_ZThn8_N7QWidgetD1Ev
+236 QWidget::_ZThn8_N7QWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class QWidget
+ size=20 align=4
+ base size=20 base align=4
+QWidget (0xb5948410) 0
+ vptr=((& QWidget::_ZTV7QWidget) + 8u)
+ QObject (0xb5af9fb4) 0
+ primary-for QWidget (0xb5948410)
+ QPaintDevice (0xb5951000) 8
+ vptr=((& QWidget::_ZTV7QWidget) + 232u)
+
+Vtable for Phonon::VideoPlayer
+Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+8 Phonon::VideoPlayer::metaObject
+12 Phonon::VideoPlayer::qt_metacast
+16 Phonon::VideoPlayer::qt_metacall
+20 Phonon::VideoPlayer::~VideoPlayer
+24 Phonon::VideoPlayer::~VideoPlayer
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+232 Phonon::VideoPlayer::_ZThn8_N6Phonon11VideoPlayerD1Ev
+236 Phonon::VideoPlayer::_ZThn8_N6Phonon11VideoPlayerD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VideoPlayer
+ size=24 align=4
+ base size=24 base align=4
+Phonon::VideoPlayer (0xb59e0cc0) 0
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 8u)
+ QWidget (0xb5a085f0) 0
+ primary-for Phonon::VideoPlayer (0xb59e0cc0)
+ QObject (0xb59f1618) 0
+ primary-for QWidget (0xb5a085f0)
+ QPaintDevice (0xb59f1654) 8
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 232u)
+
+Vtable for Phonon::Effect
+Phonon::Effect::_ZTVN6Phonon6EffectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+8 Phonon::Effect::metaObject
+12 Phonon::Effect::qt_metacast
+16 Phonon::Effect::qt_metacall
+20 Phonon::Effect::~Effect
+24 Phonon::Effect::~Effect
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+64 Phonon::Effect::_ZThn8_N6Phonon6EffectD1Ev
+68 Phonon::Effect::_ZThn8_N6Phonon6EffectD0Ev
+
+Class Phonon::Effect
+ size=16 align=4
+ base size=16 base align=4
+Phonon::Effect (0xb5803f00) 0
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 8u)
+ QObject (0xb59f1780) 0
+ primary-for Phonon::Effect (0xb5803f00)
+ Phonon::MediaNode (0xb59f17bc) 8
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 64u)
+
+Vtable for Phonon::VolumeFaderEffect
+Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+8 Phonon::VolumeFaderEffect::metaObject
+12 Phonon::VolumeFaderEffect::qt_metacast
+16 Phonon::VolumeFaderEffect::qt_metacall
+20 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+24 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+64 Phonon::VolumeFaderEffect::_ZThn8_N6Phonon17VolumeFaderEffectD1Ev
+68 Phonon::VolumeFaderEffect::_ZThn8_N6Phonon17VolumeFaderEffectD0Ev
+
+Class Phonon::VolumeFaderEffect
+ size=16 align=4
+ base size=16 base align=4
+Phonon::VolumeFaderEffect (0xb5815180) 0
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 8u)
+ Phonon::Effect (0xb58125a0) 0
+ primary-for Phonon::VolumeFaderEffect (0xb5815180)
+ QObject (0xb59f19d8) 0
+ primary-for Phonon::Effect (0xb58125a0)
+ Phonon::MediaNode (0xb59f1a14) 8
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 64u)
+
+Class QModelIndex
+ size=16 align=4
+ base size=16 base align=4
+QModelIndex (0xb59f1c30) 0
+
+Class QPersistentModelIndex
+ size=4 align=4
+ base size=4 base align=4
+QPersistentModelIndex (0xb58380f0) 0
+
+Vtable for QAbstractItemModel
+QAbstractItemModel::_ZTV18QAbstractItemModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI18QAbstractItemModel)
+8 QAbstractItemModel::metaObject
+12 QAbstractItemModel::qt_metacast
+16 QAbstractItemModel::qt_metacall
+20 QAbstractItemModel::~QAbstractItemModel
+24 QAbstractItemModel::~QAbstractItemModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 QAbstractItemModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractItemModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractItemModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractItemModel (0xb5815dc0) 0
+ vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 8u)
+ QObject (0xb5838258) 0
+ primary-for QAbstractItemModel (0xb5815dc0)
+
+Vtable for QAbstractTableModel
+QAbstractTableModel::_ZTV19QAbstractTableModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI19QAbstractTableModel)
+8 QAbstractTableModel::metaObject
+12 QAbstractTableModel::qt_metacast
+16 QAbstractTableModel::qt_metacall
+20 QAbstractTableModel::~QAbstractTableModel
+24 QAbstractTableModel::~QAbstractTableModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QAbstractTableModel::index
+60 QAbstractTableModel::parent
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 QAbstractTableModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractTableModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractTableModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractTableModel (0xb5864400) 0
+ vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 8u)
+ QAbstractItemModel (0xb5864440) 0
+ primary-for QAbstractTableModel (0xb5864400)
+ QObject (0xb5838bb8) 0
+ primary-for QAbstractItemModel (0xb5864440)
+
+Vtable for QAbstractListModel
+QAbstractListModel::_ZTV18QAbstractListModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI18QAbstractListModel)
+8 QAbstractListModel::metaObject
+12 QAbstractListModel::qt_metacast
+16 QAbstractListModel::qt_metacall
+20 QAbstractListModel::~QAbstractListModel
+24 QAbstractListModel::~QAbstractListModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QAbstractListModel::index
+60 QAbstractListModel::parent
+64 __cxa_pure_virtual
+68 QAbstractListModel::columnCount
+72 QAbstractListModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractListModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractListModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractListModel (0xb5864680) 0
+ vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 8u)
+ QAbstractItemModel (0xb58646c0) 0
+ primary-for QAbstractListModel (0xb5864680)
+ QObject (0xb5838ce4) 0
+ primary-for QAbstractItemModel (0xb58646c0)
+
+Class Phonon::ObjectDescriptionModelData
+ size=4 align=4
+ base size=4 base align=4
+Phonon::ObjectDescriptionModelData (0xb5885bb8) 0
+
+Vtable for Phonon::StreamInterface
+Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE: 8u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15StreamInterfaceE)
+8 Phonon::StreamInterface::~StreamInterface
+12 Phonon::StreamInterface::~StreamInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+
+Class Phonon::StreamInterface
+ size=8 align=4
+ base size=8 base align=4
+Phonon::StreamInterface (0xb5885d98) 0
+ vptr=((& Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE) + 8u)
+
+Vtable for Phonon::SeekSlider
+Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+8 Phonon::SeekSlider::metaObject
+12 Phonon::SeekSlider::qt_metacast
+16 Phonon::SeekSlider::qt_metacall
+20 Phonon::SeekSlider::~SeekSlider
+24 Phonon::SeekSlider::~SeekSlider
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+232 Phonon::SeekSlider::_ZThn8_N6Phonon10SeekSliderD1Ev
+236 Phonon::SeekSlider::_ZThn8_N6Phonon10SeekSliderD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::SeekSlider
+ size=24 align=4
+ base size=24 base align=4
+Phonon::SeekSlider (0xb589fb80) 0
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 8u)
+ QWidget (0xb58df3c0) 0
+ primary-for Phonon::SeekSlider (0xb589fb80)
+ QObject (0xb58e10b4) 0
+ primary-for QWidget (0xb58df3c0)
+ QPaintDevice (0xb58e10f0) 8
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 232u)
+
+Vtable for Phonon::PlatformPlugin
+Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE: 16u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon14PlatformPluginE)
+8 Phonon::PlatformPlugin::~PlatformPlugin
+12 Phonon::PlatformPlugin::~PlatformPlugin
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 Phonon::PlatformPlugin::deviceAccessListFor
+
+Class Phonon::PlatformPlugin
+ size=4 align=4
+ base size=4 base align=4
+Phonon::PlatformPlugin (0xb58e1294) 0 nearly-empty
+ vptr=((& Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE) + 8u)
+
+Vtable for Phonon::MediaController
+Phonon::MediaController::_ZTVN6Phonon15MediaControllerE: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15MediaControllerE)
+8 Phonon::MediaController::metaObject
+12 Phonon::MediaController::qt_metacast
+16 Phonon::MediaController::qt_metacall
+20 Phonon::MediaController::~MediaController
+24 Phonon::MediaController::~MediaController
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class Phonon::MediaController
+ size=12 align=4
+ base size=12 base align=4
+Phonon::MediaController (0xb58f82c0) 0
+ vptr=((& Phonon::MediaController::_ZTVN6Phonon15MediaControllerE) + 8u)
+ QObject (0xb58e17bc) 0
+ primary-for Phonon::MediaController (0xb58f82c0)
+
+Vtable for Phonon::VolumeSlider
+Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+8 Phonon::VolumeSlider::metaObject
+12 Phonon::VolumeSlider::qt_metacast
+16 Phonon::VolumeSlider::qt_metacall
+20 Phonon::VolumeSlider::~VolumeSlider
+24 Phonon::VolumeSlider::~VolumeSlider
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+232 Phonon::VolumeSlider::_ZThn8_N6Phonon12VolumeSliderD1Ev
+236 Phonon::VolumeSlider::_ZThn8_N6Phonon12VolumeSliderD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VolumeSlider
+ size=24 align=4
+ base size=24 base align=4
+Phonon::VolumeSlider (0xb58f8640) 0
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 8u)
+ QWidget (0xb57293c0) 0
+ primary-for Phonon::VolumeSlider (0xb58f8640)
+ QObject (0xb58e19d8) 0
+ primary-for QWidget (0xb57293c0)
+ QPaintDevice (0xb58e1a14) 8
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 232u)
+
+Vtable for Phonon::MediaObject
+Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+8 Phonon::MediaObject::metaObject
+12 Phonon::MediaObject::qt_metacast
+16 Phonon::MediaObject::qt_metacall
+20 Phonon::MediaObject::~MediaObject
+24 Phonon::MediaObject::~MediaObject
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+64 Phonon::MediaObject::_ZThn8_N6Phonon11MediaObjectD1Ev
+68 Phonon::MediaObject::_ZThn8_N6Phonon11MediaObjectD0Ev
+
+Class Phonon::MediaObject
+ size=16 align=4
+ base size=16 base align=4
+Phonon::MediaObject (0xb5733f50) 0
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 8u)
+ QObject (0xb58e1bb8) 0
+ primary-for Phonon::MediaObject (0xb5733f50)
+ Phonon::MediaNode (0xb58e1bf4) 8
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 64u)
+
+Vtable for Phonon::EffectWidget
+Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+8 Phonon::EffectWidget::metaObject
+12 Phonon::EffectWidget::qt_metacast
+16 Phonon::EffectWidget::qt_metacall
+20 Phonon::EffectWidget::~EffectWidget
+24 Phonon::EffectWidget::~EffectWidget
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+232 Phonon::EffectWidget::_ZThn8_N6Phonon12EffectWidgetD1Ev
+236 Phonon::EffectWidget::_ZThn8_N6Phonon12EffectWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::EffectWidget
+ size=24 align=4
+ base size=24 base align=4
+Phonon::EffectWidget (0xb58f8b80) 0
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 8u)
+ QWidget (0xb5749550) 0
+ primary-for Phonon::EffectWidget (0xb58f8b80)
+ QObject (0xb58e1e10) 0
+ primary-for QWidget (0xb5749550)
+ QPaintDevice (0xb58e1e4c) 8
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 232u)
+
+Class Phonon::EffectParameter
+ size=4 align=4
+ base size=4 base align=4
+Phonon::EffectParameter (0xb575c000) 0
+
+Vtable for Phonon::VolumeFaderInterface
+Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20VolumeFaderInterfaceE)
+8 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+12 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+16 Phonon::VolumeFaderInterface::volume
+20 Phonon::VolumeFaderInterface::setVolume
+24 Phonon::VolumeFaderInterface::fadeCurve
+28 Phonon::VolumeFaderInterface::setFadeCurve
+32 Phonon::VolumeFaderInterface::fadeTo
+
+Class Phonon::VolumeFaderInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::VolumeFaderInterface (0xb575c168) 0 nearly-empty
+ vptr=((& Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE) + 8u)
+
+Vtable for Phonon::AbstractAudioOutput
+Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+8 Phonon::AbstractAudioOutput::metaObject
+12 Phonon::AbstractAudioOutput::qt_metacast
+16 Phonon::AbstractAudioOutput::qt_metacall
+20 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+24 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+64 Phonon::AbstractAudioOutput::_ZThn8_N6Phonon19AbstractAudioOutputD1Ev
+68 Phonon::AbstractAudioOutput::_ZThn8_N6Phonon19AbstractAudioOutputD0Ev
+
+Class Phonon::AbstractAudioOutput
+ size=16 align=4
+ base size=16 base align=4
+Phonon::AbstractAudioOutput (0xb577fa50) 0
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 8u)
+ QObject (0xb575c654) 0
+ primary-for Phonon::AbstractAudioOutput (0xb577fa50)
+ Phonon::MediaNode (0xb575c690) 8
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 64u)
+
+Vtable for Phonon::AudioOutput
+Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+8 Phonon::AudioOutput::metaObject
+12 Phonon::AudioOutput::qt_metacast
+16 Phonon::AudioOutput::qt_metacall
+20 Phonon::AudioOutput::~AudioOutput
+24 Phonon::AudioOutput::~AudioOutput
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+64 Phonon::AudioOutput::_ZThn8_N6Phonon11AudioOutputD1Ev
+68 Phonon::AudioOutput::_ZThn8_N6Phonon11AudioOutputD0Ev
+
+Class Phonon::AudioOutput
+ size=16 align=4
+ base size=16 base align=4
+Phonon::AudioOutput (0xb577c7c0) 0
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 8u)
+ Phonon::AbstractAudioOutput (0xb5786cd0) 0
+ primary-for Phonon::AudioOutput (0xb577c7c0)
+ QObject (0xb575c8ac) 0
+ primary-for Phonon::AbstractAudioOutput (0xb5786cd0)
+ Phonon::MediaNode (0xb575c8e8) 8
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 64u)
+
+Vtable for Phonon::AudioOutputInterface40
+Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E: 8u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface40E)
+8 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+12 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface40
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AudioOutputInterface40 (0xb575cb04) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E) + 8u)
+
+Vtable for Phonon::AudioOutputInterface42
+Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface42E)
+8 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+12 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface42
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AudioOutputInterface42 (0xb577cc80) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E) + 8u)
+ Phonon::AudioOutputInterface40 (0xb575cd20) 0 nearly-empty
+ primary-for Phonon::AudioOutputInterface42 (0xb577cc80)
+
+Vtable for Phonon::BackendCapabilities::Notifier
+Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19BackendCapabilities8NotifierE)
+8 Phonon::BackendCapabilities::Notifier::metaObject
+12 Phonon::BackendCapabilities::Notifier::qt_metacast
+16 Phonon::BackendCapabilities::Notifier::qt_metacall
+20 Phonon::BackendCapabilities::Notifier::~Notifier
+24 Phonon::BackendCapabilities::Notifier::~Notifier
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class Phonon::BackendCapabilities::Notifier
+ size=8 align=4
+ base size=8 base align=4
+Phonon::BackendCapabilities::Notifier (0xb57a9100) 0
+ vptr=((& Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE) + 8u)
+ QObject (0xb57a821c) 0
+ primary-for Phonon::BackendCapabilities::Notifier (0xb57a9100)
+
+Vtable for Phonon::BackendInterface
+Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE: 12u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon16BackendInterfaceE)
+8 Phonon::BackendInterface::~BackendInterface
+12 Phonon::BackendInterface::~BackendInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+
+Class Phonon::BackendInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::BackendInterface (0xb57a8348) 0 nearly-empty
+ vptr=((& Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE) + 8u)
+
+Vtable for Phonon::AbstractMediaStream
+Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractMediaStreamE)
+8 Phonon::AbstractMediaStream::metaObject
+12 Phonon::AbstractMediaStream::qt_metacast
+16 Phonon::AbstractMediaStream::qt_metacall
+20 Phonon::AbstractMediaStream::~AbstractMediaStream
+24 Phonon::AbstractMediaStream::~AbstractMediaStream
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 Phonon::AbstractMediaStream::enoughData
+68 Phonon::AbstractMediaStream::seekStream
+
+Class Phonon::AbstractMediaStream
+ size=12 align=4
+ base size=12 base align=4
+Phonon::AbstractMediaStream (0xb57a9700) 0
+ vptr=((& Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE) + 8u)
+ QObject (0xb57a8834) 0
+ primary-for Phonon::AbstractMediaStream (0xb57a9700)
+
+Vtable for Phonon::VideoWidget
+Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE: 67u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+8 Phonon::VideoWidget::metaObject
+12 Phonon::VideoWidget::qt_metacast
+16 Phonon::VideoWidget::qt_metacall
+20 Phonon::VideoWidget::~VideoWidget
+24 Phonon::VideoWidget::~VideoWidget
+28 Phonon::VideoWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 Phonon::VideoWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+232 Phonon::VideoWidget::_ZThn8_N6Phonon11VideoWidgetD1Ev
+236 Phonon::VideoWidget::_ZThn8_N6Phonon11VideoWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+252 (int (*)(...))-0x000000014
+256 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+260 Phonon::VideoWidget::_ZThn20_N6Phonon11VideoWidgetD1Ev
+264 Phonon::VideoWidget::_ZThn20_N6Phonon11VideoWidgetD0Ev
+
+Class Phonon::VideoWidget
+ size=28 align=4
+ base size=28 base align=4
+Phonon::VideoWidget (0xb57ca1e0) 0
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 8u)
+ QWidget (0xb57ca230) 0
+ primary-for Phonon::VideoWidget (0xb57ca1e0)
+ QObject (0xb57a89d8) 0
+ primary-for QWidget (0xb57ca230)
+ QPaintDevice (0xb57a8a14) 8
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 232u)
+ Phonon::AbstractVideoOutput (0xb57a99c0) 20
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 260u)
+ Phonon::MediaNode (0xb57a8a50) 20
+ primary-for Phonon::AbstractVideoOutput (0xb57a99c0)
+
+Vtable for Phonon::VideoWidgetInterface
+Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE: 17u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20VideoWidgetInterfaceE)
+8 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+12 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+
+Class Phonon::VideoWidgetInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::VideoWidgetInterface (0xb57a8c6c) 0 nearly-empty
+ vptr=((& Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE) + 8u)
+
+Vtable for Phonon::MediaObjectInterface
+Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE: 25u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20MediaObjectInterfaceE)
+8 Phonon::MediaObjectInterface::~MediaObjectInterface
+12 Phonon::MediaObjectInterface::~MediaObjectInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 __cxa_pure_virtual
+76 __cxa_pure_virtual
+80 Phonon::MediaObjectInterface::remainingTime
+84 __cxa_pure_virtual
+88 __cxa_pure_virtual
+92 __cxa_pure_virtual
+96 __cxa_pure_virtual
+
+Class Phonon::MediaObjectInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::MediaObjectInterface (0xb57e50f0) 0 nearly-empty
+ vptr=((& Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE) + 8u)
+
diff --git a/tests/auto/bic/data/phonon.4.6.0.linux-gcc-amd64.txt b/tests/auto/bic/data/phonon.4.6.0.linux-gcc-amd64.txt
new file mode 100644
index 0000000..b962099
--- /dev/null
+++ b/tests/auto/bic/data/phonon.4.6.0.linux-gcc-amd64.txt
@@ -0,0 +1,1980 @@
+Class QSysInfo
+ size=1 align=1
+ base size=0 base align=1
+QSysInfo (0x7f37bb27e230) 0 empty
+
+Class QBool
+ size=1 align=1
+ base size=1 base align=1
+QBool (0x7f37bb27ee70) 0
+
+Class qIsNull(double)::U
+ size=8 align=8
+ base size=8 base align=8
+qIsNull(double)::U (0x7f37bb2a9540) 0
+
+Class qIsNull(float)::U
+ size=4 align=4
+ base size=4 base align=4
+qIsNull(float)::U (0x7f37bb2a97e0) 0
+
+Class QFlag
+ size=4 align=4
+ base size=4 base align=4
+QFlag (0x7f37ba9cb690) 0
+
+Class QIncompatibleFlag
+ size=4 align=4
+ base size=4 base align=4
+QIncompatibleFlag (0x7f37ba9cbe70) 0
+
+Class QBasicAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QBasicAtomicInt (0x7f37ba9f75b0) 0
+
+Class QAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QAtomicInt (0x7f37baa51f50) 0
+ QBasicAtomicInt (0x7f37baa67000) 0
+
+Class QSharedData
+ size=4 align=4
+ base size=4 base align=4
+QSharedData (0x7f37baa743f0) 0
+
+Class QLatin1Char
+ size=1 align=1
+ base size=1 base align=1
+QLatin1Char (0x7f37ba8fd310) 0
+
+Class QChar
+ size=2 align=2
+ base size=2 base align=2
+QChar (0x7f37ba8fde70) 0
+
+Vtable for std::exception
+std::exception::_ZTVSt9exception: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9exception)
+16 std::exception::~exception
+24 std::exception::~exception
+32 std::exception::what
+
+Class std::exception
+ size=8 align=8
+ base size=8 base align=8
+std::exception (0x7f37ba978070) 0 nearly-empty
+ vptr=((& std::exception::_ZTVSt9exception) + 16u)
+
+Vtable for std::bad_exception
+std::bad_exception::_ZTVSt13bad_exception: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt13bad_exception)
+16 std::bad_exception::~bad_exception
+24 std::bad_exception::~bad_exception
+32 std::bad_exception::what
+
+Class std::bad_exception
+ size=8 align=8
+ base size=8 base align=8
+std::bad_exception (0x7f37ba978620) 0 nearly-empty
+ vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 16u)
+ std::exception (0x7f37ba978690) 0 nearly-empty
+ primary-for std::bad_exception (0x7f37ba978620)
+
+Vtable for std::bad_alloc
+std::bad_alloc::_ZTVSt9bad_alloc: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTISt9bad_alloc)
+16 std::bad_alloc::~bad_alloc
+24 std::bad_alloc::~bad_alloc
+32 std::bad_alloc::what
+
+Class std::bad_alloc
+ size=8 align=8
+ base size=8 base align=8
+std::bad_alloc (0x7f37ba978ee0) 0 nearly-empty
+ vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 16u)
+ std::exception (0x7f37ba978f50) 0 nearly-empty
+ primary-for std::bad_alloc (0x7f37ba978ee0)
+
+Class std::nothrow_t
+ size=1 align=1
+ base size=0 base align=1
+std::nothrow_t (0x7f37ba98d700) 0 empty
+
+Class __locale_struct
+ size=232 align=8
+ base size=232 base align=8
+__locale_struct (0x7f37ba98dbd0) 0
+
+Class QListData::Data
+ size=32 align=8
+ base size=32 base align=8
+QListData::Data (0x7f37ba98dcb0) 0
+
+Class QListData
+ size=8 align=8
+ base size=8 base align=8
+QListData (0x7f37ba98dc40) 0
+
+Class QScopedPointerPodDeleter
+ size=1 align=1
+ base size=0 base align=1
+QScopedPointerPodDeleter (0x7f37ba6cb770) 0 empty
+
+Class QInternal
+ size=1 align=1
+ base size=0 base align=1
+QInternal (0x7f37ba512540) 0 empty
+
+Class QGenericArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericArgument (0x7f37ba512850) 0
+
+Class QGenericReturnArgument
+ size=16 align=8
+ base size=16 base align=8
+QGenericReturnArgument (0x7f37ba52f3f0) 0
+ QGenericArgument (0x7f37ba52f460) 0
+
+Class QMetaObject
+ size=32 align=8
+ base size=32 base align=8
+QMetaObject (0x7f37ba52fcb0) 0
+
+Class QMetaObjectExtraData
+ size=16 align=8
+ base size=16 base align=8
+QMetaObjectExtraData (0x7f37ba558d20) 0
+
+Class QByteArray::Data
+ size=32 align=8
+ base size=32 base align=8
+QByteArray::Data (0x7f37ba56daf0) 0
+
+Class QByteArray
+ size=8 align=8
+ base size=8 base align=8
+QByteArray (0x7f37ba56da80) 0
+
+Class QByteRef
+ size=16 align=8
+ base size=12 base align=8
+QByteRef (0x7f37ba40e380) 0
+
+Class QString::Null
+ size=1 align=1
+ base size=0 base align=1
+QString::Null (0x7f37ba30ed20) 0 empty
+
+Class QString::Data
+ size=32 align=8
+ base size=32 base align=8
+QString::Data (0x7f37ba3275b0) 0
+
+Class QString
+ size=8 align=8
+ base size=8 base align=8
+QString (0x7f37ba489bd0) 0
+
+Class QLatin1String
+ size=8 align=8
+ base size=8 base align=8
+QLatin1String (0x7f37ba1fb9a0) 0
+
+Class QCharRef
+ size=16 align=8
+ base size=12 base align=8
+QCharRef (0x7f37ba0a0000) 0
+
+Class QConstString
+ size=8 align=8
+ base size=8 base align=8
+QConstString (0x7f37b9fd8850) 0
+ QString (0x7f37b9fd88c0) 0
+
+Class QStringRef
+ size=16 align=8
+ base size=16 base align=8
+QStringRef (0x7f37b9ffc2a0) 0
+
+Vtable for QObjectData
+QObjectData::_ZTV11QObjectData: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QObjectData)
+16 __cxa_pure_virtual
+24 __cxa_pure_virtual
+
+Class QObjectData
+ size=48 align=8
+ base size=48 base align=8
+QObjectData (0x7f37ba0795b0) 0
+ vptr=((& QObjectData::_ZTV11QObjectData) + 16u)
+
+Vtable for QObject
+QObject::_ZTV7QObject: 14u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QObject)
+16 QObject::metaObject
+24 QObject::qt_metacast
+32 QObject::qt_metacall
+40 QObject::~QObject
+48 QObject::~QObject
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+
+Class QObject
+ size=16 align=8
+ base size=16 base align=8
+QObject (0x7f37ba0798c0) 0
+ vptr=((& QObject::_ZTV7QObject) + 16u)
+
+Vtable for QObjectUserData
+QObjectUserData::_ZTV15QObjectUserData: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI15QObjectUserData)
+16 QObjectUserData::~QObjectUserData
+24 QObjectUserData::~QObjectUserData
+
+Class QObjectUserData
+ size=8 align=8
+ base size=8 base align=8
+QObjectUserData (0x7f37b9ef7e70) 0 nearly-empty
+ vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 16u)
+
+Vtable for QIODevice
+QIODevice::_ZTV9QIODevice: 30u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI9QIODevice)
+16 QIODevice::metaObject
+24 QIODevice::qt_metacast
+32 QIODevice::qt_metacall
+40 QIODevice::~QIODevice
+48 QIODevice::~QIODevice
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QIODevice::isSequential
+120 QIODevice::open
+128 QIODevice::close
+136 QIODevice::pos
+144 QIODevice::size
+152 QIODevice::seek
+160 QIODevice::atEnd
+168 QIODevice::reset
+176 QIODevice::bytesAvailable
+184 QIODevice::bytesToWrite
+192 QIODevice::canReadLine
+200 QIODevice::waitForReadyRead
+208 QIODevice::waitForBytesWritten
+216 __cxa_pure_virtual
+224 QIODevice::readLineData
+232 __cxa_pure_virtual
+
+Class QIODevice
+ size=16 align=8
+ base size=16 base align=8
+QIODevice (0x7f37b9f05460) 0
+ vptr=((& QIODevice::_ZTV9QIODevice) + 16u)
+ QObject (0x7f37b9f054d0) 0
+ primary-for QIODevice (0x7f37b9f05460)
+
+Vtable for QDataStream
+QDataStream::_ZTV11QDataStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QDataStream)
+16 QDataStream::~QDataStream
+24 QDataStream::~QDataStream
+
+Class QDataStream
+ size=40 align=8
+ base size=40 base align=8
+QDataStream (0x7f37b9f6bd90) 0
+ vptr=((& QDataStream::_ZTV11QDataStream) + 16u)
+
+Class QHashData::Node
+ size=16 align=8
+ base size=16 base align=8
+QHashData::Node (0x7f37b9e00e70) 0
+
+Class QHashData
+ size=40 align=8
+ base size=40 base align=8
+QHashData (0x7f37b9e00e00) 0
+
+Class QHashDummyValue
+ size=1 align=1
+ base size=0 base align=1
+QHashDummyValue (0x7f37b9e211c0) 0 empty
+
+Class QMapData::Node
+ size=16 align=8
+ base size=16 base align=8
+QMapData::Node (0x7f37b9d24af0) 0
+
+Class QMapData
+ size=128 align=8
+ base size=128 base align=8
+QMapData (0x7f37b9d24a80) 0
+
+Vtable for QSystemLocale
+QSystemLocale::_ZTV13QSystemLocale: 6u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI13QSystemLocale)
+16 QSystemLocale::~QSystemLocale
+24 QSystemLocale::~QSystemLocale
+32 QSystemLocale::query
+40 QSystemLocale::fallbackLocale
+
+Class QSystemLocale
+ size=8 align=8
+ base size=8 base align=8
+QSystemLocale (0x7f37b9c5e700) 0 nearly-empty
+ vptr=((& QSystemLocale::_ZTV13QSystemLocale) + 16u)
+
+Class QLocale::Data
+ size=4 align=2
+ base size=4 base align=2
+QLocale::Data (0x7f37b9aabe00) 0
+
+Class QLocale
+ size=8 align=8
+ base size=8 base align=8
+QLocale (0x7f37b9c5eb60) 0
+
+Class QTextCodec::ConverterState
+ size=32 align=8
+ base size=32 base align=8
+QTextCodec::ConverterState (0x7f37b9affc40) 0
+
+Vtable for QTextCodec
+QTextCodec::_ZTV10QTextCodec: 9u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI10QTextCodec)
+16 __cxa_pure_virtual
+24 QTextCodec::aliases
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 QTextCodec::~QTextCodec
+64 QTextCodec::~QTextCodec
+
+Class QTextCodec
+ size=8 align=8
+ base size=8 base align=8
+QTextCodec (0x7f37b9af04d0) 0 nearly-empty
+ vptr=((& QTextCodec::_ZTV10QTextCodec) + 16u)
+
+Class QTextEncoder
+ size=40 align=8
+ base size=40 base align=8
+QTextEncoder (0x7f37b9b6c1c0) 0
+
+Class QTextDecoder
+ size=40 align=8
+ base size=40 base align=8
+QTextDecoder (0x7f37b9b73000) 0
+
+Class _IO_marker
+ size=24 align=8
+ base size=24 base align=8
+_IO_marker (0x7f37b9985070) 0
+
+Class _IO_FILE
+ size=216 align=8
+ base size=216 base align=8
+_IO_FILE (0x7f37b99850e0) 0
+
+Vtable for QTextStream
+QTextStream::_ZTV11QTextStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI11QTextStream)
+16 QTextStream::~QTextStream
+24 QTextStream::~QTextStream
+
+Class QTextStream
+ size=16 align=8
+ base size=16 base align=8
+QTextStream (0x7f37b99851c0) 0
+ vptr=((& QTextStream::_ZTV11QTextStream) + 16u)
+
+Class QTextStreamManipulator
+ size=40 align=8
+ base size=38 base align=8
+QTextStreamManipulator (0x7f37b9a22e70) 0
+
+Vtable for QTextIStream
+QTextIStream::_ZTV12QTextIStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI12QTextIStream)
+16 QTextIStream::~QTextIStream
+24 QTextIStream::~QTextIStream
+
+Class QTextIStream
+ size=16 align=8
+ base size=16 base align=8
+QTextIStream (0x7f37b9a50460) 0
+ vptr=((& QTextIStream::_ZTV12QTextIStream) + 16u)
+ QTextStream (0x7f37b9a504d0) 0
+ primary-for QTextIStream (0x7f37b9a50460)
+
+Vtable for QTextOStream
+QTextOStream::_ZTV12QTextOStream: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI12QTextOStream)
+16 QTextOStream::~QTextOStream
+24 QTextOStream::~QTextOStream
+
+Class QTextOStream
+ size=16 align=8
+ base size=16 base align=8
+QTextOStream (0x7f37b9a66310) 0
+ vptr=((& QTextOStream::_ZTV12QTextOStream) + 16u)
+ QTextStream (0x7f37b9a66380) 0
+ primary-for QTextOStream (0x7f37b9a66310)
+
+Class wait
+ size=4 align=4
+ base size=4 base align=4
+wait (0x7f37b9a781c0) 0
+
+Class timespec
+ size=16 align=8
+ base size=16 base align=8
+timespec (0x7f37b9a784d0) 0
+
+Class timeval
+ size=16 align=8
+ base size=16 base align=8
+timeval (0x7f37b9a78540) 0
+
+Class __pthread_internal_list
+ size=16 align=8
+ base size=16 base align=8
+__pthread_internal_list (0x7f37b9a78690) 0
+
+Class random_data
+ size=48 align=8
+ base size=48 base align=8
+random_data (0x7f37b9a78c40) 0
+
+Class drand48_data
+ size=24 align=8
+ base size=24 base align=8
+drand48_data (0x7f37b9a78cb0) 0
+
+Class QVectorData
+ size=16 align=4
+ base size=16 base align=4
+QVectorData (0x7f37b9a78d20) 0
+
+Class QContiguousCacheData
+ size=24 align=4
+ base size=24 base align=4
+QContiguousCacheData (0x7f37b982ea10) 0
+
+Class QDebug::Stream
+ size=40 align=8
+ base size=34 base align=8
+QDebug::Stream (0x7f37b96af540) 0
+
+Class QDebug
+ size=8 align=8
+ base size=8 base align=8
+QDebug (0x7f37b96af4d0) 0
+
+Class QNoDebug
+ size=1 align=1
+ base size=0 base align=1
+QNoDebug (0x7f37b97614d0) 0 empty
+
+Class QMetaType
+ size=1 align=1
+ base size=0 base align=1
+QMetaType (0x7f37b9771b60) 0 empty
+
+Class QVariant::PrivateShared
+ size=16 align=8
+ base size=12 base align=8
+QVariant::PrivateShared (0x7f37b967b3f0) 0
+
+Class QVariant::Private::Data
+ size=8 align=8
+ base size=8 base align=8
+QVariant::Private::Data (0x7f37b967b700) 0
+
+Class QVariant::Private
+ size=16 align=8
+ base size=12 base align=8
+QVariant::Private (0x7f37b967b4d0) 0
+
+Class QVariant::Handler
+ size=72 align=8
+ base size=72 base align=8
+QVariant::Handler (0x7f37b94863f0) 0
+
+Class QVariant
+ size=16 align=8
+ base size=16 base align=8
+QVariant (0x7f37b964e4d0) 0
+
+Class QVariantComparisonHelper
+ size=8 align=8
+ base size=8 base align=8
+QVariantComparisonHelper (0x7f37b9541690) 0
+
+Class Phonon::ObjectDescriptionData
+ size=16 align=8
+ base size=16 base align=8
+Phonon::ObjectDescriptionData (0x7f37b9568bd0) 0
+ QSharedData (0x7f37b9568c40) 0
+
+Class Phonon::Path
+ size=8 align=8
+ base size=8 base align=8
+Phonon::Path (0x7f37b93c0930) 0
+
+Vtable for Phonon::MediaNode
+Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon9MediaNodeE)
+16 Phonon::MediaNode::~MediaNode
+24 Phonon::MediaNode::~MediaNode
+
+Class Phonon::MediaNode
+ size=16 align=8
+ base size=16 base align=8
+Phonon::MediaNode (0x7f37b93da150) 0
+ vptr=((& Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE) + 16u)
+
+Vtable for Phonon::AbstractAudioOutput
+Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+16 Phonon::AbstractAudioOutput::metaObject
+24 Phonon::AbstractAudioOutput::qt_metacast
+32 Phonon::AbstractAudioOutput::qt_metacall
+40 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+48 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+128 Phonon::AbstractAudioOutput::_ZThn16_N6Phonon19AbstractAudioOutputD1Ev
+136 Phonon::AbstractAudioOutput::_ZThn16_N6Phonon19AbstractAudioOutputD0Ev
+
+Class Phonon::AbstractAudioOutput
+ size=32 align=8
+ base size=32 base align=8
+Phonon::AbstractAudioOutput (0x7f37b93f0100) 0
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 16u)
+ QObject (0x7f37b93da8c0) 0
+ primary-for Phonon::AbstractAudioOutput (0x7f37b93f0100)
+ Phonon::MediaNode (0x7f37b93da930) 16
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 128u)
+
+Vtable for Phonon::AbstractMediaStream
+Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19AbstractMediaStreamE)
+16 Phonon::AbstractMediaStream::metaObject
+24 Phonon::AbstractMediaStream::qt_metacast
+32 Phonon::AbstractMediaStream::qt_metacall
+40 Phonon::AbstractMediaStream::~AbstractMediaStream
+48 Phonon::AbstractMediaStream::~AbstractMediaStream
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 Phonon::AbstractMediaStream::enoughData
+136 Phonon::AbstractMediaStream::seekStream
+
+Class Phonon::AbstractMediaStream
+ size=24 align=8
+ base size=24 base align=8
+Phonon::AbstractMediaStream (0x7f37b9414540) 0
+ vptr=((& Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE) + 16u)
+ QObject (0x7f37b94145b0) 0
+ primary-for Phonon::AbstractMediaStream (0x7f37b9414540)
+
+Vtable for Phonon::AbstractVideoOutput
+Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE: 4u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19AbstractVideoOutputE)
+16 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+24 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+
+Class Phonon::AbstractVideoOutput
+ size=16 align=8
+ base size=16 base align=8
+Phonon::AbstractVideoOutput (0x7f37b9437b60) 0
+ vptr=((& Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE) + 16u)
+ Phonon::MediaNode (0x7f37b9437bd0) 0
+ primary-for Phonon::AbstractVideoOutput (0x7f37b9437b60)
+
+Vtable for Phonon::AddonInterface
+Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE: 6u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon14AddonInterfaceE)
+16 Phonon::AddonInterface::~AddonInterface
+24 Phonon::AddonInterface::~AddonInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+
+Class Phonon::AddonInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::AddonInterface (0x7f37b9442230) 0 nearly-empty
+ vptr=((& Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE) + 16u)
+
+Vtable for Phonon::AudioOutput
+Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+16 Phonon::AudioOutput::metaObject
+24 Phonon::AudioOutput::qt_metacast
+32 Phonon::AudioOutput::qt_metacall
+40 Phonon::AudioOutput::~AudioOutput
+48 Phonon::AudioOutput::~AudioOutput
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+128 Phonon::AudioOutput::_ZThn16_N6Phonon11AudioOutputD1Ev
+136 Phonon::AudioOutput::_ZThn16_N6Phonon11AudioOutputD0Ev
+
+Class Phonon::AudioOutput
+ size=32 align=8
+ base size=32 base align=8
+Phonon::AudioOutput (0x7f37b945d620) 0
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 16u)
+ Phonon::AbstractAudioOutput (0x7f37b9456f00) 0
+ primary-for Phonon::AudioOutput (0x7f37b945d620)
+ QObject (0x7f37b945d690) 0
+ primary-for Phonon::AbstractAudioOutput (0x7f37b9456f00)
+ Phonon::MediaNode (0x7f37b945d700) 16
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 128u)
+
+Vtable for Phonon::AudioOutputInterface40
+Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E: 8u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface40E)
+16 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+24 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface40
+ size=8 align=8
+ base size=8 base align=8
+Phonon::AudioOutputInterface40 (0x7f37b9254b60) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E) + 16u)
+
+Vtable for Phonon::AudioOutputInterface42
+Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E: 9u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface42E)
+16 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+24 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface42
+ size=8 align=8
+ base size=8 base align=8
+Phonon::AudioOutputInterface42 (0x7f37b925e540) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E) + 16u)
+ Phonon::AudioOutputInterface40 (0x7f37b925e5b0) 0 nearly-empty
+ primary-for Phonon::AudioOutputInterface42 (0x7f37b925e540)
+
+Vtable for Phonon::BackendCapabilities::Notifier
+Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE: 14u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon19BackendCapabilities8NotifierE)
+16 Phonon::BackendCapabilities::Notifier::metaObject
+24 Phonon::BackendCapabilities::Notifier::qt_metacast
+32 Phonon::BackendCapabilities::Notifier::qt_metacall
+40 Phonon::BackendCapabilities::Notifier::~Notifier
+48 Phonon::BackendCapabilities::Notifier::~Notifier
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+
+Class Phonon::BackendCapabilities::Notifier
+ size=16 align=8
+ base size=16 base align=8
+Phonon::BackendCapabilities::Notifier (0x7f37b926f7e0) 0
+ vptr=((& Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE) + 16u)
+ QObject (0x7f37b926f850) 0
+ primary-for Phonon::BackendCapabilities::Notifier (0x7f37b926f7e0)
+
+Vtable for Phonon::BackendInterface
+Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE: 12u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon16BackendInterfaceE)
+16 Phonon::BackendInterface::~BackendInterface
+24 Phonon::BackendInterface::~BackendInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+
+Class Phonon::BackendInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::BackendInterface (0x7f37b927f540) 0 nearly-empty
+ vptr=((& Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE) + 16u)
+
+Vtable for Phonon::Effect
+Phonon::Effect::_ZTVN6Phonon6EffectE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+16 Phonon::Effect::metaObject
+24 Phonon::Effect::qt_metacast
+32 Phonon::Effect::qt_metacall
+40 Phonon::Effect::~Effect
+48 Phonon::Effect::~Effect
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+128 Phonon::Effect::_ZThn16_N6Phonon6EffectD1Ev
+136 Phonon::Effect::_ZThn16_N6Phonon6EffectD0Ev
+
+Class Phonon::Effect
+ size=32 align=8
+ base size=32 base align=8
+Phonon::Effect (0x7f37b9291c00) 0
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 16u)
+ QObject (0x7f37b9292930) 0
+ primary-for Phonon::Effect (0x7f37b9291c00)
+ Phonon::MediaNode (0x7f37b92929a0) 16
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 128u)
+
+Vtable for Phonon::EffectInterface
+Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon15EffectInterfaceE)
+16 Phonon::EffectInterface::~EffectInterface
+24 Phonon::EffectInterface::~EffectInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+
+Class Phonon::EffectInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::EffectInterface (0x7f37b92a5e00) 0 nearly-empty
+ vptr=((& Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE) + 16u)
+
+Class Phonon::EffectParameter
+ size=8 align=8
+ base size=8 base align=8
+Phonon::EffectParameter (0x7f37b92bd070) 0
+
+Class QMargins
+ size=16 align=4
+ base size=16 base align=4
+QMargins (0x7f37b92ecc40) 0
+
+Class QSize
+ size=8 align=4
+ base size=8 base align=4
+QSize (0x7f37b9318690) 0
+
+Class QSizeF
+ size=16 align=8
+ base size=16 base align=8
+QSizeF (0x7f37b9164380) 0
+
+Class QPoint
+ size=8 align=4
+ base size=8 base align=4
+QPoint (0x7f37b91ad8c0) 0
+
+Class QPointF
+ size=16 align=8
+ base size=16 base align=8
+QPointF (0x7f37b91e6540) 0
+
+Class QRect
+ size=16 align=4
+ base size=16 base align=4
+QRect (0x7f37b9225540) 0
+
+Class QRectF
+ size=32 align=8
+ base size=32 base align=8
+QRectF (0x7f37b90d2ee0) 0
+
+Vtable for QPaintDevice
+QPaintDevice::_ZTV12QPaintDevice: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI12QPaintDevice)
+16 QPaintDevice::~QPaintDevice
+24 QPaintDevice::~QPaintDevice
+32 QPaintDevice::devType
+40 __cxa_pure_virtual
+48 QPaintDevice::metric
+
+Class QPaintDevice
+ size=16 align=8
+ base size=10 base align=8
+QPaintDevice (0x7f37b8f7dd20) 0
+ vptr=((& QPaintDevice::_ZTV12QPaintDevice) + 16u)
+
+Class QRegExp
+ size=8 align=8
+ base size=8 base align=8
+QRegExp (0x7f37b8fb1620) 0
+
+Class QStringMatcher::Data
+ size=272 align=8
+ base size=272 base align=8
+QStringMatcher::Data (0x7f37b8fe1a10) 0
+
+Class QStringMatcher
+ size=1048 align=8
+ base size=1048 base align=8
+QStringMatcher (0x7f37b8fe13f0) 0
+
+Class QStringList
+ size=8 align=8
+ base size=8 base align=8
+QStringList (0x7f37b9016000) 0
+ QList<QString> (0x7f37b9016070) 0
+
+Class QColor
+ size=16 align=4
+ base size=14 base align=4
+QColor (0x7f37b8e84c40) 0
+
+Class QPolygon
+ size=8 align=8
+ base size=8 base align=8
+QPolygon (0x7f37b8ee5460) 0
+ QVector<QPoint> (0x7f37b8ee54d0) 0
+
+Class QPolygonF
+ size=8 align=8
+ base size=8 base align=8
+QPolygonF (0x7f37b8f289a0) 0
+ QVector<QPointF> (0x7f37b8f28a10) 0
+
+Class QRegion::QRegionData
+ size=32 align=8
+ base size=32 base align=8
+QRegion::QRegionData (0x7f37b8d84380) 0
+
+Class QRegion
+ size=8 align=8
+ base size=8 base align=8
+QRegion (0x7f37b8d64af0) 0
+
+Class QLine
+ size=16 align=4
+ base size=16 base align=4
+QLine (0x7f37b8d96c40) 0
+
+Class QLineF
+ size=32 align=8
+ base size=32 base align=8
+QLineF (0x7f37b8dd4af0) 0
+
+Class QMatrix
+ size=48 align=8
+ base size=48 base align=8
+QMatrix (0x7f37b8e305b0) 0
+
+Class QPainterPath::Element
+ size=24 align=8
+ base size=24 base align=8
+QPainterPath::Element (0x7f37b8c37700) 0
+
+Class QPainterPath
+ size=8 align=8
+ base size=8 base align=8
+QPainterPath (0x7f37b8c37690) 0
+
+Class QPainterPathPrivate
+ size=16 align=8
+ base size=16 base align=8
+QPainterPathPrivate (0x7f37b8c86e00) 0
+
+Class QPainterPathStroker
+ size=8 align=8
+ base size=8 base align=8
+QPainterPathStroker (0x7f37b8c8f930) 0
+
+Class QTransform
+ size=88 align=8
+ base size=88 base align=8
+QTransform (0x7f37b8cfc930) 0
+
+Class QImageTextKeyLang
+ size=16 align=8
+ base size=16 base align=8
+QImageTextKeyLang (0x7f37b8b9df50) 0
+
+Vtable for QImage
+QImage::_ZTV6QImage: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI6QImage)
+16 QImage::~QImage
+24 QImage::~QImage
+32 QImage::devType
+40 QImage::paintEngine
+48 QImage::metric
+
+Class QImage
+ size=24 align=8
+ base size=24 base align=8
+QImage (0x7f37b8bd07e0) 0
+ vptr=((& QImage::_ZTV6QImage) + 16u)
+ QPaintDevice (0x7f37b8bd0850) 0
+ primary-for QImage (0x7f37b8bd07e0)
+
+Vtable for QtSharedPointer::ExternalRefCountData
+QtSharedPointer::ExternalRefCountData::_ZTVN15QtSharedPointer20ExternalRefCountDataE: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN15QtSharedPointer20ExternalRefCountDataE)
+16 QtSharedPointer::ExternalRefCountData::~ExternalRefCountData
+24 QtSharedPointer::ExternalRefCountData::~ExternalRefCountData
+32 QtSharedPointer::ExternalRefCountData::destroy
+
+Class QtSharedPointer::ExternalRefCountData
+ size=16 align=8
+ base size=16 base align=8
+QtSharedPointer::ExternalRefCountData (0x7f37b8a807e0) 0
+ vptr=((& QtSharedPointer::ExternalRefCountData::_ZTVN15QtSharedPointer20ExternalRefCountDataE) + 16u)
+
+Vtable for QtSharedPointer::ExternalRefCountWithDestroyFn
+QtSharedPointer::ExternalRefCountWithDestroyFn::_ZTVN15QtSharedPointer29ExternalRefCountWithDestroyFnE: 5u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN15QtSharedPointer29ExternalRefCountWithDestroyFnE)
+16 QtSharedPointer::ExternalRefCountWithDestroyFn::~ExternalRefCountWithDestroyFn
+24 QtSharedPointer::ExternalRefCountWithDestroyFn::~ExternalRefCountWithDestroyFn
+32 QtSharedPointer::ExternalRefCountWithDestroyFn::destroy
+
+Class QtSharedPointer::ExternalRefCountWithDestroyFn
+ size=24 align=8
+ base size=24 base align=8
+QtSharedPointer::ExternalRefCountWithDestroyFn (0x7f37b8aab0e0) 0
+ vptr=((& QtSharedPointer::ExternalRefCountWithDestroyFn::_ZTVN15QtSharedPointer29ExternalRefCountWithDestroyFnE) + 16u)
+ QtSharedPointer::ExternalRefCountData (0x7f37b8aab150) 0
+ primary-for QtSharedPointer::ExternalRefCountWithDestroyFn (0x7f37b8aab0e0)
+
+Vtable for QPixmap
+QPixmap::_ZTV7QPixmap: 7u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QPixmap)
+16 QPixmap::~QPixmap
+24 QPixmap::~QPixmap
+32 QPixmap::devType
+40 QPixmap::paintEngine
+48 QPixmap::metric
+
+Class QPixmap
+ size=24 align=8
+ base size=24 base align=8
+QPixmap (0x7f37b8921d20) 0
+ vptr=((& QPixmap::_ZTV7QPixmap) + 16u)
+ QPaintDevice (0x7f37b8921d90) 0
+ primary-for QPixmap (0x7f37b8921d20)
+
+Class QBrush
+ size=8 align=8
+ base size=8 base align=8
+QBrush (0x7f37b89a3070) 0
+
+Class QBrushData
+ size=112 align=8
+ base size=112 base align=8
+QBrushData (0x7f37b89c1a80) 0
+
+Class QGradient
+ size=64 align=8
+ base size=64 base align=8
+QGradient (0x7f37b89cfc40) 0
+
+Class QLinearGradient
+ size=64 align=8
+ base size=64 base align=8
+QLinearGradient (0x7f37b8810700) 0
+ QGradient (0x7f37b8810770) 0
+
+Class QRadialGradient
+ size=64 align=8
+ base size=64 base align=8
+QRadialGradient (0x7f37b8810bd0) 0
+ QGradient (0x7f37b8810c40) 0
+
+Class QConicalGradient
+ size=64 align=8
+ base size=64 base align=8
+QConicalGradient (0x7f37b88221c0) 0
+ QGradient (0x7f37b8822230) 0
+
+Class QPalette
+ size=16 align=8
+ base size=12 base align=8
+QPalette (0x7f37b8822540) 0
+
+Class QColorGroup
+ size=16 align=8
+ base size=12 base align=8
+QColorGroup (0x7f37b886ee70) 0
+ QPalette (0x7f37b886eee0) 0
+
+Class QFont
+ size=16 align=8
+ base size=12 base align=8
+QFont (0x7f37b88b11c0) 0
+
+Class QFontMetrics
+ size=8 align=8
+ base size=8 base align=8
+QFontMetrics (0x7f37b88f2e70) 0
+
+Class QFontMetricsF
+ size=8 align=8
+ base size=8 base align=8
+QFontMetricsF (0x7f37b8710310) 0
+
+Class QFontInfo
+ size=8 align=8
+ base size=8 base align=8
+QFontInfo (0x7f37b8722230) 0
+
+Class QSizePolicy
+ size=4 align=4
+ base size=4 base align=4
+QSizePolicy (0x7f37b8722d20) 0
+
+Class QCursor
+ size=8 align=8
+ base size=8 base align=8
+QCursor (0x7f37b87dad20) 0
+
+Class QKeySequence
+ size=8 align=8
+ base size=8 base align=8
+QKeySequence (0x7f37b87e1540) 0
+
+Class QWidgetData
+ size=88 align=8
+ base size=88 base align=8
+QWidgetData (0x7f37b8801e70) 0
+
+Vtable for QWidget
+QWidget::_ZTV7QWidget: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI7QWidget)
+16 QWidget::metaObject
+24 QWidget::qt_metacast
+32 QWidget::qt_metacall
+40 QWidget::~QWidget
+48 QWidget::~QWidget
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTI7QWidget)
+464 QWidget::_ZThn16_N7QWidgetD1Ev
+472 QWidget::_ZThn16_N7QWidgetD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class QWidget
+ size=40 align=8
+ base size=40 base align=8
+QWidget (0x7f37b8611f00) 0
+ vptr=((& QWidget::_ZTV7QWidget) + 16u)
+ QObject (0x7f37b8801ee0) 0
+ primary-for QWidget (0x7f37b8611f00)
+ QPaintDevice (0x7f37b8801f50) 16
+ vptr=((& QWidget::_ZTV7QWidget) + 464u)
+
+Vtable for Phonon::EffectWidget
+Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+16 Phonon::EffectWidget::metaObject
+24 Phonon::EffectWidget::qt_metacast
+32 Phonon::EffectWidget::qt_metacall
+40 Phonon::EffectWidget::~EffectWidget
+48 Phonon::EffectWidget::~EffectWidget
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+464 Phonon::EffectWidget::_ZThn16_N6Phonon12EffectWidgetD1Ev
+472 Phonon::EffectWidget::_ZThn16_N6Phonon12EffectWidgetD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::EffectWidget
+ size=48 align=8
+ base size=48 base align=8
+Phonon::EffectWidget (0x7f37b8581f50) 0
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 16u)
+ QWidget (0x7f37b8583b80) 0
+ primary-for Phonon::EffectWidget (0x7f37b8581f50)
+ QObject (0x7f37b858b000) 0
+ primary-for QWidget (0x7f37b8583b80)
+ QPaintDevice (0x7f37b858b070) 16
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 464u)
+
+Vtable for Phonon::MediaController
+Phonon::MediaController::_ZTVN6Phonon15MediaControllerE: 14u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon15MediaControllerE)
+16 Phonon::MediaController::metaObject
+24 Phonon::MediaController::qt_metacast
+32 Phonon::MediaController::qt_metacall
+40 Phonon::MediaController::~MediaController
+48 Phonon::MediaController::~MediaController
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+
+Class Phonon::MediaController
+ size=24 align=8
+ base size=24 base align=8
+Phonon::MediaController (0x7f37b85a0310) 0
+ vptr=((& Phonon::MediaController::_ZTVN6Phonon15MediaControllerE) + 16u)
+ QObject (0x7f37b85a0380) 0
+ primary-for Phonon::MediaController (0x7f37b85a0310)
+
+Class Phonon::MediaSource
+ size=8 align=8
+ base size=8 base align=8
+Phonon::MediaSource (0x7f37b85e1230) 0
+
+Vtable for Phonon::MediaObject
+Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+16 Phonon::MediaObject::metaObject
+24 Phonon::MediaObject::qt_metacast
+32 Phonon::MediaObject::qt_metacall
+40 Phonon::MediaObject::~MediaObject
+48 Phonon::MediaObject::~MediaObject
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+128 Phonon::MediaObject::_ZThn16_N6Phonon11MediaObjectD1Ev
+136 Phonon::MediaObject::_ZThn16_N6Phonon11MediaObjectD0Ev
+
+Class Phonon::MediaObject
+ size=32 align=8
+ base size=32 base align=8
+Phonon::MediaObject (0x7f37b85df600) 0
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 16u)
+ QObject (0x7f37b85e1d90) 0
+ primary-for Phonon::MediaObject (0x7f37b85df600)
+ Phonon::MediaNode (0x7f37b85e1e00) 16
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 128u)
+
+Vtable for Phonon::MediaObjectInterface
+Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE: 25u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon20MediaObjectInterfaceE)
+16 Phonon::MediaObjectInterface::~MediaObjectInterface
+24 Phonon::MediaObjectInterface::~MediaObjectInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+96 __cxa_pure_virtual
+104 __cxa_pure_virtual
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 __cxa_pure_virtual
+136 __cxa_pure_virtual
+144 __cxa_pure_virtual
+152 __cxa_pure_virtual
+160 Phonon::MediaObjectInterface::remainingTime
+168 __cxa_pure_virtual
+176 __cxa_pure_virtual
+184 __cxa_pure_virtual
+192 __cxa_pure_virtual
+
+Class Phonon::MediaObjectInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::MediaObjectInterface (0x7f37b8419310) 0 nearly-empty
+ vptr=((& Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE) + 16u)
+
+Class QModelIndex
+ size=24 align=8
+ base size=24 base align=8
+QModelIndex (0x7f37b842ab60) 0
+
+Class QPersistentModelIndex
+ size=8 align=8
+ base size=8 base align=8
+QPersistentModelIndex (0x7f37b845a620) 0
+
+Vtable for QAbstractItemModel
+QAbstractItemModel::_ZTV18QAbstractItemModel: 42u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractItemModel)
+16 QAbstractItemModel::metaObject
+24 QAbstractItemModel::qt_metacast
+32 QAbstractItemModel::qt_metacall
+40 QAbstractItemModel::~QAbstractItemModel
+48 QAbstractItemModel::~QAbstractItemModel
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 __cxa_pure_virtual
+136 __cxa_pure_virtual
+144 QAbstractItemModel::hasChildren
+152 __cxa_pure_virtual
+160 QAbstractItemModel::setData
+168 QAbstractItemModel::headerData
+176 QAbstractItemModel::setHeaderData
+184 QAbstractItemModel::itemData
+192 QAbstractItemModel::setItemData
+200 QAbstractItemModel::mimeTypes
+208 QAbstractItemModel::mimeData
+216 QAbstractItemModel::dropMimeData
+224 QAbstractItemModel::supportedDropActions
+232 QAbstractItemModel::insertRows
+240 QAbstractItemModel::insertColumns
+248 QAbstractItemModel::removeRows
+256 QAbstractItemModel::removeColumns
+264 QAbstractItemModel::fetchMore
+272 QAbstractItemModel::canFetchMore
+280 QAbstractItemModel::flags
+288 QAbstractItemModel::sort
+296 QAbstractItemModel::buddy
+304 QAbstractItemModel::match
+312 QAbstractItemModel::span
+320 QAbstractItemModel::submit
+328 QAbstractItemModel::revert
+
+Class QAbstractItemModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractItemModel (0x7f37b8464930) 0
+ vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 16u)
+ QObject (0x7f37b84649a0) 0
+ primary-for QAbstractItemModel (0x7f37b8464930)
+
+Vtable for QAbstractTableModel
+QAbstractTableModel::_ZTV19QAbstractTableModel: 42u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI19QAbstractTableModel)
+16 QAbstractTableModel::metaObject
+24 QAbstractTableModel::qt_metacast
+32 QAbstractTableModel::qt_metacall
+40 QAbstractTableModel::~QAbstractTableModel
+48 QAbstractTableModel::~QAbstractTableModel
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QAbstractTableModel::index
+120 QAbstractTableModel::parent
+128 __cxa_pure_virtual
+136 __cxa_pure_virtual
+144 QAbstractTableModel::hasChildren
+152 __cxa_pure_virtual
+160 QAbstractItemModel::setData
+168 QAbstractItemModel::headerData
+176 QAbstractItemModel::setHeaderData
+184 QAbstractItemModel::itemData
+192 QAbstractItemModel::setItemData
+200 QAbstractItemModel::mimeTypes
+208 QAbstractItemModel::mimeData
+216 QAbstractTableModel::dropMimeData
+224 QAbstractItemModel::supportedDropActions
+232 QAbstractItemModel::insertRows
+240 QAbstractItemModel::insertColumns
+248 QAbstractItemModel::removeRows
+256 QAbstractItemModel::removeColumns
+264 QAbstractItemModel::fetchMore
+272 QAbstractItemModel::canFetchMore
+280 QAbstractItemModel::flags
+288 QAbstractItemModel::sort
+296 QAbstractItemModel::buddy
+304 QAbstractItemModel::match
+312 QAbstractItemModel::span
+320 QAbstractItemModel::submit
+328 QAbstractItemModel::revert
+
+Class QAbstractTableModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractTableModel (0x7f37b84bdc40) 0
+ vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 16u)
+ QAbstractItemModel (0x7f37b84bdcb0) 0
+ primary-for QAbstractTableModel (0x7f37b84bdc40)
+ QObject (0x7f37b84bdd20) 0
+ primary-for QAbstractItemModel (0x7f37b84bdcb0)
+
+Vtable for QAbstractListModel
+QAbstractListModel::_ZTV18QAbstractListModel: 42u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTI18QAbstractListModel)
+16 QAbstractListModel::metaObject
+24 QAbstractListModel::qt_metacast
+32 QAbstractListModel::qt_metacall
+40 QAbstractListModel::~QAbstractListModel
+48 QAbstractListModel::~QAbstractListModel
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QAbstractListModel::index
+120 QAbstractListModel::parent
+128 __cxa_pure_virtual
+136 QAbstractListModel::columnCount
+144 QAbstractListModel::hasChildren
+152 __cxa_pure_virtual
+160 QAbstractItemModel::setData
+168 QAbstractItemModel::headerData
+176 QAbstractItemModel::setHeaderData
+184 QAbstractItemModel::itemData
+192 QAbstractItemModel::setItemData
+200 QAbstractItemModel::mimeTypes
+208 QAbstractItemModel::mimeData
+216 QAbstractListModel::dropMimeData
+224 QAbstractItemModel::supportedDropActions
+232 QAbstractItemModel::insertRows
+240 QAbstractItemModel::insertColumns
+248 QAbstractItemModel::removeRows
+256 QAbstractItemModel::removeColumns
+264 QAbstractItemModel::fetchMore
+272 QAbstractItemModel::canFetchMore
+280 QAbstractItemModel::flags
+288 QAbstractItemModel::sort
+296 QAbstractItemModel::buddy
+304 QAbstractItemModel::match
+312 QAbstractItemModel::span
+320 QAbstractItemModel::submit
+328 QAbstractItemModel::revert
+
+Class QAbstractListModel
+ size=16 align=8
+ base size=16 base align=8
+QAbstractListModel (0x7f37b84d91c0) 0
+ vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 16u)
+ QAbstractItemModel (0x7f37b84d9230) 0
+ primary-for QAbstractListModel (0x7f37b84d91c0)
+ QObject (0x7f37b84d92a0) 0
+ primary-for QAbstractItemModel (0x7f37b84d9230)
+
+Class Phonon::ObjectDescriptionModelData
+ size=8 align=8
+ base size=8 base align=8
+Phonon::ObjectDescriptionModelData (0x7f37b830c310) 0
+
+Vtable for Phonon::PlatformPlugin
+Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE: 16u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon14PlatformPluginE)
+16 Phonon::PlatformPlugin::~PlatformPlugin
+24 Phonon::PlatformPlugin::~PlatformPlugin
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+96 __cxa_pure_virtual
+104 __cxa_pure_virtual
+112 __cxa_pure_virtual
+120 Phonon::PlatformPlugin::deviceAccessListFor
+
+Class Phonon::PlatformPlugin
+ size=8 align=8
+ base size=8 base align=8
+Phonon::PlatformPlugin (0x7f37b83762a0) 0 nearly-empty
+ vptr=((& Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE) + 16u)
+
+Vtable for Phonon::SeekSlider
+Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+16 Phonon::SeekSlider::metaObject
+24 Phonon::SeekSlider::qt_metacast
+32 Phonon::SeekSlider::qt_metacall
+40 Phonon::SeekSlider::~SeekSlider
+48 Phonon::SeekSlider::~SeekSlider
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+464 Phonon::SeekSlider::_ZThn16_N6Phonon10SeekSliderD1Ev
+472 Phonon::SeekSlider::_ZThn16_N6Phonon10SeekSliderD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::SeekSlider
+ size=48 align=8
+ base size=48 base align=8
+Phonon::SeekSlider (0x7f37b83ad8c0) 0
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 16u)
+ QWidget (0x7f37b8388e00) 0
+ primary-for Phonon::SeekSlider (0x7f37b83ad8c0)
+ QObject (0x7f37b83ad930) 0
+ primary-for QWidget (0x7f37b8388e00)
+ QPaintDevice (0x7f37b83ad9a0) 16
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 464u)
+
+Vtable for Phonon::StreamInterface
+Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE: 8u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon15StreamInterfaceE)
+16 Phonon::StreamInterface::~StreamInterface
+24 Phonon::StreamInterface::~StreamInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+
+Class Phonon::StreamInterface
+ size=16 align=8
+ base size=16 base align=8
+Phonon::StreamInterface (0x7f37b83c9d90) 0
+ vptr=((& Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE) + 16u)
+
+Vtable for Phonon::VideoPlayer
+Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+16 Phonon::VideoPlayer::metaObject
+24 Phonon::VideoPlayer::qt_metacast
+32 Phonon::VideoPlayer::qt_metacall
+40 Phonon::VideoPlayer::~VideoPlayer
+48 Phonon::VideoPlayer::~VideoPlayer
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+464 Phonon::VideoPlayer::_ZThn16_N6Phonon11VideoPlayerD1Ev
+472 Phonon::VideoPlayer::_ZThn16_N6Phonon11VideoPlayerD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VideoPlayer
+ size=48 align=8
+ base size=48 base align=8
+Phonon::VideoPlayer (0x7f37b83d87e0) 0
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 16u)
+ QWidget (0x7f37b83dd080) 0
+ primary-for Phonon::VideoPlayer (0x7f37b83d87e0)
+ QObject (0x7f37b83d8850) 0
+ primary-for QWidget (0x7f37b83dd080)
+ QPaintDevice (0x7f37b83d88c0) 16
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 464u)
+
+Vtable for Phonon::VideoWidget
+Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE: 67u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+16 Phonon::VideoWidget::metaObject
+24 Phonon::VideoWidget::qt_metacast
+32 Phonon::VideoWidget::qt_metacall
+40 Phonon::VideoWidget::~VideoWidget
+48 Phonon::VideoWidget::~VideoWidget
+56 Phonon::VideoWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 Phonon::VideoWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+464 Phonon::VideoWidget::_ZThn16_N6Phonon11VideoWidgetD1Ev
+472 Phonon::VideoWidget::_ZThn16_N6Phonon11VideoWidgetD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+504 (int (*)(...))-0x00000000000000028
+512 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+520 Phonon::VideoWidget::_ZThn40_N6Phonon11VideoWidgetD1Ev
+528 Phonon::VideoWidget::_ZThn40_N6Phonon11VideoWidgetD0Ev
+
+Class Phonon::VideoWidget
+ size=56 align=8
+ base size=56 base align=8
+Phonon::VideoWidget (0x7f37b83dd780) 0
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 16u)
+ QWidget (0x7f37b83dd800) 0
+ primary-for Phonon::VideoWidget (0x7f37b83dd780)
+ QObject (0x7f37b81f0850) 0
+ primary-for QWidget (0x7f37b83dd800)
+ QPaintDevice (0x7f37b81f08c0) 16
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 464u)
+ Phonon::AbstractVideoOutput (0x7f37b81f0930) 40
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 520u)
+ Phonon::MediaNode (0x7f37b81f09a0) 40
+ primary-for Phonon::AbstractVideoOutput (0x7f37b81f0930)
+
+Vtable for Phonon::VideoWidgetInterface
+Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE: 17u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon20VideoWidgetInterfaceE)
+16 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+24 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+32 __cxa_pure_virtual
+40 __cxa_pure_virtual
+48 __cxa_pure_virtual
+56 __cxa_pure_virtual
+64 __cxa_pure_virtual
+72 __cxa_pure_virtual
+80 __cxa_pure_virtual
+88 __cxa_pure_virtual
+96 __cxa_pure_virtual
+104 __cxa_pure_virtual
+112 __cxa_pure_virtual
+120 __cxa_pure_virtual
+128 __cxa_pure_virtual
+
+Class Phonon::VideoWidgetInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::VideoWidgetInterface (0x7f37b8216230) 0 nearly-empty
+ vptr=((& Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE) + 16u)
+
+Vtable for Phonon::VolumeFaderEffect
+Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE: 18u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+16 Phonon::VolumeFaderEffect::metaObject
+24 Phonon::VolumeFaderEffect::qt_metacast
+32 Phonon::VolumeFaderEffect::qt_metacall
+40 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+48 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+56 QObject::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 (int (*)(...))-0x00000000000000010
+120 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+128 Phonon::VolumeFaderEffect::_ZThn16_N6Phonon17VolumeFaderEffectD1Ev
+136 Phonon::VolumeFaderEffect::_ZThn16_N6Phonon17VolumeFaderEffectD0Ev
+
+Class Phonon::VolumeFaderEffect
+ size=32 align=8
+ base size=32 base align=8
+Phonon::VolumeFaderEffect (0x7f37b8225850) 0
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 16u)
+ Phonon::Effect (0x7f37b8223c80) 0
+ primary-for Phonon::VolumeFaderEffect (0x7f37b8225850)
+ QObject (0x7f37b82258c0) 0
+ primary-for Phonon::Effect (0x7f37b8223c80)
+ Phonon::MediaNode (0x7f37b8225930) 16
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 128u)
+
+Vtable for Phonon::VolumeFaderInterface
+Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE: 9u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon20VolumeFaderInterfaceE)
+16 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+24 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+32 Phonon::VolumeFaderInterface::volume
+40 Phonon::VolumeFaderInterface::setVolume
+48 Phonon::VolumeFaderInterface::fadeCurve
+56 Phonon::VolumeFaderInterface::setFadeCurve
+64 Phonon::VolumeFaderInterface::fadeTo
+
+Class Phonon::VolumeFaderInterface
+ size=8 align=8
+ base size=8 base align=8
+Phonon::VolumeFaderInterface (0x7f37b823ae70) 0 nearly-empty
+ vptr=((& Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE) + 16u)
+
+Vtable for Phonon::VolumeSlider
+Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE: 63u entries
+0 (int (*)(...))0
+8 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+16 Phonon::VolumeSlider::metaObject
+24 Phonon::VolumeSlider::qt_metacast
+32 Phonon::VolumeSlider::qt_metacall
+40 Phonon::VolumeSlider::~VolumeSlider
+48 Phonon::VolumeSlider::~VolumeSlider
+56 QWidget::event
+64 QObject::eventFilter
+72 QObject::timerEvent
+80 QObject::childEvent
+88 QObject::customEvent
+96 QObject::connectNotify
+104 QObject::disconnectNotify
+112 QWidget::devType
+120 QWidget::setVisible
+128 QWidget::sizeHint
+136 QWidget::minimumSizeHint
+144 QWidget::heightForWidth
+152 QWidget::paintEngine
+160 QWidget::mousePressEvent
+168 QWidget::mouseReleaseEvent
+176 QWidget::mouseDoubleClickEvent
+184 QWidget::mouseMoveEvent
+192 QWidget::wheelEvent
+200 QWidget::keyPressEvent
+208 QWidget::keyReleaseEvent
+216 QWidget::focusInEvent
+224 QWidget::focusOutEvent
+232 QWidget::enterEvent
+240 QWidget::leaveEvent
+248 QWidget::paintEvent
+256 QWidget::moveEvent
+264 QWidget::resizeEvent
+272 QWidget::closeEvent
+280 QWidget::contextMenuEvent
+288 QWidget::tabletEvent
+296 QWidget::actionEvent
+304 QWidget::dragEnterEvent
+312 QWidget::dragMoveEvent
+320 QWidget::dragLeaveEvent
+328 QWidget::dropEvent
+336 QWidget::showEvent
+344 QWidget::hideEvent
+352 QWidget::x11Event
+360 QWidget::changeEvent
+368 QWidget::metric
+376 QWidget::inputMethodEvent
+384 QWidget::inputMethodQuery
+392 QWidget::focusNextPrevChild
+400 QWidget::styleChange
+408 QWidget::enabledChange
+416 QWidget::paletteChange
+424 QWidget::fontChange
+432 QWidget::windowActivationChange
+440 QWidget::languageChange
+448 (int (*)(...))-0x00000000000000010
+456 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+464 Phonon::VolumeSlider::_ZThn16_N6Phonon12VolumeSliderD1Ev
+472 Phonon::VolumeSlider::_ZThn16_N6Phonon12VolumeSliderD0Ev
+480 QWidget::_ZThn16_NK7QWidget7devTypeEv
+488 QWidget::_ZThn16_NK7QWidget11paintEngineEv
+496 QWidget::_ZThn16_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VolumeSlider
+ size=48 align=8
+ base size=48 base align=8
+Phonon::VolumeSlider (0x7f37b824f930) 0
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 16u)
+ QWidget (0x7f37b8254500) 0
+ primary-for Phonon::VolumeSlider (0x7f37b824f930)
+ QObject (0x7f37b824f9a0) 0
+ primary-for QWidget (0x7f37b8254500)
+ QPaintDevice (0x7f37b824fa10) 16
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 464u)
+
diff --git a/tests/auto/bic/data/phonon.4.6.0.linux-gcc-ia32.txt b/tests/auto/bic/data/phonon.4.6.0.linux-gcc-ia32.txt
new file mode 100644
index 0000000..7255636
--- /dev/null
+++ b/tests/auto/bic/data/phonon.4.6.0.linux-gcc-ia32.txt
@@ -0,0 +1,1980 @@
+Class QSysInfo
+ size=1 align=1
+ base size=0 base align=1
+QSysInfo (0xb6f30ec4) 0 empty
+
+Class QBool
+ size=1 align=1
+ base size=1 base align=1
+QBool (0xb6e12078) 0
+
+Class qIsNull(double)::U
+ size=8 align=4
+ base size=8 base align=4
+qIsNull(double)::U (0xb6e12744) 0
+
+Class qIsNull(float)::U
+ size=4 align=4
+ base size=4 base align=4
+qIsNull(float)::U (0xb6e127f8) 0
+
+Class QFlag
+ size=4 align=4
+ base size=4 base align=4
+QFlag (0xb6e4303c) 0
+
+Class QIncompatibleFlag
+ size=4 align=4
+ base size=4 base align=4
+QIncompatibleFlag (0xb6e43168) 0
+
+Class QBasicAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QBasicAtomicInt (0xb6e433c0) 0
+
+Class QAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QAtomicInt (0xb69763c0) 0
+ QBasicAtomicInt (0xb6e43ac8) 0
+
+Class QSharedData
+ size=4 align=4
+ base size=4 base align=4
+QSharedData (0xb6e43fb4) 0
+
+Class QLatin1Char
+ size=1 align=1
+ base size=1 base align=1
+QLatin1Char (0xb6989348) 0
+
+Class QChar
+ size=2 align=2
+ base size=2 base align=2
+QChar (0xb6989528) 0
+
+Vtable for std::exception
+std::exception::_ZTVSt9exception: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt9exception)
+8 std::exception::~exception
+12 std::exception::~exception
+16 std::exception::what
+
+Class std::exception
+ size=4 align=4
+ base size=4 base align=4
+std::exception (0xb6a05c6c) 0 nearly-empty
+ vptr=((& std::exception::_ZTVSt9exception) + 8u)
+
+Vtable for std::bad_exception
+std::bad_exception::_ZTVSt13bad_exception: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt13bad_exception)
+8 std::bad_exception::~bad_exception
+12 std::bad_exception::~bad_exception
+16 std::bad_exception::what
+
+Class std::bad_exception
+ size=4 align=4
+ base size=4 base align=4
+std::bad_exception (0xb6a04b00) 0 nearly-empty
+ vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 8u)
+ std::exception (0xb6a05d5c) 0 nearly-empty
+ primary-for std::bad_exception (0xb6a04b00)
+
+Vtable for std::bad_alloc
+std::bad_alloc::_ZTVSt9bad_alloc: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt9bad_alloc)
+8 std::bad_alloc::~bad_alloc
+12 std::bad_alloc::~bad_alloc
+16 std::bad_alloc::what
+
+Class std::bad_alloc
+ size=4 align=4
+ base size=4 base align=4
+std::bad_alloc (0xb6a04c80) 0 nearly-empty
+ vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 8u)
+ std::exception (0xb6a05fb4) 0 nearly-empty
+ primary-for std::bad_alloc (0xb6a04c80)
+
+Class std::nothrow_t
+ size=1 align=1
+ base size=0 base align=1
+std::nothrow_t (0xb6a1b21c) 0 empty
+
+Class __locale_struct
+ size=116 align=4
+ base size=116 base align=4
+__locale_struct (0xb6a1b2d0) 0
+
+Class QListData::Data
+ size=24 align=4
+ base size=24 base align=4
+QListData::Data (0xb6a1b348) 0
+
+Class QListData
+ size=4 align=4
+ base size=4 base align=4
+QListData (0xb6a1b30c) 0
+
+Class QScopedPointerPodDeleter
+ size=1 align=1
+ base size=0 base align=1
+QScopedPointerPodDeleter (0xb6a1bb7c) 0 empty
+
+Class QInternal
+ size=1 align=1
+ base size=0 base align=1
+QInternal (0xb6763b40) 0 empty
+
+Class QGenericArgument
+ size=8 align=4
+ base size=8 base align=4
+QGenericArgument (0xb6763b7c) 0
+
+Class QGenericReturnArgument
+ size=8 align=4
+ base size=8 base align=4
+QGenericReturnArgument (0xb67c1940) 0
+ QGenericArgument (0xb6763d98) 0
+
+Class QMetaObject
+ size=16 align=4
+ base size=16 base align=4
+QMetaObject (0xb6763f00) 0
+
+Class QMetaObjectExtraData
+ size=8 align=4
+ base size=8 base align=4
+QMetaObjectExtraData (0xb682d03c) 0
+
+Class QByteArray::Data
+ size=20 align=4
+ base size=20 base align=4
+QByteArray::Data (0xb682d654) 0
+
+Class QByteArray
+ size=4 align=4
+ base size=4 base align=4
+QByteArray (0xb682d618) 0
+
+Class QByteRef
+ size=8 align=4
+ base size=8 base align=4
+QByteRef (0xb6686564) 0
+
+Class QString::Null
+ size=1 align=1
+ base size=0 base align=1
+QString::Null (0xb66a0d20) 0 empty
+
+Class QString::Data
+ size=20 align=4
+ base size=20 base align=4
+QString::Data (0xb66a0d5c) 0
+
+Class QString
+ size=4 align=4
+ base size=4 base align=4
+QString (0xb66a0ce4) 0
+
+Class QLatin1String
+ size=4 align=4
+ base size=4 base align=4
+QLatin1String (0xb65809d8) 0
+
+Class QCharRef
+ size=8 align=4
+ base size=8 base align=4
+QCharRef (0xb65e36cc) 0
+
+Class QConstString
+ size=4 align=4
+ base size=4 base align=4
+QConstString (0xb6646fc0) 0
+ QString (0xb646de10) 0
+
+Class QStringRef
+ size=12 align=4
+ base size=12 base align=4
+QStringRef (0xb649c168) 0
+
+Vtable for QObjectData
+QObjectData::_ZTV11QObjectData: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QObjectData)
+8 __cxa_pure_virtual
+12 __cxa_pure_virtual
+
+Class QObjectData
+ size=28 align=4
+ base size=28 base align=4
+QObjectData (0xb64ec0b4) 0
+ vptr=((& QObjectData::_ZTV11QObjectData) + 8u)
+
+Vtable for QObject
+QObject::_ZTV7QObject: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QObject)
+8 QObject::metaObject
+12 QObject::qt_metacast
+16 QObject::qt_metacall
+20 QObject::~QObject
+24 QObject::~QObject
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class QObject
+ size=8 align=4
+ base size=8 base align=4
+QObject (0xb64ec168) 0
+ vptr=((& QObject::_ZTV7QObject) + 8u)
+
+Vtable for QObjectUserData
+QObjectUserData::_ZTV15QObjectUserData: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI15QObjectUserData)
+8 QObjectUserData::~QObjectUserData
+12 QObjectUserData::~QObjectUserData
+
+Class QObjectUserData
+ size=4 align=4
+ base size=4 base align=4
+QObjectUserData (0xb64ec9d8) 0 nearly-empty
+ vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 8u)
+
+Vtable for QIODevice
+QIODevice::_ZTV9QIODevice: 30u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI9QIODevice)
+8 QIODevice::metaObject
+12 QIODevice::qt_metacast
+16 QIODevice::qt_metacall
+20 QIODevice::~QIODevice
+24 QIODevice::~QIODevice
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QIODevice::isSequential
+60 QIODevice::open
+64 QIODevice::close
+68 QIODevice::pos
+72 QIODevice::size
+76 QIODevice::seek
+80 QIODevice::atEnd
+84 QIODevice::reset
+88 QIODevice::bytesAvailable
+92 QIODevice::bytesToWrite
+96 QIODevice::canReadLine
+100 QIODevice::waitForReadyRead
+104 QIODevice::waitForBytesWritten
+108 __cxa_pure_virtual
+112 QIODevice::readLineData
+116 __cxa_pure_virtual
+
+Class QIODevice
+ size=8 align=4
+ base size=8 base align=4
+QIODevice (0xb652f780) 0
+ vptr=((& QIODevice::_ZTV9QIODevice) + 8u)
+ QObject (0xb64ecb04) 0
+ primary-for QIODevice (0xb652f780)
+
+Vtable for QDataStream
+QDataStream::_ZTV11QDataStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QDataStream)
+8 QDataStream::~QDataStream
+12 QDataStream::~QDataStream
+
+Class QDataStream
+ size=28 align=4
+ base size=28 base align=4
+QDataStream (0xb635f870) 0
+ vptr=((& QDataStream::_ZTV11QDataStream) + 8u)
+
+Class QHashData::Node
+ size=8 align=4
+ base size=8 base align=4
+QHashData::Node (0xb63bd438) 0
+
+Class QHashData
+ size=32 align=4
+ base size=32 base align=4
+QHashData (0xb63bd3fc) 0
+
+Class QHashDummyValue
+ size=1 align=1
+ base size=0 base align=1
+QHashDummyValue (0xb63bdb40) 0 empty
+
+Class QMapData::Node
+ size=8 align=4
+ base size=8 base align=4
+QMapData::Node (0xb63e6294) 0
+
+Class QMapData
+ size=72 align=4
+ base size=72 base align=4
+QMapData (0xb63e6258) 0
+
+Vtable for QSystemLocale
+QSystemLocale::_ZTV13QSystemLocale: 6u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI13QSystemLocale)
+8 QSystemLocale::~QSystemLocale
+12 QSystemLocale::~QSystemLocale
+16 QSystemLocale::query
+20 QSystemLocale::fallbackLocale
+
+Class QSystemLocale
+ size=4 align=4
+ base size=4 base align=4
+QSystemLocale (0xb63e65a0) 0 nearly-empty
+ vptr=((& QSystemLocale::_ZTV13QSystemLocale) + 8u)
+
+Class QLocale::Data
+ size=4 align=2
+ base size=4 base align=2
+QLocale::Data (0xb63e6618) 0
+
+Class QLocale
+ size=4 align=4
+ base size=4 base align=4
+QLocale (0xb63e65dc) 0
+
+Class QTextCodec::ConverterState
+ size=28 align=4
+ base size=28 base align=4
+QTextCodec::ConverterState (0xb63e6c6c) 0
+
+Vtable for QTextCodec
+QTextCodec::_ZTV10QTextCodec: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI10QTextCodec)
+8 __cxa_pure_virtual
+12 QTextCodec::aliases
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 QTextCodec::~QTextCodec
+32 QTextCodec::~QTextCodec
+
+Class QTextCodec
+ size=4 align=4
+ base size=4 base align=4
+QTextCodec (0xb63e6c30) 0 nearly-empty
+ vptr=((& QTextCodec::_ZTV10QTextCodec) + 8u)
+
+Class QTextEncoder
+ size=32 align=4
+ base size=32 base align=4
+QTextEncoder (0xb6170960) 0
+
+Class QTextDecoder
+ size=32 align=4
+ base size=32 base align=4
+QTextDecoder (0xb6170bb8) 0
+
+Class _IO_marker
+ size=12 align=4
+ base size=12 base align=4
+_IO_marker (0xb6170f3c) 0
+
+Class _IO_FILE
+ size=148 align=4
+ base size=148 base align=4
+_IO_FILE (0xb6170f78) 0
+
+Vtable for QTextStream
+QTextStream::_ZTV11QTextStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QTextStream)
+8 QTextStream::~QTextStream
+12 QTextStream::~QTextStream
+
+Class QTextStream
+ size=8 align=4
+ base size=8 base align=4
+QTextStream (0xb61c2000) 0
+ vptr=((& QTextStream::_ZTV11QTextStream) + 8u)
+
+Class QTextStreamManipulator
+ size=24 align=4
+ base size=22 base align=4
+QTextStreamManipulator (0xb61c2690) 0
+
+Vtable for QTextIStream
+QTextIStream::_ZTV12QTextIStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QTextIStream)
+8 QTextIStream::~QTextIStream
+12 QTextIStream::~QTextIStream
+
+Class QTextIStream
+ size=8 align=4
+ base size=8 base align=4
+QTextIStream (0xb6212140) 0
+ vptr=((& QTextIStream::_ZTV12QTextIStream) + 8u)
+ QTextStream (0xb620e870) 0
+ primary-for QTextIStream (0xb6212140)
+
+Vtable for QTextOStream
+QTextOStream::_ZTV12QTextOStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QTextOStream)
+8 QTextOStream::~QTextOStream
+12 QTextOStream::~QTextOStream
+
+Class QTextOStream
+ size=8 align=4
+ base size=8 base align=4
+QTextOStream (0xb6212400) 0
+ vptr=((& QTextOStream::_ZTV12QTextOStream) + 8u)
+ QTextStream (0xb620ef00) 0
+ primary-for QTextOStream (0xb6212400)
+
+Class wait
+ size=4 align=4
+ base size=4 base align=4
+wait (0xb62245a0) 0
+
+Class timespec
+ size=8 align=4
+ base size=8 base align=4
+timespec (0xb6224744) 0
+
+Class timeval
+ size=8 align=4
+ base size=8 base align=4
+timeval (0xb6224780) 0
+
+Class __pthread_internal_slist
+ size=4 align=4
+ base size=4 base align=4
+__pthread_internal_slist (0xb6224834) 0
+
+Class random_data
+ size=28 align=4
+ base size=28 base align=4
+random_data (0xb6224b40) 0
+
+Class drand48_data
+ size=24 align=4
+ base size=24 base align=4
+drand48_data (0xb6224b7c) 0
+
+Class QVectorData
+ size=16 align=4
+ base size=16 base align=4
+QVectorData (0xb6224bb8) 0
+
+Class QContiguousCacheData
+ size=24 align=4
+ base size=24 base align=4
+QContiguousCacheData (0xb6224ec4) 0
+
+Class QDebug::Stream
+ size=24 align=4
+ base size=22 base align=4
+QDebug::Stream (0xb61440b4) 0
+
+Class QDebug
+ size=4 align=4
+ base size=4 base align=4
+QDebug (0xb6144078) 0
+
+Class QNoDebug
+ size=1 align=1
+ base size=0 base align=1
+QNoDebug (0xb5f9ace4) 0 empty
+
+Class QMetaType
+ size=1 align=1
+ base size=0 base align=1
+QMetaType (0xb5f9af78) 0 empty
+
+Class QVariant::PrivateShared
+ size=8 align=4
+ base size=8 base align=4
+QVariant::PrivateShared (0xb6014c30) 0
+
+Class QVariant::Private::Data
+ size=8 align=4
+ base size=8 base align=4
+QVariant::Private::Data (0xb6014ca8) 0
+
+Class QVariant::Private
+ size=12 align=4
+ base size=12 base align=4
+QVariant::Private (0xb6014c6c) 0
+
+Class QVariant::Handler
+ size=36 align=4
+ base size=36 base align=4
+QVariant::Handler (0xb6014d20) 0
+
+Class QVariant
+ size=12 align=4
+ base size=12 base align=4
+QVariant (0xb6014bf4) 0
+
+Class QVariantComparisonHelper
+ size=4 align=4
+ base size=4 base align=4
+QVariantComparisonHelper (0xb5eb25dc) 0
+
+Class Phonon::ObjectDescriptionData
+ size=8 align=4
+ base size=8 base align=4
+Phonon::ObjectDescriptionData (0xb5eb5dc0) 0
+ QSharedData (0xb5eb2bf4) 0
+
+Class Phonon::Path
+ size=4 align=4
+ base size=4 base align=4
+Phonon::Path (0xb5ef84ec) 0
+
+Vtable for Phonon::MediaNode
+Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon9MediaNodeE)
+8 Phonon::MediaNode::~MediaNode
+12 Phonon::MediaNode::~MediaNode
+
+Class Phonon::MediaNode
+ size=8 align=4
+ base size=8 base align=4
+Phonon::MediaNode (0xb5ef8564) 0
+ vptr=((& Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE) + 8u)
+
+Vtable for Phonon::AbstractAudioOutput
+Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+8 Phonon::AbstractAudioOutput::metaObject
+12 Phonon::AbstractAudioOutput::qt_metacast
+16 Phonon::AbstractAudioOutput::qt_metacall
+20 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+24 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+64 Phonon::AbstractAudioOutput::_ZThn8_N6Phonon19AbstractAudioOutputD1Ev
+68 Phonon::AbstractAudioOutput::_ZThn8_N6Phonon19AbstractAudioOutputD0Ev
+
+Class Phonon::AbstractAudioOutput
+ size=16 align=4
+ base size=16 base align=4
+Phonon::AbstractAudioOutput (0xb5f18eb0) 0
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 8u)
+ QObject (0xb5ef8618) 0
+ primary-for Phonon::AbstractAudioOutput (0xb5f18eb0)
+ Phonon::MediaNode (0xb5ef8654) 8
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 64u)
+
+Vtable for Phonon::AbstractMediaStream
+Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractMediaStreamE)
+8 Phonon::AbstractMediaStream::metaObject
+12 Phonon::AbstractMediaStream::qt_metacast
+16 Phonon::AbstractMediaStream::qt_metacall
+20 Phonon::AbstractMediaStream::~AbstractMediaStream
+24 Phonon::AbstractMediaStream::~AbstractMediaStream
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 Phonon::AbstractMediaStream::enoughData
+68 Phonon::AbstractMediaStream::seekStream
+
+Class Phonon::AbstractMediaStream
+ size=12 align=4
+ base size=12 base align=4
+Phonon::AbstractMediaStream (0xb5f0e7c0) 0
+ vptr=((& Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE) + 8u)
+ QObject (0xb5ef8a8c) 0
+ primary-for Phonon::AbstractMediaStream (0xb5f0e7c0)
+
+Vtable for Phonon::AbstractVideoOutput
+Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractVideoOutputE)
+8 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+12 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+
+Class Phonon::AbstractVideoOutput
+ size=8 align=4
+ base size=8 base align=4
+Phonon::AbstractVideoOutput (0xb5f0eac0) 0
+ vptr=((& Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE) + 8u)
+ Phonon::MediaNode (0xb5ef8ce4) 0
+ primary-for Phonon::AbstractVideoOutput (0xb5f0eac0)
+
+Vtable for Phonon::AddonInterface
+Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE: 6u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon14AddonInterfaceE)
+8 Phonon::AddonInterface::~AddonInterface
+12 Phonon::AddonInterface::~AddonInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+
+Class Phonon::AddonInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AddonInterface (0xb5ef8e10) 0 nearly-empty
+ vptr=((& Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE) + 8u)
+
+Vtable for Phonon::AudioOutput
+Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+8 Phonon::AudioOutput::metaObject
+12 Phonon::AudioOutput::qt_metacast
+16 Phonon::AudioOutput::qt_metacall
+20 Phonon::AudioOutput::~AudioOutput
+24 Phonon::AudioOutput::~AudioOutput
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+64 Phonon::AudioOutput::_ZThn8_N6Phonon11AudioOutputD1Ev
+68 Phonon::AudioOutput::_ZThn8_N6Phonon11AudioOutputD0Ev
+
+Class Phonon::AudioOutput
+ size=16 align=4
+ base size=16 base align=4
+Phonon::AudioOutput (0xb5d48040) 0
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 8u)
+ Phonon::AbstractAudioOutput (0xb5d41eb0) 0
+ primary-for Phonon::AudioOutput (0xb5d48040)
+ QObject (0xb5d44384) 0
+ primary-for Phonon::AbstractAudioOutput (0xb5d41eb0)
+ Phonon::MediaNode (0xb5d443c0) 8
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 64u)
+
+Vtable for Phonon::AudioOutputInterface40
+Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E: 8u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface40E)
+8 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+12 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface40
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AudioOutputInterface40 (0xb5d445dc) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E) + 8u)
+
+Vtable for Phonon::AudioOutputInterface42
+Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface42E)
+8 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+12 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface42
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AudioOutputInterface42 (0xb5d48500) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E) + 8u)
+ Phonon::AudioOutputInterface40 (0xb5d447f8) 0 nearly-empty
+ primary-for Phonon::AudioOutputInterface42 (0xb5d48500)
+
+Vtable for Phonon::BackendCapabilities::Notifier
+Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19BackendCapabilities8NotifierE)
+8 Phonon::BackendCapabilities::Notifier::metaObject
+12 Phonon::BackendCapabilities::Notifier::qt_metacast
+16 Phonon::BackendCapabilities::Notifier::qt_metacall
+20 Phonon::BackendCapabilities::Notifier::~Notifier
+24 Phonon::BackendCapabilities::Notifier::~Notifier
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class Phonon::BackendCapabilities::Notifier
+ size=8 align=4
+ base size=8 base align=4
+Phonon::BackendCapabilities::Notifier (0xb5d48b00) 0
+ vptr=((& Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE) + 8u)
+ QObject (0xb5d44d5c) 0
+ primary-for Phonon::BackendCapabilities::Notifier (0xb5d48b00)
+
+Vtable for Phonon::BackendInterface
+Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE: 12u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon16BackendInterfaceE)
+8 Phonon::BackendInterface::~BackendInterface
+12 Phonon::BackendInterface::~BackendInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+
+Class Phonon::BackendInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::BackendInterface (0xb5d44e88) 0 nearly-empty
+ vptr=((& Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE) + 8u)
+
+Vtable for Phonon::Effect
+Phonon::Effect::_ZTVN6Phonon6EffectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+8 Phonon::Effect::metaObject
+12 Phonon::Effect::qt_metacast
+16 Phonon::Effect::qt_metacall
+20 Phonon::Effect::~Effect
+24 Phonon::Effect::~Effect
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+64 Phonon::Effect::_ZThn8_N6Phonon6EffectD1Ev
+68 Phonon::Effect::_ZThn8_N6Phonon6EffectD0Ev
+
+Class Phonon::Effect
+ size=16 align=4
+ base size=16 base align=4
+Phonon::Effect (0xb5d70e10) 0
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 8u)
+ QObject (0xb5d743fc) 0
+ primary-for Phonon::Effect (0xb5d70e10)
+ Phonon::MediaNode (0xb5d74438) 8
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 64u)
+
+Vtable for Phonon::EffectInterface
+Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15EffectInterfaceE)
+8 Phonon::EffectInterface::~EffectInterface
+12 Phonon::EffectInterface::~EffectInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+
+Class Phonon::EffectInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::EffectInterface (0xb5d74654) 0 nearly-empty
+ vptr=((& Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE) + 8u)
+
+Class Phonon::EffectParameter
+ size=4 align=4
+ base size=4 base align=4
+Phonon::EffectParameter (0xb5d74bb8) 0
+
+Class QMargins
+ size=16 align=4
+ base size=16 base align=4
+QMargins (0xb5d74d20) 0
+
+Class QSize
+ size=8 align=4
+ base size=8 base align=4
+QSize (0xb5db4e4c) 0
+
+Class QSizeF
+ size=16 align=4
+ base size=16 base align=4
+QSizeF (0xb5dda8e8) 0
+
+Class QPoint
+ size=8 align=4
+ base size=8 base align=4
+QPoint (0xb5e084ec) 0
+
+Class QPointF
+ size=16 align=4
+ base size=16 base align=4
+QPointF (0xb5e21a8c) 0
+
+Class QRect
+ size=16 align=4
+ base size=16 base align=4
+QRect (0xb5c471a4) 0
+
+Class QRectF
+ size=32 align=4
+ base size=32 base align=4
+QRectF (0xb5c93dd4) 0
+
+Vtable for QPaintDevice
+QPaintDevice::_ZTV12QPaintDevice: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QPaintDevice)
+8 QPaintDevice::~QPaintDevice
+12 QPaintDevice::~QPaintDevice
+16 QPaintDevice::devType
+20 __cxa_pure_virtual
+24 QPaintDevice::metric
+
+Class QPaintDevice
+ size=8 align=4
+ base size=6 base align=4
+QPaintDevice (0xb5cf0b40) 0
+ vptr=((& QPaintDevice::_ZTV12QPaintDevice) + 8u)
+
+Class QRegExp
+ size=4 align=4
+ base size=4 base align=4
+QRegExp (0xb5d0d708) 0
+
+Class QStringMatcher::Data
+ size=264 align=4
+ base size=264 base align=4
+QStringMatcher::Data (0xb5d3112c) 0
+
+Class QStringMatcher
+ size=1036 align=4
+ base size=1036 base align=4
+QStringMatcher (0xb5d310f0) 0
+
+Class QStringList
+ size=4 align=4
+ base size=4 base align=4
+QStringList (0xb5d17bc0) 0
+ QList<QString> (0xb5d31258) 0
+
+Class QColor
+ size=16 align=4
+ base size=14 base align=4
+QColor (0xb5b787bc) 0
+
+Class QPolygon
+ size=4 align=4
+ base size=4 base align=4
+QPolygon (0xb5bb3380) 0
+ QVector<QPoint> (0xb5b78e4c) 0
+
+Class QPolygonF
+ size=4 align=4
+ base size=4 base align=4
+QPolygonF (0xb5bb39c0) 0
+ QVector<QPointF> (0xb5bd9834) 0
+
+Class QRegion::QRegionData
+ size=16 align=4
+ base size=16 base align=4
+QRegion::QRegionData (0xb5c041a4) 0
+
+Class QRegion
+ size=4 align=4
+ base size=4 base align=4
+QRegion (0xb5c04168) 0
+
+Class QLine
+ size=16 align=4
+ base size=16 base align=4
+QLine (0xb5c044ec) 0
+
+Class QLineF
+ size=32 align=4
+ base size=32 base align=4
+QLineF (0xb5c3f21c) 0
+
+Class QMatrix
+ size=48 align=4
+ base size=48 base align=4
+QMatrix (0xb5a6630c) 0
+
+Class QPainterPath::Element
+ size=20 align=4
+ base size=20 base align=4
+QPainterPath::Element (0xb5a874b0) 0
+
+Class QPainterPath
+ size=4 align=4
+ base size=4 base align=4
+QPainterPath (0xb5a87474) 0
+
+Class QPainterPathPrivate
+ size=8 align=4
+ base size=8 base align=4
+QPainterPathPrivate (0xb5a8799c) 0
+
+Class QPainterPathStroker
+ size=4 align=4
+ base size=4 base align=4
+QPainterPathStroker (0xb5a87ac8) 0
+
+Class QTransform
+ size=80 align=4
+ base size=80 base align=4
+QTransform (0xb5aeaa50) 0
+
+Class QImageTextKeyLang
+ size=8 align=4
+ base size=8 base align=4
+QImageTextKeyLang (0xb594f99c) 0
+
+Vtable for QImage
+QImage::_ZTV6QImage: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI6QImage)
+8 QImage::~QImage
+12 QImage::~QImage
+16 QImage::devType
+20 QImage::paintEngine
+24 QImage::metric
+
+Class QImage
+ size=12 align=4
+ base size=12 base align=4
+QImage (0xb594b600) 0
+ vptr=((& QImage::_ZTV6QImage) + 8u)
+ QPaintDevice (0xb596e384) 0
+ primary-for QImage (0xb594b600)
+
+Vtable for QtSharedPointer::ExternalRefCountData
+QtSharedPointer::ExternalRefCountData::_ZTVN15QtSharedPointer20ExternalRefCountDataE: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN15QtSharedPointer20ExternalRefCountDataE)
+8 QtSharedPointer::ExternalRefCountData::~ExternalRefCountData
+12 QtSharedPointer::ExternalRefCountData::~ExternalRefCountData
+16 QtSharedPointer::ExternalRefCountData::destroy
+
+Class QtSharedPointer::ExternalRefCountData
+ size=12 align=4
+ base size=12 base align=4
+QtSharedPointer::ExternalRefCountData (0xb59cd0b4) 0
+ vptr=((& QtSharedPointer::ExternalRefCountData::_ZTVN15QtSharedPointer20ExternalRefCountDataE) + 8u)
+
+Vtable for QtSharedPointer::ExternalRefCountWithDestroyFn
+QtSharedPointer::ExternalRefCountWithDestroyFn::_ZTVN15QtSharedPointer29ExternalRefCountWithDestroyFnE: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN15QtSharedPointer29ExternalRefCountWithDestroyFnE)
+8 QtSharedPointer::ExternalRefCountWithDestroyFn::~ExternalRefCountWithDestroyFn
+12 QtSharedPointer::ExternalRefCountWithDestroyFn::~ExternalRefCountWithDestroyFn
+16 QtSharedPointer::ExternalRefCountWithDestroyFn::destroy
+
+Class QtSharedPointer::ExternalRefCountWithDestroyFn
+ size=16 align=4
+ base size=16 base align=4
+QtSharedPointer::ExternalRefCountWithDestroyFn (0xb59c6cc0) 0
+ vptr=((& QtSharedPointer::ExternalRefCountWithDestroyFn::_ZTVN15QtSharedPointer29ExternalRefCountWithDestroyFnE) + 8u)
+ QtSharedPointer::ExternalRefCountData (0xb59cd8ac) 0
+ primary-for QtSharedPointer::ExternalRefCountWithDestroyFn (0xb59c6cc0)
+
+Vtable for QPixmap
+QPixmap::_ZTV7QPixmap: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QPixmap)
+8 QPixmap::~QPixmap
+12 QPixmap::~QPixmap
+16 QPixmap::devType
+20 QPixmap::paintEngine
+24 QPixmap::metric
+
+Class QPixmap
+ size=12 align=4
+ base size=12 base align=4
+QPixmap (0xb5a2c740) 0
+ vptr=((& QPixmap::_ZTV7QPixmap) + 8u)
+ QPaintDevice (0xb59cddd4) 0
+ primary-for QPixmap (0xb5a2c740)
+
+Class QBrush
+ size=4 align=4
+ base size=4 base align=4
+QBrush (0xb585c474) 0
+
+Class QBrushData
+ size=104 align=4
+ base size=104 base align=4
+QBrushData (0xb585c618) 0
+
+Class QGradient
+ size=56 align=4
+ base size=56 base align=4
+QGradient (0xb585c9d8) 0
+
+Class QLinearGradient
+ size=56 align=4
+ base size=56 base align=4
+QLinearGradient (0xb58795c0) 0
+ QGradient (0xb585cc6c) 0
+
+Class QRadialGradient
+ size=56 align=4
+ base size=56 base align=4
+QRadialGradient (0xb58796c0) 0
+ QGradient (0xb585cca8) 0
+
+Class QConicalGradient
+ size=56 align=4
+ base size=56 base align=4
+QConicalGradient (0xb58797c0) 0
+ QGradient (0xb585cce4) 0
+
+Class QPalette
+ size=8 align=4
+ base size=8 base align=4
+QPalette (0xb585cd20) 0
+
+Class QColorGroup
+ size=8 align=4
+ base size=8 base align=4
+QColorGroup (0xb58d3200) 0
+ QPalette (0xb58c7618) 0
+
+Class QFont
+ size=8 align=4
+ base size=8 base align=4
+QFont (0xb58eb780) 0
+
+Class QFontMetrics
+ size=4 align=4
+ base size=4 base align=4
+QFontMetrics (0xb58eb99c) 0
+
+Class QFontMetricsF
+ size=4 align=4
+ base size=4 base align=4
+QFontMetricsF (0xb58ebbf4) 0
+
+Class QFontInfo
+ size=4 align=4
+ base size=4 base align=4
+QFontInfo (0xb58ebca8) 0
+
+Class QSizePolicy
+ size=4 align=4
+ base size=4 base align=4
+QSizePolicy (0xb58ebce4) 0
+
+Class QCursor
+ size=4 align=4
+ base size=4 base align=4
+QCursor (0xb5775bb8) 0
+
+Class QKeySequence
+ size=4 align=4
+ base size=4 base align=4
+QKeySequence (0xb5775bf4) 0
+
+Class QWidgetData
+ size=64 align=4
+ base size=64 base align=4
+QWidgetData (0xb5775e10) 0
+
+Vtable for QWidget
+QWidget::_ZTV7QWidget: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QWidget)
+8 QWidget::metaObject
+12 QWidget::qt_metacast
+16 QWidget::qt_metacall
+20 QWidget::~QWidget
+24 QWidget::~QWidget
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTI7QWidget)
+232 QWidget::_ZThn8_N7QWidgetD1Ev
+236 QWidget::_ZThn8_N7QWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class QWidget
+ size=20 align=4
+ base size=20 base align=4
+QWidget (0xb57c4dc0) 0
+ vptr=((& QWidget::_ZTV7QWidget) + 8u)
+ QObject (0xb5775e4c) 0
+ primary-for QWidget (0xb57c4dc0)
+ QPaintDevice (0xb5775e88) 8
+ vptr=((& QWidget::_ZTV7QWidget) + 232u)
+
+Vtable for Phonon::EffectWidget
+Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+8 Phonon::EffectWidget::metaObject
+12 Phonon::EffectWidget::qt_metacast
+16 Phonon::EffectWidget::qt_metacall
+20 Phonon::EffectWidget::~EffectWidget
+24 Phonon::EffectWidget::~EffectWidget
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+232 Phonon::EffectWidget::_ZThn8_N6Phonon12EffectWidgetD1Ev
+236 Phonon::EffectWidget::_ZThn8_N6Phonon12EffectWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::EffectWidget
+ size=24 align=4
+ base size=24 base align=4
+Phonon::EffectWidget (0xb5680080) 0
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 8u)
+ QWidget (0xb567f5f0) 0
+ primary-for Phonon::EffectWidget (0xb5680080)
+ QObject (0xb56685dc) 0
+ primary-for QWidget (0xb567f5f0)
+ QPaintDevice (0xb5668618) 8
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 232u)
+
+Vtable for Phonon::MediaController
+Phonon::MediaController::_ZTVN6Phonon15MediaControllerE: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15MediaControllerE)
+8 Phonon::MediaController::metaObject
+12 Phonon::MediaController::qt_metacast
+16 Phonon::MediaController::qt_metacall
+20 Phonon::MediaController::~MediaController
+24 Phonon::MediaController::~MediaController
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class Phonon::MediaController
+ size=12 align=4
+ base size=12 base align=4
+Phonon::MediaController (0xb5680340) 0
+ vptr=((& Phonon::MediaController::_ZTVN6Phonon15MediaControllerE) + 8u)
+ QObject (0xb56687bc) 0
+ primary-for Phonon::MediaController (0xb5680340)
+
+Class Phonon::MediaSource
+ size=4 align=4
+ base size=4 base align=4
+Phonon::MediaSource (0xb56689d8) 0
+
+Vtable for Phonon::MediaObject
+Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+8 Phonon::MediaObject::metaObject
+12 Phonon::MediaObject::qt_metacast
+16 Phonon::MediaObject::qt_metacall
+20 Phonon::MediaObject::~MediaObject
+24 Phonon::MediaObject::~MediaObject
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+64 Phonon::MediaObject::_ZThn8_N6Phonon11MediaObjectD1Ev
+68 Phonon::MediaObject::_ZThn8_N6Phonon11MediaObjectD0Ev
+
+Class Phonon::MediaObject
+ size=16 align=4
+ base size=16 base align=4
+Phonon::MediaObject (0xb56bc640) 0
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 8u)
+ QObject (0xb5668a50) 0
+ primary-for Phonon::MediaObject (0xb56bc640)
+ Phonon::MediaNode (0xb5668a8c) 8
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 64u)
+
+Vtable for Phonon::MediaObjectInterface
+Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE: 25u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20MediaObjectInterfaceE)
+8 Phonon::MediaObjectInterface::~MediaObjectInterface
+12 Phonon::MediaObjectInterface::~MediaObjectInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 __cxa_pure_virtual
+76 __cxa_pure_virtual
+80 Phonon::MediaObjectInterface::remainingTime
+84 __cxa_pure_virtual
+88 __cxa_pure_virtual
+92 __cxa_pure_virtual
+96 __cxa_pure_virtual
+
+Class Phonon::MediaObjectInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::MediaObjectInterface (0xb5668ca8) 0 nearly-empty
+ vptr=((& Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE) + 8u)
+
+Class QModelIndex
+ size=16 align=4
+ base size=16 base align=4
+QModelIndex (0xb56d8294) 0
+
+Class QPersistentModelIndex
+ size=4 align=4
+ base size=4 base align=4
+QPersistentModelIndex (0xb56ea744) 0
+
+Vtable for QAbstractItemModel
+QAbstractItemModel::_ZTV18QAbstractItemModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI18QAbstractItemModel)
+8 QAbstractItemModel::metaObject
+12 QAbstractItemModel::qt_metacast
+16 QAbstractItemModel::qt_metacall
+20 QAbstractItemModel::~QAbstractItemModel
+24 QAbstractItemModel::~QAbstractItemModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 QAbstractItemModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractItemModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractItemModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractItemModel (0xb56e1940) 0
+ vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 8u)
+ QObject (0xb56ea8ac) 0
+ primary-for QAbstractItemModel (0xb56e1940)
+
+Vtable for QAbstractTableModel
+QAbstractTableModel::_ZTV19QAbstractTableModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI19QAbstractTableModel)
+8 QAbstractTableModel::metaObject
+12 QAbstractTableModel::qt_metacast
+16 QAbstractTableModel::qt_metacall
+20 QAbstractTableModel::~QAbstractTableModel
+24 QAbstractTableModel::~QAbstractTableModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QAbstractTableModel::index
+60 QAbstractTableModel::parent
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 QAbstractTableModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractTableModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractTableModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractTableModel (0xb56e1f80) 0
+ vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 8u)
+ QAbstractItemModel (0xb56e1fc0) 0
+ primary-for QAbstractTableModel (0xb56e1f80)
+ QObject (0xb572621c) 0
+ primary-for QAbstractItemModel (0xb56e1fc0)
+
+Vtable for QAbstractListModel
+QAbstractListModel::_ZTV18QAbstractListModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI18QAbstractListModel)
+8 QAbstractListModel::metaObject
+12 QAbstractListModel::qt_metacast
+16 QAbstractListModel::qt_metacall
+20 QAbstractListModel::~QAbstractListModel
+24 QAbstractListModel::~QAbstractListModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QAbstractListModel::index
+60 QAbstractListModel::parent
+64 __cxa_pure_virtual
+68 QAbstractListModel::columnCount
+72 QAbstractListModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractListModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractListModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractListModel (0xb572a200) 0
+ vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 8u)
+ QAbstractItemModel (0xb572a240) 0
+ primary-for QAbstractListModel (0xb572a200)
+ QObject (0xb5726348) 0
+ primary-for QAbstractItemModel (0xb572a240)
+
+Class Phonon::ObjectDescriptionModelData
+ size=4 align=4
+ base size=4 base align=4
+Phonon::ObjectDescriptionModelData (0xb554f21c) 0
+
+Vtable for Phonon::PlatformPlugin
+Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE: 16u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon14PlatformPluginE)
+8 Phonon::PlatformPlugin::~PlatformPlugin
+12 Phonon::PlatformPlugin::~PlatformPlugin
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 Phonon::PlatformPlugin::deviceAccessListFor
+
+Class Phonon::PlatformPlugin
+ size=4 align=4
+ base size=4 base align=4
+Phonon::PlatformPlugin (0xb554f384) 0 nearly-empty
+ vptr=((& Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE) + 8u)
+
+Vtable for Phonon::SeekSlider
+Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+8 Phonon::SeekSlider::metaObject
+12 Phonon::SeekSlider::qt_metacast
+16 Phonon::SeekSlider::qt_metacall
+20 Phonon::SeekSlider::~SeekSlider
+24 Phonon::SeekSlider::~SeekSlider
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+232 Phonon::SeekSlider::_ZThn8_N6Phonon10SeekSliderD1Ev
+236 Phonon::SeekSlider::_ZThn8_N6Phonon10SeekSliderD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::SeekSlider
+ size=24 align=4
+ base size=24 base align=4
+Phonon::SeekSlider (0xb5573840) 0
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 8u)
+ QWidget (0xb55a5e10) 0
+ primary-for Phonon::SeekSlider (0xb5573840)
+ QObject (0xb554f924) 0
+ primary-for QWidget (0xb55a5e10)
+ QPaintDevice (0xb554f960) 8
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 232u)
+
+Vtable for Phonon::StreamInterface
+Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE: 8u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15StreamInterfaceE)
+8 Phonon::StreamInterface::~StreamInterface
+12 Phonon::StreamInterface::~StreamInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+
+Class Phonon::StreamInterface
+ size=8 align=4
+ base size=8 base align=4
+Phonon::StreamInterface (0xb554fb04) 0
+ vptr=((& Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE) + 8u)
+
+Vtable for Phonon::VideoPlayer
+Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+8 Phonon::VideoPlayer::metaObject
+12 Phonon::VideoPlayer::qt_metacast
+16 Phonon::VideoPlayer::qt_metacall
+20 Phonon::VideoPlayer::~VideoPlayer
+24 Phonon::VideoPlayer::~VideoPlayer
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+232 Phonon::VideoPlayer::_ZThn8_N6Phonon11VideoPlayerD1Ev
+236 Phonon::VideoPlayer::_ZThn8_N6Phonon11VideoPlayerD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VideoPlayer
+ size=24 align=4
+ base size=24 base align=4
+Phonon::VideoPlayer (0xb5573d80) 0
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 8u)
+ QWidget (0xb55ba730) 0
+ primary-for Phonon::VideoPlayer (0xb5573d80)
+ QObject (0xb554fec4) 0
+ primary-for QWidget (0xb55ba730)
+ QPaintDevice (0xb554ff00) 8
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 232u)
+
+Vtable for Phonon::VideoWidget
+Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE: 67u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+8 Phonon::VideoWidget::metaObject
+12 Phonon::VideoWidget::qt_metacast
+16 Phonon::VideoWidget::qt_metacall
+20 Phonon::VideoWidget::~VideoWidget
+24 Phonon::VideoWidget::~VideoWidget
+28 Phonon::VideoWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 Phonon::VideoWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+232 Phonon::VideoWidget::_ZThn8_N6Phonon11VideoWidgetD1Ev
+236 Phonon::VideoWidget::_ZThn8_N6Phonon11VideoWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+252 (int (*)(...))-0x000000014
+256 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+260 Phonon::VideoWidget::_ZThn20_N6Phonon11VideoWidgetD1Ev
+264 Phonon::VideoWidget::_ZThn20_N6Phonon11VideoWidgetD0Ev
+
+Class Phonon::VideoWidget
+ size=28 align=4
+ base size=28 base align=4
+Phonon::VideoWidget (0xb55c6b90) 0
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 8u)
+ QWidget (0xb55d0000) 0
+ primary-for Phonon::VideoWidget (0xb55c6b90)
+ QObject (0xb55cf03c) 0
+ primary-for QWidget (0xb55d0000)
+ QPaintDevice (0xb55cf078) 8
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 232u)
+ Phonon::AbstractVideoOutput (0xb5573fc0) 20
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 260u)
+ Phonon::MediaNode (0xb55cf0b4) 20
+ primary-for Phonon::AbstractVideoOutput (0xb5573fc0)
+
+Vtable for Phonon::VideoWidgetInterface
+Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE: 17u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20VideoWidgetInterfaceE)
+8 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+12 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+
+Class Phonon::VideoWidgetInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::VideoWidgetInterface (0xb55cf2d0) 0 nearly-empty
+ vptr=((& Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE) + 8u)
+
+Vtable for Phonon::VolumeFaderEffect
+Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+8 Phonon::VolumeFaderEffect::metaObject
+12 Phonon::VolumeFaderEffect::qt_metacast
+16 Phonon::VolumeFaderEffect::qt_metacall
+20 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+24 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+64 Phonon::VolumeFaderEffect::_ZThn8_N6Phonon17VolumeFaderEffectD1Ev
+68 Phonon::VolumeFaderEffect::_ZThn8_N6Phonon17VolumeFaderEffectD0Ev
+
+Class Phonon::VolumeFaderEffect
+ size=16 align=4
+ base size=16 base align=4
+Phonon::VolumeFaderEffect (0xb55d3780) 0
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 8u)
+ Phonon::Effect (0xb55e8500) 0
+ primary-for Phonon::VolumeFaderEffect (0xb55d3780)
+ QObject (0xb55cf7bc) 0
+ primary-for Phonon::Effect (0xb55e8500)
+ Phonon::MediaNode (0xb55cf7f8) 8
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 64u)
+
+Vtable for Phonon::VolumeFaderInterface
+Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20VolumeFaderInterfaceE)
+8 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+12 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+16 Phonon::VolumeFaderInterface::volume
+20 Phonon::VolumeFaderInterface::setVolume
+24 Phonon::VolumeFaderInterface::fadeCurve
+28 Phonon::VolumeFaderInterface::setFadeCurve
+32 Phonon::VolumeFaderInterface::fadeTo
+
+Class Phonon::VolumeFaderInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::VolumeFaderInterface (0xb55cfa14) 0 nearly-empty
+ vptr=((& Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE) + 8u)
+
+Vtable for Phonon::VolumeSlider
+Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+8 Phonon::VolumeSlider::metaObject
+12 Phonon::VolumeSlider::qt_metacast
+16 Phonon::VolumeSlider::qt_metacall
+20 Phonon::VolumeSlider::~VolumeSlider
+24 Phonon::VolumeSlider::~VolumeSlider
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+232 Phonon::VolumeSlider::_ZThn8_N6Phonon12VolumeSliderD1Ev
+236 Phonon::VolumeSlider::_ZThn8_N6Phonon12VolumeSliderD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VolumeSlider
+ size=24 align=4
+ base size=24 base align=4
+Phonon::VolumeSlider (0xb5602080) 0
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 8u)
+ QWidget (0xb5600280) 0
+ primary-for Phonon::VolumeSlider (0xb5602080)
+ QObject (0xb55cff78) 0
+ primary-for QWidget (0xb5600280)
+ QPaintDevice (0xb55cffb4) 8
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 232u)
+
diff --git a/tests/auto/bic/data/phonon.4.7.0.linux-gcc-ia32.txt b/tests/auto/bic/data/phonon.4.7.0.linux-gcc-ia32.txt
new file mode 100644
index 0000000..69753ab
--- /dev/null
+++ b/tests/auto/bic/data/phonon.4.7.0.linux-gcc-ia32.txt
@@ -0,0 +1,2095 @@
+Class QSysInfo
+ size=1 align=1
+ base size=0 base align=1
+QSysInfo (0xb6dedec4) 0 empty
+
+Class QBool
+ size=1 align=1
+ base size=1 base align=1
+QBool (0xb6d3a078) 0
+
+Class qIsNull(double)::U
+ size=8 align=4
+ base size=8 base align=4
+qIsNull(double)::U (0xb6d3a744) 0
+
+Class qIsNull(float)::U
+ size=4 align=4
+ base size=4 base align=4
+qIsNull(float)::U (0xb6d3a7f8) 0
+
+Class QFlag
+ size=4 align=4
+ base size=4 base align=4
+QFlag (0xb6d6d03c) 0
+
+Class QIncompatibleFlag
+ size=4 align=4
+ base size=4 base align=4
+QIncompatibleFlag (0xb6d6d168) 0
+
+Class QBasicAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QBasicAtomicInt (0xb6d6d3c0) 0
+
+Class QAtomicInt
+ size=4 align=4
+ base size=4 base align=4
+QAtomicInt (0xb681d480) 0
+ QBasicAtomicInt (0xb6d6dac8) 0
+
+Class QSharedData
+ size=4 align=4
+ base size=4 base align=4
+QSharedData (0xb6d6dfb4) 0
+
+Class QLatin1Char
+ size=1 align=1
+ base size=1 base align=1
+QLatin1Char (0xb6832348) 0
+
+Class QChar
+ size=2 align=2
+ base size=2 base align=2
+QChar (0xb6832528) 0
+
+Vtable for std::exception
+std::exception::_ZTVSt9exception: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt9exception)
+8 std::exception::~exception
+12 std::exception::~exception
+16 std::exception::what
+
+Class std::exception
+ size=4 align=4
+ base size=4 base align=4
+std::exception (0xb68adc6c) 0 nearly-empty
+ vptr=((& std::exception::_ZTVSt9exception) + 8u)
+
+Vtable for std::bad_exception
+std::bad_exception::_ZTVSt13bad_exception: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt13bad_exception)
+8 std::bad_exception::~bad_exception
+12 std::bad_exception::~bad_exception
+16 std::bad_exception::what
+
+Class std::bad_exception
+ size=4 align=4
+ base size=4 base align=4
+std::bad_exception (0xb68a9dc0) 0 nearly-empty
+ vptr=((& std::bad_exception::_ZTVSt13bad_exception) + 8u)
+ std::exception (0xb68add5c) 0 nearly-empty
+ primary-for std::bad_exception (0xb68a9dc0)
+
+Vtable for std::bad_alloc
+std::bad_alloc::_ZTVSt9bad_alloc: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTISt9bad_alloc)
+8 std::bad_alloc::~bad_alloc
+12 std::bad_alloc::~bad_alloc
+16 std::bad_alloc::what
+
+Class std::bad_alloc
+ size=4 align=4
+ base size=4 base align=4
+std::bad_alloc (0xb68a9f40) 0 nearly-empty
+ vptr=((& std::bad_alloc::_ZTVSt9bad_alloc) + 8u)
+ std::exception (0xb68adfb4) 0 nearly-empty
+ primary-for std::bad_alloc (0xb68a9f40)
+
+Class std::nothrow_t
+ size=1 align=1
+ base size=0 base align=1
+std::nothrow_t (0xb68c621c) 0 empty
+
+Class __locale_struct
+ size=116 align=4
+ base size=116 base align=4
+__locale_struct (0xb68c62d0) 0
+
+Class QListData::Data
+ size=24 align=4
+ base size=24 base align=4
+QListData::Data (0xb68c6348) 0
+
+Class QListData
+ size=4 align=4
+ base size=4 base align=4
+QListData (0xb68c630c) 0
+
+Class QScopedPointerPodDeleter
+ size=1 align=1
+ base size=0 base align=1
+QScopedPointerPodDeleter (0xb68c6b7c) 0 empty
+
+Class QInternal
+ size=1 align=1
+ base size=0 base align=1
+QInternal (0xb6616b40) 0 empty
+
+Class QGenericArgument
+ size=8 align=4
+ base size=8 base align=4
+QGenericArgument (0xb6616b7c) 0
+
+Class QGenericReturnArgument
+ size=8 align=4
+ base size=8 base align=4
+QGenericReturnArgument (0xb66c42c0) 0
+ QGenericArgument (0xb6616d98) 0
+
+Class QMetaObject
+ size=16 align=4
+ base size=16 base align=4
+QMetaObject (0xb6616f3c) 0
+
+Class QMetaObjectExtraData
+ size=8 align=4
+ base size=8 base align=4
+QMetaObjectExtraData (0xb66e1078) 0
+
+Class QByteArray::Data
+ size=20 align=4
+ base size=20 base align=4
+QByteArray::Data (0xb66e1690) 0
+
+Class QByteArray
+ size=4 align=4
+ base size=4 base align=4
+QByteArray (0xb66e1654) 0
+
+Class QByteRef
+ size=8 align=4
+ base size=8 base align=4
+QByteRef (0xb653a5a0) 0
+
+Class QString::Null
+ size=1 align=1
+ base size=0 base align=1
+QString::Null (0xb6556d5c) 0 empty
+
+Class QString::Data
+ size=20 align=4
+ base size=20 base align=4
+QString::Data (0xb6556d98) 0
+
+Class QString
+ size=4 align=4
+ base size=4 base align=4
+QString (0xb6556d20) 0
+
+Class QLatin1String
+ size=4 align=4
+ base size=4 base align=4
+QLatin1String (0xb643899c) 0
+
+Class QCharRef
+ size=8 align=4
+ base size=8 base align=4
+QCharRef (0xb649a690) 0
+
+Class QConstString
+ size=4 align=4
+ base size=4 base align=4
+QConstString (0xb63109c0) 0
+ QString (0xb6324dd4) 0
+
+Class QStringRef
+ size=12 align=4
+ base size=12 base align=4
+QStringRef (0xb635212c) 0
+
+Vtable for QObjectData
+QObjectData::_ZTV11QObjectData: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QObjectData)
+8 __cxa_pure_virtual
+12 __cxa_pure_virtual
+
+Class QObjectData
+ size=28 align=4
+ base size=28 base align=4
+QObjectData (0xb63a1078) 0
+ vptr=((& QObjectData::_ZTV11QObjectData) + 8u)
+
+Vtable for QObject
+QObject::_ZTV7QObject: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QObject)
+8 QObject::metaObject
+12 QObject::qt_metacast
+16 QObject::qt_metacall
+20 QObject::~QObject
+24 QObject::~QObject
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class QObject
+ size=8 align=4
+ base size=8 base align=4
+QObject (0xb63a112c) 0
+ vptr=((& QObject::_ZTV7QObject) + 8u)
+
+Vtable for QObjectUserData
+QObjectUserData::_ZTV15QObjectUserData: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI15QObjectUserData)
+8 QObjectUserData::~QObjectUserData
+12 QObjectUserData::~QObjectUserData
+
+Class QObjectUserData
+ size=4 align=4
+ base size=4 base align=4
+QObjectUserData (0xb63a199c) 0 nearly-empty
+ vptr=((& QObjectUserData::_ZTV15QObjectUserData) + 8u)
+
+Vtable for QIODevice
+QIODevice::_ZTV9QIODevice: 30u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI9QIODevice)
+8 QIODevice::metaObject
+12 QIODevice::qt_metacast
+16 QIODevice::qt_metacall
+20 QIODevice::~QIODevice
+24 QIODevice::~QIODevice
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QIODevice::isSequential
+60 QIODevice::open
+64 QIODevice::close
+68 QIODevice::pos
+72 QIODevice::size
+76 QIODevice::seek
+80 QIODevice::atEnd
+84 QIODevice::reset
+88 QIODevice::bytesAvailable
+92 QIODevice::bytesToWrite
+96 QIODevice::canReadLine
+100 QIODevice::waitForReadyRead
+104 QIODevice::waitForBytesWritten
+108 __cxa_pure_virtual
+112 QIODevice::readLineData
+116 __cxa_pure_virtual
+
+Class QIODevice
+ size=8 align=4
+ base size=8 base align=4
+QIODevice (0xb63f1180) 0
+ vptr=((& QIODevice::_ZTV9QIODevice) + 8u)
+ QObject (0xb63a1ac8) 0
+ primary-for QIODevice (0xb63f1180)
+
+Vtable for QDataStream
+QDataStream::_ZTV11QDataStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QDataStream)
+8 QDataStream::~QDataStream
+12 QDataStream::~QDataStream
+
+Class QDataStream
+ size=28 align=4
+ base size=28 base align=4
+QDataStream (0xb6218834) 0
+ vptr=((& QDataStream::_ZTV11QDataStream) + 8u)
+
+Class QHashData::Node
+ size=8 align=4
+ base size=8 base align=4
+QHashData::Node (0xb62753fc) 0
+
+Class QHashData
+ size=32 align=4
+ base size=32 base align=4
+QHashData (0xb62753c0) 0
+
+Class QHashDummyValue
+ size=1 align=1
+ base size=0 base align=1
+QHashDummyValue (0xb6275b04) 0 empty
+
+Class QMapData::Node
+ size=8 align=4
+ base size=8 base align=4
+QMapData::Node (0xb62a0258) 0
+
+Class QMapData
+ size=72 align=4
+ base size=72 base align=4
+QMapData (0xb62a021c) 0
+
+Vtable for QSystemLocale
+QSystemLocale::_ZTV13QSystemLocale: 6u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI13QSystemLocale)
+8 QSystemLocale::~QSystemLocale
+12 QSystemLocale::~QSystemLocale
+16 QSystemLocale::query
+20 QSystemLocale::fallbackLocale
+
+Class QSystemLocale
+ size=4 align=4
+ base size=4 base align=4
+QSystemLocale (0xb62a0564) 0 nearly-empty
+ vptr=((& QSystemLocale::_ZTV13QSystemLocale) + 8u)
+
+Class QLocale::Data
+ size=4 align=2
+ base size=4 base align=2
+QLocale::Data (0xb62a05dc) 0
+
+Class QLocale
+ size=4 align=4
+ base size=4 base align=4
+QLocale (0xb62a05a0) 0
+
+Class QTextCodec::ConverterState
+ size=28 align=4
+ base size=28 base align=4
+QTextCodec::ConverterState (0xb62a0c30) 0
+
+Vtable for QTextCodec
+QTextCodec::_ZTV10QTextCodec: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI10QTextCodec)
+8 __cxa_pure_virtual
+12 QTextCodec::aliases
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 QTextCodec::~QTextCodec
+32 QTextCodec::~QTextCodec
+
+Class QTextCodec
+ size=4 align=4
+ base size=4 base align=4
+QTextCodec (0xb62a0bf4) 0 nearly-empty
+ vptr=((& QTextCodec::_ZTV10QTextCodec) + 8u)
+
+Class QTextEncoder
+ size=32 align=4
+ base size=32 base align=4
+QTextEncoder (0xb6028924) 0
+
+Class QTextDecoder
+ size=32 align=4
+ base size=32 base align=4
+QTextDecoder (0xb6028b7c) 0
+
+Class _IO_marker
+ size=12 align=4
+ base size=12 base align=4
+_IO_marker (0xb6028f00) 0
+
+Class _IO_FILE
+ size=148 align=4
+ base size=148 base align=4
+_IO_FILE (0xb6028f3c) 0
+
+Vtable for QTextStream
+QTextStream::_ZTV11QTextStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI11QTextStream)
+8 QTextStream::~QTextStream
+12 QTextStream::~QTextStream
+
+Class QTextStream
+ size=8 align=4
+ base size=8 base align=4
+QTextStream (0xb6028fb4) 0
+ vptr=((& QTextStream::_ZTV11QTextStream) + 8u)
+
+Class QTextStreamManipulator
+ size=24 align=4
+ base size=22 base align=4
+QTextStreamManipulator (0xb609a654) 0
+
+Vtable for QTextIStream
+QTextIStream::_ZTV12QTextIStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QTextIStream)
+8 QTextIStream::~QTextIStream
+12 QTextIStream::~QTextIStream
+
+Class QTextIStream
+ size=8 align=4
+ base size=8 base align=4
+QTextIStream (0xb60a2bc0) 0
+ vptr=((& QTextIStream::_ZTV12QTextIStream) + 8u)
+ QTextStream (0xb60c6834) 0
+ primary-for QTextIStream (0xb60a2bc0)
+
+Vtable for QTextOStream
+QTextOStream::_ZTV12QTextOStream: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QTextOStream)
+8 QTextOStream::~QTextOStream
+12 QTextOStream::~QTextOStream
+
+Class QTextOStream
+ size=8 align=4
+ base size=8 base align=4
+QTextOStream (0xb60a2e80) 0
+ vptr=((& QTextOStream::_ZTV12QTextOStream) + 8u)
+ QTextStream (0xb60c6ec4) 0
+ primary-for QTextOStream (0xb60a2e80)
+
+Class wait
+ size=4 align=4
+ base size=4 base align=4
+wait (0xb60db564) 0
+
+Class timespec
+ size=8 align=4
+ base size=8 base align=4
+timespec (0xb60db708) 0
+
+Class timeval
+ size=8 align=4
+ base size=8 base align=4
+timeval (0xb60db744) 0
+
+Class __pthread_internal_slist
+ size=4 align=4
+ base size=4 base align=4
+__pthread_internal_slist (0xb60db7f8) 0
+
+Class random_data
+ size=28 align=4
+ base size=28 base align=4
+random_data (0xb60dbb04) 0
+
+Class drand48_data
+ size=24 align=4
+ base size=24 base align=4
+drand48_data (0xb60dbb40) 0
+
+Class QVectorData
+ size=16 align=4
+ base size=16 base align=4
+QVectorData (0xb60dbb7c) 0
+
+Class QContiguousCacheData
+ size=24 align=4
+ base size=24 base align=4
+QContiguousCacheData (0xb60dbe88) 0
+
+Class QDebug::Stream
+ size=24 align=4
+ base size=22 base align=4
+QDebug::Stream (0xb5e06078) 0
+
+Class QDebug
+ size=4 align=4
+ base size=4 base align=4
+QDebug (0xb5e0603c) 0
+
+Class QNoDebug
+ size=1 align=1
+ base size=0 base align=1
+QNoDebug (0xb5e57ca8) 0 empty
+
+Class QMetaType
+ size=1 align=1
+ base size=0 base align=1
+QMetaType (0xb5e57f3c) 0 empty
+
+Class QVariant::PrivateShared
+ size=8 align=4
+ base size=8 base align=4
+QVariant::PrivateShared (0xb5ed9d5c) 0
+
+Class QVariant::Private::Data
+ size=8 align=4
+ base size=8 base align=4
+QVariant::Private::Data (0xb5ed9dd4) 0
+
+Class QVariant::Private
+ size=12 align=4
+ base size=12 base align=4
+QVariant::Private (0xb5ed9d98) 0
+
+Class QVariant::Handler
+ size=36 align=4
+ base size=36 base align=4
+QVariant::Handler (0xb5ed9e4c) 0
+
+Class QVariant
+ size=12 align=4
+ base size=12 base align=4
+QVariant (0xb5ed9d20) 0
+
+Class QVariantComparisonHelper
+ size=4 align=4
+ base size=4 base align=4
+QVariantComparisonHelper (0xb5d66708) 0
+
+Class Phonon::ObjectDescriptionData
+ size=8 align=4
+ base size=8 base align=4
+Phonon::ObjectDescriptionData (0xb5d7ae40) 0
+ QSharedData (0xb5d66b7c) 0
+
+Class Phonon::Path
+ size=4 align=4
+ base size=4 base align=4
+Phonon::Path (0xb5dc7474) 0
+
+Vtable for Phonon::MediaNode
+Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon9MediaNodeE)
+8 Phonon::MediaNode::~MediaNode
+12 Phonon::MediaNode::~MediaNode
+
+Class Phonon::MediaNode
+ size=8 align=4
+ base size=8 base align=4
+Phonon::MediaNode (0xb5dc74ec) 0
+ vptr=((& Phonon::MediaNode::_ZTVN6Phonon9MediaNodeE) + 8u)
+
+Vtable for Phonon::AbstractAudioOutput
+Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+8 Phonon::AbstractAudioOutput::metaObject
+12 Phonon::AbstractAudioOutput::qt_metacast
+16 Phonon::AbstractAudioOutput::qt_metacall
+20 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+24 Phonon::AbstractAudioOutput::~AbstractAudioOutput
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon19AbstractAudioOutputE)
+64 Phonon::AbstractAudioOutput::_ZThn8_N6Phonon19AbstractAudioOutputD1Ev
+68 Phonon::AbstractAudioOutput::_ZThn8_N6Phonon19AbstractAudioOutputD0Ev
+
+Class Phonon::AbstractAudioOutput
+ size=16 align=4
+ base size=16 base align=4
+Phonon::AbstractAudioOutput (0xb5de4d70) 0
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 8u)
+ QObject (0xb5dc75a0) 0
+ primary-for Phonon::AbstractAudioOutput (0xb5de4d70)
+ Phonon::MediaNode (0xb5dc75dc) 8
+ vptr=((& Phonon::AbstractAudioOutput::_ZTVN6Phonon19AbstractAudioOutputE) + 64u)
+
+Vtable for Phonon::AbstractMediaStream
+Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractMediaStreamE)
+8 Phonon::AbstractMediaStream::metaObject
+12 Phonon::AbstractMediaStream::qt_metacast
+16 Phonon::AbstractMediaStream::qt_metacall
+20 Phonon::AbstractMediaStream::~AbstractMediaStream
+24 Phonon::AbstractMediaStream::~AbstractMediaStream
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 Phonon::AbstractMediaStream::enoughData
+68 Phonon::AbstractMediaStream::seekStream
+
+Class Phonon::AbstractMediaStream
+ size=12 align=4
+ base size=12 base align=4
+Phonon::AbstractMediaStream (0xb5dd7840) 0
+ vptr=((& Phonon::AbstractMediaStream::_ZTVN6Phonon19AbstractMediaStreamE) + 8u)
+ QObject (0xb5dc7a14) 0
+ primary-for Phonon::AbstractMediaStream (0xb5dd7840)
+
+Vtable for Phonon::AbstractVideoOutput
+Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19AbstractVideoOutputE)
+8 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+12 Phonon::AbstractVideoOutput::~AbstractVideoOutput
+
+Class Phonon::AbstractVideoOutput
+ size=8 align=4
+ base size=8 base align=4
+Phonon::AbstractVideoOutput (0xb5dd7b40) 0
+ vptr=((& Phonon::AbstractVideoOutput::_ZTVN6Phonon19AbstractVideoOutputE) + 8u)
+ Phonon::MediaNode (0xb5dc7c6c) 0
+ primary-for Phonon::AbstractVideoOutput (0xb5dd7b40)
+
+Vtable for Phonon::AddonInterface
+Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE: 6u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon14AddonInterfaceE)
+8 Phonon::AddonInterface::~AddonInterface
+12 Phonon::AddonInterface::~AddonInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+
+Class Phonon::AddonInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AddonInterface (0xb5dc7d98) 0 nearly-empty
+ vptr=((& Phonon::AddonInterface::_ZTVN6Phonon14AddonInterfaceE) + 8u)
+
+Vtable for Phonon::AudioDataOutput
+Phonon::AudioDataOutput::_ZTVN6Phonon15AudioDataOutputE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15AudioDataOutputE)
+8 Phonon::AudioDataOutput::metaObject
+12 Phonon::AudioDataOutput::qt_metacast
+16 Phonon::AudioDataOutput::qt_metacall
+20 Phonon::AudioDataOutput::~AudioDataOutput
+24 Phonon::AudioDataOutput::~AudioDataOutput
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon15AudioDataOutputE)
+64 Phonon::AudioDataOutput::_ZThn8_N6Phonon15AudioDataOutputD1Ev
+68 Phonon::AudioDataOutput::_ZThn8_N6Phonon15AudioDataOutputD0Ev
+
+Class Phonon::AudioDataOutput
+ size=16 align=4
+ base size=16 base align=4
+Phonon::AudioDataOutput (0xb5c110c0) 0
+ vptr=((& Phonon::AudioDataOutput::_ZTVN6Phonon15AudioDataOutputE) + 8u)
+ Phonon::AbstractAudioOutput (0xb5c0bc30) 0
+ primary-for Phonon::AudioDataOutput (0xb5c110c0)
+ QObject (0xb5c0d30c) 0
+ primary-for Phonon::AbstractAudioOutput (0xb5c0bc30)
+ Phonon::MediaNode (0xb5c0d348) 8
+ vptr=((& Phonon::AudioDataOutput::_ZTVN6Phonon15AudioDataOutputE) + 64u)
+
+Vtable for Phonon::AudioDataOutputInterface
+Phonon::AudioDataOutputInterface::_ZTVN6Phonon24AudioDataOutputInterfaceE: 6u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon24AudioDataOutputInterfaceE)
+8 Phonon::AudioDataOutputInterface::~AudioDataOutputInterface
+12 Phonon::AudioDataOutputInterface::~AudioDataOutputInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+
+Class Phonon::AudioDataOutputInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AudioDataOutputInterface (0xb5c0d564) 0 nearly-empty
+ vptr=((& Phonon::AudioDataOutputInterface::_ZTVN6Phonon24AudioDataOutputInterfaceE) + 8u)
+
+Vtable for Phonon::AudioOutput
+Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+8 Phonon::AudioOutput::metaObject
+12 Phonon::AudioOutput::qt_metacast
+16 Phonon::AudioOutput::qt_metacall
+20 Phonon::AudioOutput::~AudioOutput
+24 Phonon::AudioOutput::~AudioOutput
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon11AudioOutputE)
+64 Phonon::AudioOutput::_ZThn8_N6Phonon11AudioOutputD1Ev
+68 Phonon::AudioOutput::_ZThn8_N6Phonon11AudioOutputD0Ev
+
+Class Phonon::AudioOutput
+ size=16 align=4
+ base size=16 base align=4
+Phonon::AudioOutput (0xb5c11780) 0
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 8u)
+ Phonon::AbstractAudioOutput (0xb5c24460) 0
+ primary-for Phonon::AudioOutput (0xb5c11780)
+ QObject (0xb5c0da14) 0
+ primary-for Phonon::AbstractAudioOutput (0xb5c24460)
+ Phonon::MediaNode (0xb5c0da50) 8
+ vptr=((& Phonon::AudioOutput::_ZTVN6Phonon11AudioOutputE) + 64u)
+
+Vtable for Phonon::AudioOutputInterface40
+Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E: 8u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface40E)
+8 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+12 Phonon::AudioOutputInterface40::~AudioOutputInterface40
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface40
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AudioOutputInterface40 (0xb5c0dc6c) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface40::_ZTVN6Phonon22AudioOutputInterface40E) + 8u)
+
+Vtable for Phonon::AudioOutputInterface42
+Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon22AudioOutputInterface42E)
+8 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+12 Phonon::AudioOutputInterface42::~AudioOutputInterface42
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+
+Class Phonon::AudioOutputInterface42
+ size=4 align=4
+ base size=4 base align=4
+Phonon::AudioOutputInterface42 (0xb5c11c40) 0 nearly-empty
+ vptr=((& Phonon::AudioOutputInterface42::_ZTVN6Phonon22AudioOutputInterface42E) + 8u)
+ Phonon::AudioOutputInterface40 (0xb5c0de88) 0 nearly-empty
+ primary-for Phonon::AudioOutputInterface42 (0xb5c11c40)
+
+Vtable for Phonon::BackendCapabilities::Notifier
+Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon19BackendCapabilities8NotifierE)
+8 Phonon::BackendCapabilities::Notifier::metaObject
+12 Phonon::BackendCapabilities::Notifier::qt_metacast
+16 Phonon::BackendCapabilities::Notifier::qt_metacall
+20 Phonon::BackendCapabilities::Notifier::~Notifier
+24 Phonon::BackendCapabilities::Notifier::~Notifier
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class Phonon::BackendCapabilities::Notifier
+ size=8 align=4
+ base size=8 base align=4
+Phonon::BackendCapabilities::Notifier (0xb5c42240) 0
+ vptr=((& Phonon::BackendCapabilities::Notifier::_ZTVN6Phonon19BackendCapabilities8NotifierE) + 8u)
+ QObject (0xb5c3f3fc) 0
+ primary-for Phonon::BackendCapabilities::Notifier (0xb5c42240)
+
+Vtable for Phonon::BackendInterface
+Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE: 12u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon16BackendInterfaceE)
+8 Phonon::BackendInterface::~BackendInterface
+12 Phonon::BackendInterface::~BackendInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+
+Class Phonon::BackendInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::BackendInterface (0xb5c3f528) 0 nearly-empty
+ vptr=((& Phonon::BackendInterface::_ZTVN6Phonon16BackendInterfaceE) + 8u)
+
+Vtable for Phonon::Effect
+Phonon::Effect::_ZTVN6Phonon6EffectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+8 Phonon::Effect::metaObject
+12 Phonon::Effect::qt_metacast
+16 Phonon::Effect::qt_metacall
+20 Phonon::Effect::~Effect
+24 Phonon::Effect::~Effect
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon6EffectE)
+64 Phonon::Effect::_ZThn8_N6Phonon6EffectD1Ev
+68 Phonon::Effect::_ZThn8_N6Phonon6EffectD0Ev
+
+Class Phonon::Effect
+ size=16 align=4
+ base size=16 base align=4
+Phonon::Effect (0xb5c55370) 0
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 8u)
+ QObject (0xb5c3fa8c) 0
+ primary-for Phonon::Effect (0xb5c55370)
+ Phonon::MediaNode (0xb5c3fac8) 8
+ vptr=((& Phonon::Effect::_ZTVN6Phonon6EffectE) + 64u)
+
+Vtable for Phonon::EffectInterface
+Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15EffectInterfaceE)
+8 Phonon::EffectInterface::~EffectInterface
+12 Phonon::EffectInterface::~EffectInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+
+Class Phonon::EffectInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::EffectInterface (0xb5c3fce4) 0 nearly-empty
+ vptr=((& Phonon::EffectInterface::_ZTVN6Phonon15EffectInterfaceE) + 8u)
+
+Class Phonon::EffectParameter
+ size=4 align=4
+ base size=4 base align=4
+Phonon::EffectParameter (0xb5c67258) 0
+
+Class QMargins
+ size=16 align=4
+ base size=16 base align=4
+QMargins (0xb5c673c0) 0
+
+Class QSize
+ size=8 align=4
+ base size=8 base align=4
+QSize (0xb5c984ec) 0
+
+Class QSizeF
+ size=16 align=4
+ base size=16 base align=4
+QSizeF (0xb5cb0f78) 0
+
+Class QPoint
+ size=8 align=4
+ base size=8 base align=4
+QPoint (0xb5cdcb7c) 0
+
+Class QPointF
+ size=16 align=4
+ base size=16 base align=4
+QPointF (0xb5b0512c) 0
+
+Class QRect
+ size=16 align=4
+ base size=16 base align=4
+QRect (0xb5b1e834) 0
+
+Class QRectF
+ size=32 align=4
+ base size=32 base align=4
+QRectF (0xb5b7f474) 0
+
+Vtable for QPaintDevice
+QPaintDevice::_ZTV12QPaintDevice: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI12QPaintDevice)
+8 QPaintDevice::~QPaintDevice
+12 QPaintDevice::~QPaintDevice
+16 QPaintDevice::devType
+20 __cxa_pure_virtual
+24 QPaintDevice::metric
+
+Class QPaintDevice
+ size=8 align=4
+ base size=6 base align=4
+QPaintDevice (0xb5bda1e0) 0
+ vptr=((& QPaintDevice::_ZTV12QPaintDevice) + 8u)
+
+Class QRegExp
+ size=4 align=4
+ base size=4 base align=4
+QRegExp (0xb5bdad98) 0
+
+Class QStringMatcher::Data
+ size=264 align=4
+ base size=264 base align=4
+QStringMatcher::Data (0xb5a0c7bc) 0
+
+Class QStringMatcher
+ size=1036 align=4
+ base size=1036 base align=4
+QStringMatcher (0xb5a0c780) 0
+
+Class QStringList
+ size=4 align=4
+ base size=4 base align=4
+QStringList (0xb5a09300) 0
+ QList<QString> (0xb5a0c8e8) 0
+
+Class QColor
+ size=16 align=4
+ base size=14 base align=4
+QColor (0xb5a3be4c) 0
+
+Class QPolygon
+ size=4 align=4
+ base size=4 base align=4
+QPolygon (0xb5a65a80) 0
+ QVector<QPoint> (0xb5a8a4ec) 0
+
+Class QPolygonF
+ size=4 align=4
+ base size=4 base align=4
+QPolygonF (0xb5ac10c0) 0
+ QVector<QPointF> (0xb5a8aec4) 0
+
+Class QRegion::QRegionData
+ size=16 align=4
+ base size=16 base align=4
+QRegion::QRegionData (0xb5ada834) 0
+
+Class QRegion
+ size=4 align=4
+ base size=4 base align=4
+QRegion (0xb5ada7f8) 0
+
+Class QLine
+ size=16 align=4
+ base size=16 base align=4
+QLine (0xb5adab7c) 0
+
+Class QLineF
+ size=32 align=4
+ base size=32 base align=4
+QLineF (0xb59088ac) 0
+
+Class QMatrix
+ size=48 align=4
+ base size=48 base align=4
+QMatrix (0xb593399c) 0
+
+Class QPainterPath::Element
+ size=20 align=4
+ base size=20 base align=4
+QPainterPath::Element (0xb5961b40) 0
+
+Class QPainterPath
+ size=4 align=4
+ base size=4 base align=4
+QPainterPath (0xb5961b04) 0
+
+Class QPainterPathPrivate
+ size=8 align=4
+ base size=8 base align=4
+QPainterPathPrivate (0xb599f03c) 0
+
+Class QPainterPathStroker
+ size=4 align=4
+ base size=4 base align=4
+QPainterPathStroker (0xb599f168) 0
+
+Class QTransform
+ size=80 align=4
+ base size=80 base align=4
+QTransform (0xb59da0f0) 0
+
+Class QImageTextKeyLang
+ size=8 align=4
+ base size=8 base align=4
+QImageTextKeyLang (0xb583403c) 0
+
+Vtable for QImage
+QImage::_ZTV6QImage: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI6QImage)
+8 QImage::~QImage
+12 QImage::~QImage
+16 QImage::devType
+20 QImage::paintEngine
+24 QImage::metric
+
+Class QImage
+ size=12 align=4
+ base size=12 base align=4
+QImage (0xb5817d00) 0
+ vptr=((& QImage::_ZTV6QImage) + 8u)
+ QPaintDevice (0xb5834a14) 0
+ primary-for QImage (0xb5817d00)
+
+Vtable for QtSharedPointer::ExternalRefCountData
+QtSharedPointer::ExternalRefCountData::_ZTVN15QtSharedPointer20ExternalRefCountDataE: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN15QtSharedPointer20ExternalRefCountDataE)
+8 QtSharedPointer::ExternalRefCountData::~ExternalRefCountData
+12 QtSharedPointer::ExternalRefCountData::~ExternalRefCountData
+16 QtSharedPointer::ExternalRefCountData::destroy
+
+Class QtSharedPointer::ExternalRefCountData
+ size=12 align=4
+ base size=12 base align=4
+QtSharedPointer::ExternalRefCountData (0xb5898744) 0
+ vptr=((& QtSharedPointer::ExternalRefCountData::_ZTVN15QtSharedPointer20ExternalRefCountDataE) + 8u)
+
+Vtable for QtSharedPointer::ExternalRefCountWithDestroyFn
+QtSharedPointer::ExternalRefCountWithDestroyFn::_ZTVN15QtSharedPointer29ExternalRefCountWithDestroyFnE: 5u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN15QtSharedPointer29ExternalRefCountWithDestroyFnE)
+8 QtSharedPointer::ExternalRefCountWithDestroyFn::~ExternalRefCountWithDestroyFn
+12 QtSharedPointer::ExternalRefCountWithDestroyFn::~ExternalRefCountWithDestroyFn
+16 QtSharedPointer::ExternalRefCountWithDestroyFn::destroy
+
+Class QtSharedPointer::ExternalRefCountWithDestroyFn
+ size=16 align=4
+ base size=16 base align=4
+QtSharedPointer::ExternalRefCountWithDestroyFn (0xb58be3c0) 0
+ vptr=((& QtSharedPointer::ExternalRefCountWithDestroyFn::_ZTVN15QtSharedPointer29ExternalRefCountWithDestroyFnE) + 8u)
+ QtSharedPointer::ExternalRefCountData (0xb5898f3c) 0
+ primary-for QtSharedPointer::ExternalRefCountWithDestroyFn (0xb58be3c0)
+
+Vtable for QPixmap
+QPixmap::_ZTV7QPixmap: 7u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QPixmap)
+8 QPixmap::~QPixmap
+12 QPixmap::~QPixmap
+16 QPixmap::devType
+20 QPixmap::paintEngine
+24 QPixmap::metric
+
+Class QPixmap
+ size=12 align=4
+ base size=12 base align=4
+QPixmap (0xb57151c0) 0
+ vptr=((& QPixmap::_ZTV7QPixmap) + 8u)
+ QPaintDevice (0xb58c5474) 0
+ primary-for QPixmap (0xb57151c0)
+
+Class QBrush
+ size=4 align=4
+ base size=4 base align=4
+QBrush (0xb58c5ac8) 0
+
+Class QBrushData
+ size=104 align=4
+ base size=104 base align=4
+QBrushData (0xb58c5c6c) 0
+
+Class QGradient
+ size=56 align=4
+ base size=56 base align=4
+QGradient (0xb576803c) 0
+
+Class QLinearGradient
+ size=56 align=4
+ base size=56 base align=4
+QLinearGradient (0xb5784000) 0
+ QGradient (0xb57682d0) 0
+
+Class QRadialGradient
+ size=56 align=4
+ base size=56 base align=4
+QRadialGradient (0xb5784100) 0
+ QGradient (0xb576830c) 0
+
+Class QConicalGradient
+ size=56 align=4
+ base size=56 base align=4
+QConicalGradient (0xb5784200) 0
+ QGradient (0xb5768348) 0
+
+Class QPalette
+ size=8 align=4
+ base size=8 base align=4
+QPalette (0xb5768384) 0
+
+Class QColorGroup
+ size=8 align=4
+ base size=8 base align=4
+QColorGroup (0xb5784c40) 0
+ QPalette (0xb5768c6c) 0
+
+Class QFont
+ size=8 align=4
+ base size=8 base align=4
+QFont (0xb57c5dd4) 0
+
+Class QFontMetrics
+ size=4 align=4
+ base size=4 base align=4
+QFontMetrics (0xb5602000) 0
+
+Class QFontMetricsF
+ size=4 align=4
+ base size=4 base align=4
+QFontMetricsF (0xb5602258) 0
+
+Class QFontInfo
+ size=4 align=4
+ base size=4 base align=4
+QFontInfo (0xb560230c) 0
+
+Class QSizePolicy
+ size=4 align=4
+ base size=4 base align=4
+QSizePolicy (0xb5602348) 0
+
+Class QCursor
+ size=4 align=4
+ base size=4 base align=4
+QCursor (0xb567521c) 0
+
+Class QKeySequence
+ size=4 align=4
+ base size=4 base align=4
+QKeySequence (0xb5675258) 0
+
+Class QWidgetData
+ size=64 align=4
+ base size=64 base align=4
+QWidgetData (0xb5675474) 0
+
+Vtable for QWidget
+QWidget::_ZTV7QWidget: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI7QWidget)
+8 QWidget::metaObject
+12 QWidget::qt_metacast
+16 QWidget::qt_metacall
+20 QWidget::~QWidget
+24 QWidget::~QWidget
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTI7QWidget)
+232 QWidget::_ZThn8_N7QWidgetD1Ev
+236 QWidget::_ZThn8_N7QWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class QWidget
+ size=20 align=4
+ base size=20 base align=4
+QWidget (0xb56ab730) 0
+ vptr=((& QWidget::_ZTV7QWidget) + 8u)
+ QObject (0xb56754b0) 0
+ primary-for QWidget (0xb56ab730)
+ QPaintDevice (0xb56754ec) 8
+ vptr=((& QWidget::_ZTV7QWidget) + 232u)
+
+Vtable for Phonon::EffectWidget
+Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+8 Phonon::EffectWidget::metaObject
+12 Phonon::EffectWidget::qt_metacast
+16 Phonon::EffectWidget::qt_metacall
+20 Phonon::EffectWidget::~EffectWidget
+24 Phonon::EffectWidget::~EffectWidget
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon12EffectWidgetE)
+232 Phonon::EffectWidget::_ZThn8_N6Phonon12EffectWidgetD1Ev
+236 Phonon::EffectWidget::_ZThn8_N6Phonon12EffectWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::EffectWidget
+ size=24 align=4
+ base size=24 base align=4
+Phonon::EffectWidget (0xb554cac0) 0
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 8u)
+ QWidget (0xb5572000) 0
+ primary-for Phonon::EffectWidget (0xb554cac0)
+ QObject (0xb554fc30) 0
+ primary-for QWidget (0xb5572000)
+ QPaintDevice (0xb554fc6c) 8
+ vptr=((& Phonon::EffectWidget::_ZTVN6Phonon12EffectWidgetE) + 232u)
+
+Vtable for Phonon::GlobalConfig
+Phonon::GlobalConfig::_ZTVN6Phonon12GlobalConfigE: 4u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12GlobalConfigE)
+8 Phonon::GlobalConfig::~GlobalConfig
+12 Phonon::GlobalConfig::~GlobalConfig
+
+Class Phonon::GlobalConfig
+ size=8 align=4
+ base size=8 base align=4
+Phonon::GlobalConfig (0xb554fe10) 0
+ vptr=((& Phonon::GlobalConfig::_ZTVN6Phonon12GlobalConfigE) + 8u)
+
+Vtable for Phonon::MediaController
+Phonon::MediaController::_ZTVN6Phonon15MediaControllerE: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15MediaControllerE)
+8 Phonon::MediaController::metaObject
+12 Phonon::MediaController::qt_metacast
+16 Phonon::MediaController::qt_metacall
+20 Phonon::MediaController::~MediaController
+24 Phonon::MediaController::~MediaController
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class Phonon::MediaController
+ size=12 align=4
+ base size=12 base align=4
+Phonon::MediaController (0xb554ce40) 0
+ vptr=((& Phonon::MediaController::_ZTVN6Phonon15MediaControllerE) + 8u)
+ QObject (0xb554fec4) 0
+ primary-for Phonon::MediaController (0xb554ce40)
+
+Class Phonon::MediaSource
+ size=4 align=4
+ base size=4 base align=4
+Phonon::MediaSource (0xb558e0f0) 0
+
+Vtable for Phonon::MediaObject
+Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+8 Phonon::MediaObject::metaObject
+12 Phonon::MediaObject::qt_metacast
+16 Phonon::MediaObject::qt_metacall
+20 Phonon::MediaObject::~MediaObject
+24 Phonon::MediaObject::~MediaObject
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon11MediaObjectE)
+64 Phonon::MediaObject::_ZThn8_N6Phonon11MediaObjectD1Ev
+68 Phonon::MediaObject::_ZThn8_N6Phonon11MediaObjectD0Ev
+
+Class Phonon::MediaObject
+ size=16 align=4
+ base size=16 base align=4
+Phonon::MediaObject (0xb55aee60) 0
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 8u)
+ QObject (0xb558e168) 0
+ primary-for Phonon::MediaObject (0xb55aee60)
+ Phonon::MediaNode (0xb558e1a4) 8
+ vptr=((& Phonon::MediaObject::_ZTVN6Phonon11MediaObjectE) + 64u)
+
+Vtable for Phonon::MediaObjectInterface
+Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE: 25u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20MediaObjectInterfaceE)
+8 Phonon::MediaObjectInterface::~MediaObjectInterface
+12 Phonon::MediaObjectInterface::~MediaObjectInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 __cxa_pure_virtual
+76 __cxa_pure_virtual
+80 Phonon::MediaObjectInterface::remainingTime
+84 __cxa_pure_virtual
+88 __cxa_pure_virtual
+92 __cxa_pure_virtual
+96 __cxa_pure_virtual
+
+Class Phonon::MediaObjectInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::MediaObjectInterface (0xb558e3c0) 0 nearly-empty
+ vptr=((& Phonon::MediaObjectInterface::_ZTVN6Phonon20MediaObjectInterfaceE) + 8u)
+
+Class QModelIndex
+ size=16 align=4
+ base size=16 base align=4
+QModelIndex (0xb558e99c) 0
+
+Class QPersistentModelIndex
+ size=4 align=4
+ base size=4 base align=4
+QPersistentModelIndex (0xb55dae4c) 0
+
+Vtable for QAbstractItemModel
+QAbstractItemModel::_ZTV18QAbstractItemModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI18QAbstractItemModel)
+8 QAbstractItemModel::metaObject
+12 QAbstractItemModel::qt_metacast
+16 QAbstractItemModel::qt_metacall
+20 QAbstractItemModel::~QAbstractItemModel
+24 QAbstractItemModel::~QAbstractItemModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 QAbstractItemModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractItemModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractItemModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractItemModel (0xb53da440) 0
+ vptr=((& QAbstractItemModel::_ZTV18QAbstractItemModel) + 8u)
+ QObject (0xb55dafb4) 0
+ primary-for QAbstractItemModel (0xb53da440)
+
+Vtable for QAbstractTableModel
+QAbstractTableModel::_ZTV19QAbstractTableModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI19QAbstractTableModel)
+8 QAbstractTableModel::metaObject
+12 QAbstractTableModel::qt_metacast
+16 QAbstractTableModel::qt_metacall
+20 QAbstractTableModel::~QAbstractTableModel
+24 QAbstractTableModel::~QAbstractTableModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QAbstractTableModel::index
+60 QAbstractTableModel::parent
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+72 QAbstractTableModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractTableModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractTableModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractTableModel (0xb53daa80) 0
+ vptr=((& QAbstractTableModel::_ZTV19QAbstractTableModel) + 8u)
+ QAbstractItemModel (0xb53daac0) 0
+ primary-for QAbstractTableModel (0xb53daa80)
+ QObject (0xb5406924) 0
+ primary-for QAbstractItemModel (0xb53daac0)
+
+Vtable for QAbstractListModel
+QAbstractListModel::_ZTV18QAbstractListModel: 42u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTI18QAbstractListModel)
+8 QAbstractListModel::metaObject
+12 QAbstractListModel::qt_metacast
+16 QAbstractListModel::qt_metacall
+20 QAbstractListModel::~QAbstractListModel
+24 QAbstractListModel::~QAbstractListModel
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QAbstractListModel::index
+60 QAbstractListModel::parent
+64 __cxa_pure_virtual
+68 QAbstractListModel::columnCount
+72 QAbstractListModel::hasChildren
+76 __cxa_pure_virtual
+80 QAbstractItemModel::setData
+84 QAbstractItemModel::headerData
+88 QAbstractItemModel::setHeaderData
+92 QAbstractItemModel::itemData
+96 QAbstractItemModel::setItemData
+100 QAbstractItemModel::mimeTypes
+104 QAbstractItemModel::mimeData
+108 QAbstractListModel::dropMimeData
+112 QAbstractItemModel::supportedDropActions
+116 QAbstractItemModel::insertRows
+120 QAbstractItemModel::insertColumns
+124 QAbstractItemModel::removeRows
+128 QAbstractItemModel::removeColumns
+132 QAbstractItemModel::fetchMore
+136 QAbstractItemModel::canFetchMore
+140 QAbstractItemModel::flags
+144 QAbstractItemModel::sort
+148 QAbstractItemModel::buddy
+152 QAbstractItemModel::match
+156 QAbstractItemModel::span
+160 QAbstractItemModel::submit
+164 QAbstractItemModel::revert
+
+Class QAbstractListModel
+ size=8 align=4
+ base size=8 base align=4
+QAbstractListModel (0xb53dad00) 0
+ vptr=((& QAbstractListModel::_ZTV18QAbstractListModel) + 8u)
+ QAbstractItemModel (0xb53dad40) 0
+ primary-for QAbstractListModel (0xb53dad00)
+ QObject (0xb5406a50) 0
+ primary-for QAbstractItemModel (0xb53dad40)
+
+Class Phonon::ObjectDescriptionModelData
+ size=4 align=4
+ base size=4 base align=4
+Phonon::ObjectDescriptionModelData (0xb5432924) 0
+
+Vtable for Phonon::PlatformPlugin
+Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE: 16u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon14PlatformPluginE)
+8 Phonon::PlatformPlugin::~PlatformPlugin
+12 Phonon::PlatformPlugin::~PlatformPlugin
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 Phonon::PlatformPlugin::deviceAccessListFor
+
+Class Phonon::PlatformPlugin
+ size=4 align=4
+ base size=4 base align=4
+Phonon::PlatformPlugin (0xb5432a8c) 0 nearly-empty
+ vptr=((& Phonon::PlatformPlugin::_ZTVN6Phonon14PlatformPluginE) + 8u)
+
+Vtable for Phonon::PulseSupport
+Phonon::PulseSupport::_ZTVN6Phonon12PulseSupportE: 14u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12PulseSupportE)
+8 Phonon::PulseSupport::metaObject
+12 Phonon::PulseSupport::qt_metacast
+16 Phonon::PulseSupport::qt_metacall
+20 Phonon::PulseSupport::~PulseSupport
+24 Phonon::PulseSupport::~PulseSupport
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+
+Class Phonon::PulseSupport
+ size=12 align=4
+ base size=9 base align=4
+Phonon::PulseSupport (0xb547f340) 0
+ vptr=((& Phonon::PulseSupport::_ZTVN6Phonon12PulseSupportE) + 8u)
+ QObject (0xb549903c) 0
+ primary-for Phonon::PulseSupport (0xb547f340)
+
+Vtable for Phonon::SeekSlider
+Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+8 Phonon::SeekSlider::metaObject
+12 Phonon::SeekSlider::qt_metacast
+16 Phonon::SeekSlider::qt_metacall
+20 Phonon::SeekSlider::~SeekSlider
+24 Phonon::SeekSlider::~SeekSlider
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon10SeekSliderE)
+232 Phonon::SeekSlider::_ZThn8_N6Phonon10SeekSliderD1Ev
+236 Phonon::SeekSlider::_ZThn8_N6Phonon10SeekSliderD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::SeekSlider
+ size=24 align=4
+ base size=24 base align=4
+Phonon::SeekSlider (0xb547f580) 0
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 8u)
+ QWidget (0xb549e910) 0
+ primary-for Phonon::SeekSlider (0xb547f580)
+ QObject (0xb5499168) 0
+ primary-for QWidget (0xb549e910)
+ QPaintDevice (0xb54991a4) 8
+ vptr=((& Phonon::SeekSlider::_ZTVN6Phonon10SeekSliderE) + 232u)
+
+Vtable for Phonon::StreamInterface
+Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE: 8u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon15StreamInterfaceE)
+8 Phonon::StreamInterface::~StreamInterface
+12 Phonon::StreamInterface::~StreamInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+
+Class Phonon::StreamInterface
+ size=8 align=4
+ base size=8 base align=4
+Phonon::StreamInterface (0xb5499348) 0
+ vptr=((& Phonon::StreamInterface::_ZTVN6Phonon15StreamInterfaceE) + 8u)
+
+Vtable for Phonon::VideoPlayer
+Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+8 Phonon::VideoPlayer::metaObject
+12 Phonon::VideoPlayer::qt_metacast
+16 Phonon::VideoPlayer::qt_metacall
+20 Phonon::VideoPlayer::~VideoPlayer
+24 Phonon::VideoPlayer::~VideoPlayer
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon11VideoPlayerE)
+232 Phonon::VideoPlayer::_ZThn8_N6Phonon11VideoPlayerD1Ev
+236 Phonon::VideoPlayer::_ZThn8_N6Phonon11VideoPlayerD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VideoPlayer
+ size=24 align=4
+ base size=24 base align=4
+Phonon::VideoPlayer (0xb547fac0) 0
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 8u)
+ QWidget (0xb54ba1e0) 0
+ primary-for Phonon::VideoPlayer (0xb547fac0)
+ QObject (0xb5499708) 0
+ primary-for QWidget (0xb54ba1e0)
+ QPaintDevice (0xb5499744) 8
+ vptr=((& Phonon::VideoPlayer::_ZTVN6Phonon11VideoPlayerE) + 232u)
+
+Vtable for Phonon::VideoWidget
+Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE: 67u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+8 Phonon::VideoWidget::metaObject
+12 Phonon::VideoWidget::qt_metacast
+16 Phonon::VideoWidget::qt_metacall
+20 Phonon::VideoWidget::~VideoWidget
+24 Phonon::VideoWidget::~VideoWidget
+28 Phonon::VideoWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 Phonon::VideoWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+232 Phonon::VideoWidget::_ZThn8_N6Phonon11VideoWidgetD1Ev
+236 Phonon::VideoWidget::_ZThn8_N6Phonon11VideoWidgetD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+252 (int (*)(...))-0x000000014
+256 (int (*)(...))(& _ZTIN6Phonon11VideoWidgetE)
+260 Phonon::VideoWidget::_ZThn20_N6Phonon11VideoWidgetD1Ev
+264 Phonon::VideoWidget::_ZThn20_N6Phonon11VideoWidgetD0Ev
+
+Class Phonon::VideoWidget
+ size=28 align=4
+ base size=28 base align=4
+Phonon::VideoWidget (0xb54bfaa0) 0
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 8u)
+ QWidget (0xb54bfaf0) 0
+ primary-for Phonon::VideoWidget (0xb54bfaa0)
+ QObject (0xb5499870) 0
+ primary-for QWidget (0xb54bfaf0)
+ QPaintDevice (0xb54998ac) 8
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 232u)
+ Phonon::AbstractVideoOutput (0xb547fd00) 20
+ vptr=((& Phonon::VideoWidget::_ZTVN6Phonon11VideoWidgetE) + 260u)
+ Phonon::MediaNode (0xb54998e8) 20
+ primary-for Phonon::AbstractVideoOutput (0xb547fd00)
+
+Vtable for Phonon::VideoWidgetInterface
+Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE: 17u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20VideoWidgetInterfaceE)
+8 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+12 Phonon::VideoWidgetInterface::~VideoWidgetInterface
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+
+Class Phonon::VideoWidgetInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::VideoWidgetInterface (0xb5499b04) 0 nearly-empty
+ vptr=((& Phonon::VideoWidgetInterface::_ZTVN6Phonon20VideoWidgetInterfaceE) + 8u)
+
+Vtable for Phonon::VideoWidgetInterface44
+Phonon::VideoWidgetInterface44::_ZTVN6Phonon22VideoWidgetInterface44E: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon22VideoWidgetInterface44E)
+8 Phonon::VideoWidgetInterface44::~VideoWidgetInterface44
+12 Phonon::VideoWidgetInterface44::~VideoWidgetInterface44
+16 __cxa_pure_virtual
+20 __cxa_pure_virtual
+24 __cxa_pure_virtual
+28 __cxa_pure_virtual
+32 __cxa_pure_virtual
+36 __cxa_pure_virtual
+40 __cxa_pure_virtual
+44 __cxa_pure_virtual
+48 __cxa_pure_virtual
+52 __cxa_pure_virtual
+56 __cxa_pure_virtual
+60 __cxa_pure_virtual
+64 __cxa_pure_virtual
+68 __cxa_pure_virtual
+
+Class Phonon::VideoWidgetInterface44
+ size=4 align=4
+ base size=4 base align=4
+Phonon::VideoWidgetInterface44 (0xb52dd1c0) 0 nearly-empty
+ vptr=((& Phonon::VideoWidgetInterface44::_ZTVN6Phonon22VideoWidgetInterface44E) + 8u)
+ Phonon::VideoWidgetInterface (0xb5499d20) 0 nearly-empty
+ primary-for Phonon::VideoWidgetInterface44 (0xb52dd1c0)
+
+Vtable for Phonon::VolumeFaderEffect
+Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE: 18u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+8 Phonon::VolumeFaderEffect::metaObject
+12 Phonon::VolumeFaderEffect::qt_metacast
+16 Phonon::VolumeFaderEffect::qt_metacall
+20 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+24 Phonon::VolumeFaderEffect::~VolumeFaderEffect
+28 QObject::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 (int (*)(...))-0x000000008
+60 (int (*)(...))(& _ZTIN6Phonon17VolumeFaderEffectE)
+64 Phonon::VolumeFaderEffect::_ZThn8_N6Phonon17VolumeFaderEffectD1Ev
+68 Phonon::VolumeFaderEffect::_ZThn8_N6Phonon17VolumeFaderEffectD0Ev
+
+Class Phonon::VolumeFaderEffect
+ size=16 align=4
+ base size=16 base align=4
+Phonon::VolumeFaderEffect (0xb52dd840) 0
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 8u)
+ Phonon::Effect (0xb52e68c0) 0
+ primary-for Phonon::VolumeFaderEffect (0xb52dd840)
+ QObject (0xb52e730c) 0
+ primary-for Phonon::Effect (0xb52e68c0)
+ Phonon::MediaNode (0xb52e7348) 8
+ vptr=((& Phonon::VolumeFaderEffect::_ZTVN6Phonon17VolumeFaderEffectE) + 64u)
+
+Vtable for Phonon::VolumeFaderInterface
+Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE: 9u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon20VolumeFaderInterfaceE)
+8 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+12 Phonon::VolumeFaderInterface::~VolumeFaderInterface
+16 Phonon::VolumeFaderInterface::volume
+20 Phonon::VolumeFaderInterface::setVolume
+24 Phonon::VolumeFaderInterface::fadeCurve
+28 Phonon::VolumeFaderInterface::setFadeCurve
+32 Phonon::VolumeFaderInterface::fadeTo
+
+Class Phonon::VolumeFaderInterface
+ size=4 align=4
+ base size=4 base align=4
+Phonon::VolumeFaderInterface (0xb52e7564) 0 nearly-empty
+ vptr=((& Phonon::VolumeFaderInterface::_ZTVN6Phonon20VolumeFaderInterfaceE) + 8u)
+
+Vtable for Phonon::VolumeSlider
+Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE: 63u entries
+0 (int (*)(...))0
+4 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+8 Phonon::VolumeSlider::metaObject
+12 Phonon::VolumeSlider::qt_metacast
+16 Phonon::VolumeSlider::qt_metacall
+20 Phonon::VolumeSlider::~VolumeSlider
+24 Phonon::VolumeSlider::~VolumeSlider
+28 QWidget::event
+32 QObject::eventFilter
+36 QObject::timerEvent
+40 QObject::childEvent
+44 QObject::customEvent
+48 QObject::connectNotify
+52 QObject::disconnectNotify
+56 QWidget::devType
+60 QWidget::setVisible
+64 QWidget::sizeHint
+68 QWidget::minimumSizeHint
+72 QWidget::heightForWidth
+76 QWidget::paintEngine
+80 QWidget::mousePressEvent
+84 QWidget::mouseReleaseEvent
+88 QWidget::mouseDoubleClickEvent
+92 QWidget::mouseMoveEvent
+96 QWidget::wheelEvent
+100 QWidget::keyPressEvent
+104 QWidget::keyReleaseEvent
+108 QWidget::focusInEvent
+112 QWidget::focusOutEvent
+116 QWidget::enterEvent
+120 QWidget::leaveEvent
+124 QWidget::paintEvent
+128 QWidget::moveEvent
+132 QWidget::resizeEvent
+136 QWidget::closeEvent
+140 QWidget::contextMenuEvent
+144 QWidget::tabletEvent
+148 QWidget::actionEvent
+152 QWidget::dragEnterEvent
+156 QWidget::dragMoveEvent
+160 QWidget::dragLeaveEvent
+164 QWidget::dropEvent
+168 QWidget::showEvent
+172 QWidget::hideEvent
+176 QWidget::x11Event
+180 QWidget::changeEvent
+184 QWidget::metric
+188 QWidget::inputMethodEvent
+192 QWidget::inputMethodQuery
+196 QWidget::focusNextPrevChild
+200 QWidget::styleChange
+204 QWidget::enabledChange
+208 QWidget::paletteChange
+212 QWidget::fontChange
+216 QWidget::windowActivationChange
+220 QWidget::languageChange
+224 (int (*)(...))-0x000000008
+228 (int (*)(...))(& _ZTIN6Phonon12VolumeSliderE)
+232 Phonon::VolumeSlider::_ZThn8_N6Phonon12VolumeSliderD1Ev
+236 Phonon::VolumeSlider::_ZThn8_N6Phonon12VolumeSliderD0Ev
+240 QWidget::_ZThn8_NK7QWidget7devTypeEv
+244 QWidget::_ZThn8_NK7QWidget11paintEngineEv
+248 QWidget::_ZThn8_NK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE
+
+Class Phonon::VolumeSlider
+ size=24 align=4
+ base size=24 base align=4
+Phonon::VolumeSlider (0xb5301140) 0
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 8u)
+ QWidget (0xb52fc640) 0
+ primary-for Phonon::VolumeSlider (0xb5301140)
+ QObject (0xb52e7ac8) 0
+ primary-for QWidget (0xb52fc640)
+ QPaintDevice (0xb52e7b04) 8
+ vptr=((& Phonon::VolumeSlider::_ZTVN6Phonon12VolumeSliderE) + 232u)
+
diff --git a/tests/auto/mediaobject/.gitignore b/tests/auto/mediaobject/.gitignore
new file mode 100644
index 0000000..2b4d356
--- /dev/null
+++ b/tests/auto/mediaobject/.gitignore
@@ -0,0 +1 @@
+tst_mediaobject
diff --git a/tests/auto/mediaobject/dummy/README b/tests/auto/mediaobject/dummy/README
new file mode 100644
index 0000000..43f69d9
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/README
@@ -0,0 +1 @@
+This is a dummy backend for phonon, used for testing purposes.
diff --git a/tests/auto/mediaobject/dummy/audiooutput.cpp b/tests/auto/mediaobject/dummy/audiooutput.cpp
new file mode 100644
index 0000000..2645e20
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/audiooutput.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 test suite module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "audiooutput.h"
+#include "backend.h"
+#include <phonon/audiooutput.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Dummy
+{
+AudioOutput::AudioOutput(Backend *backend, QObject *parent)
+ : QObject(parent)
+{
+ Q_UNUSED(backend)
+
+ m_volumeLevel = 100;
+}
+
+AudioOutput::~AudioOutput()
+{
+}
+
+qreal AudioOutput::volume() const
+{
+ return m_volumeLevel;
+}
+
+int AudioOutput::outputDevice() const
+{
+ return m_device;
+}
+
+void AudioOutput::setVolume(qreal newVolume)
+{
+ m_volumeLevel = newVolume;
+ emit volumeChanged(newVolume);
+}
+
+bool AudioOutput::setOutputDevice(int newDevice)
+{
+ return (newDevice == 0);
+}
+
+bool AudioOutput::setOutputDevice(const AudioOutputDevice &newDevice)
+{
+ return setOutputDevice(newDevice.index());
+}
+
+}
+} //namespace Phonon::Dummy
+
+QT_END_NAMESPACE
+#include "moc_audiooutput.cpp"
diff --git a/tests/auto/mediaobject/dummy/audiooutput.h b/tests/auto/mediaobject/dummy/audiooutput.h
new file mode 100644
index 0000000..4acdd8a
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/audiooutput.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHONON_DUMMY_AUDIOOUTPUT_H
+#define PHONON_DUMMY_AUDIOOUTPUT_H
+
+#include "backend.h"
+#include <phonon/audiooutputinterface.h>
+#include <phonon/phononnamespace.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Dummy
+{
+class AudioOutput : public QObject, public AudioOutputInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioOutputInterface)
+public:
+ AudioOutput(Backend *backend, QObject *parent);
+ ~AudioOutput();
+
+ qreal volume() const;
+ int outputDevice() const;
+ void setVolume(qreal newVolume);
+ bool setOutputDevice(int newDevice);
+ bool setOutputDevice(const AudioOutputDevice &newDevice);
+
+Q_SIGNALS:
+ void volumeChanged(qreal newVolume);
+ void audioDeviceFailed();
+
+private:
+ qreal m_volumeLevel;
+ int m_device;
+};
+}
+} //namespace Phonon::Dummy
+
+QT_END_NAMESPACE
+
+#endif // PHONON_DUMMY_AUDIOOUTPUT_H
diff --git a/tests/auto/mediaobject/dummy/backend.cpp b/tests/auto/mediaobject/dummy/backend.cpp
new file mode 100644
index 0000000..1db89cc
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/backend.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** 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 test suite module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "audiooutput.h"
+#include "mediaobject.h"
+#include "videowidget.h"
+
+#include "backend.h"
+
+#include <QtCore/QSet>
+#include <QtCore/QVariant>
+#include <QtCore/QtPlugin>
+
+QT_BEGIN_NAMESPACE
+
+Q_EXPORT_PLUGIN2(phonon_dummy, Phonon::Dummy::Backend)
+
+namespace Phonon
+{
+namespace Dummy
+{
+
+Backend::Backend(QObject *parent, const QVariantList &)
+ : QObject(parent)
+{
+ qWarning()<<"Using TEST Phonon backend";
+}
+
+Backend::~Backend()
+{
+}
+
+/***
+ * !reimp
+ */
+QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
+{
+ Q_UNUSED(args)
+
+ switch (c) {
+ case MediaObjectClass:
+ return new MediaObject(this, parent);
+
+ case AudioOutputClass: {
+ AudioOutput *ao = new AudioOutput(this, parent);
+ m_audioOutputs.append(ao);
+ return ao;
+ }
+ case VideoWidgetClass: {
+ QWidget *widget = qobject_cast<QWidget*>(parent);
+ return new VideoWidget(this, widget);
+ }
+ default:
+ qWarning("createObject() : Backend object not available");
+ }
+ return 0;
+}
+
+/***
+ * !reimp
+ */
+QStringList Backend::availableMimeTypes() const
+{
+ QStringList availableMimeTypes;
+ // audio *.wav and *.mp3 files
+ availableMimeTypes << QLatin1String("audio/x-mp3");
+ availableMimeTypes << QLatin1String("audio/x-wav");
+
+ // video *.ogv, *.mp4, *.avi (some)
+
+ availableMimeTypes << QLatin1String("video/mpeg");
+ availableMimeTypes << QLatin1String("video/ogg");
+ availableMimeTypes << QLatin1String("video/mp4");
+
+ return availableMimeTypes;
+}
+
+/***
+ * !reimp
+ */
+QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+ QList<int> list;
+
+ if(type == Phonon::AudioOutputDeviceType)
+ list.append(0);
+
+ return list;
+}
+
+/***
+ * !reimp
+ */
+QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+ Q_UNUSED(index);
+ QHash<QByteArray, QVariant> ret;
+
+ if(type == Phonon::AudioOutputDeviceType)
+ ret["name"] = QLatin1String("default audio device");
+
+ return ret;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::startConnectionChange(QSet<QObject *> objects)
+{
+ Q_UNUSED(objects)
+
+ return true;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::connectNodes(QObject *source, QObject *sink)
+{
+ Q_UNUSED(source)
+ Q_UNUSED(sink)
+
+ return true;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::disconnectNodes(QObject *source, QObject *sink)
+{
+ Q_UNUSED(source)
+ Q_UNUSED(sink)
+
+ return true;
+}
+
+/***
+ * !reimp
+ */
+bool Backend::endConnectionChange(QSet<QObject *> objects)
+{
+ Q_UNUSED(objects)
+
+ return true;
+}
+
+}
+}
+
+QT_END_NAMESPACE
+
+#include "moc_backend.cpp"
diff --git a/tests/auto/mediaobject/dummy/backend.h b/tests/auto/mediaobject/dummy/backend.h
new file mode 100644
index 0000000..40833ea
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/backend.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHONON_DUMMY_BACKEND_H
+#define PHONON_DUMMY_BACKEND_H
+
+#include <phonon/objectdescription.h>
+#include <phonon/backendinterface.h>
+
+#include <phonon/medianode.h>
+
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+#include <QtCore/QStringList>
+#include <QtCore/QTimer>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Dummy
+{
+class AudioOutput;
+class MediaObject;
+
+class Backend : public QObject, public BackendInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::BackendInterface)
+
+public:
+ Backend(QObject *parent = 0, const QVariantList & = QVariantList());
+ virtual ~Backend();
+
+ QObject *createObject(BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
+
+ QStringList availableMimeTypes() const;
+
+ QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+
+ bool startConnectionChange(QSet<QObject *>);
+ bool connectNodes(QObject *, QObject *);
+ bool disconnectNodes(QObject *, QObject *);
+ bool endConnectionChange(QSet<QObject *>);
+
+Q_SIGNALS:
+ void objectDescriptionChanged(ObjectDescriptionType);
+
+private:
+ QList<QPointer<AudioOutput> > m_audioOutputs;
+};
+}
+} // namespace Phonon::Dummy
+
+QT_END_NAMESPACE
+
+#endif // PHONON_DUMMY_BACKEND_H
diff --git a/tests/auto/mediaobject/dummy/dummy.pro b/tests/auto/mediaobject/dummy/dummy.pro
new file mode 100644
index 0000000..9797500
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/dummy.pro
@@ -0,0 +1,23 @@
+TEMPLATE = lib
+
+isEmpty(QT_MAJOR_VERSION) {
+ VERSION=4.7.4
+} else {
+ VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}
+}
+CONFIG += qt plugin
+
+TARGET = phonon_dummy
+DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend
+DEPENDPATH += .
+INCLUDEPATH += .
+
+QT += phonon
+
+
+# Input
+HEADERS += backend.h audiooutput.h mediaobject.h videowidget.h
+SOURCES += backend.cpp audiooutput.cpp mediaobject.cpp videowidget.cpp
+
+target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend
+INSTALLS += target
diff --git a/tests/auto/mediaobject/dummy/mediaobject.cpp b/tests/auto/mediaobject/dummy/mediaobject.cpp
new file mode 100644
index 0000000..98ab94f
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/mediaobject.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** 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 test suite module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mediaobject.h"
+#include "backend.h"
+
+#include <QtCore>
+#include <QtCore/QTimer>
+#include <QtCore/QVector>
+#include <QtCore/QFile>
+#include <QtCore/QByteRef>
+#include <QtCore/QStringList>
+#include <QtCore/QEvent>
+#include <QApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Dummy
+{
+
+static const char* riffId = "RIFF";
+
+MediaObject::MediaObject(Backend *backend, QObject *parent)
+ : QObject(parent)
+ , m_resumeState(false)
+ , m_oldState(Phonon::LoadingState)
+ , m_oldPos(0)
+ , currentPos(0)
+{
+ Q_UNUSED(backend)
+
+ m_error = Phonon::NoError;
+ m_tickInterval = 100; // 100ms
+ m_totalTime = 26000; // 26s
+ m_prefinishMark = 0;
+ m_transitionTime = 100; //100ms
+ m_hasVideo = false;
+ m_prefinishMarkReachedNotEmitted = true;
+ m_aboutToFinishEmitted = false;
+ m_pendingState = Phonon::LoadingState;
+ m_state = Phonon::LoadingState;
+ m_pendingState = Phonon::LoadingState;
+ m_tickTimer = new QTimer(this);
+ connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
+}
+
+MediaObject::~MediaObject()
+{
+ delete m_tickTimer;
+}
+
+QString stateString(const Phonon::State &state)
+{
+ switch (state) {
+ case Phonon::LoadingState:
+ return QString("LoadingState");
+ case Phonon::StoppedState:
+ return QString("StoppedState");
+ case Phonon::PlayingState:
+ return QString("PlayingState");
+ case Phonon::BufferingState:
+ return QString("BufferingState");
+ case Phonon::PausedState:
+ return QString("PausedState");
+ case Phonon::ErrorState:
+ return QString("ErrorState");
+ }
+ return QString();
+}
+
+void MediaObject::saveState()
+{
+ if (m_resumeState)
+ return;
+
+ if (m_pendingState == Phonon::PlayingState || m_pendingState == Phonon::PausedState) {
+ m_resumeState = true;
+ m_oldState = m_pendingState;
+ m_oldPos = currentPos;
+ }
+}
+
+void MediaObject::resumeState()
+{
+ if (m_resumeState)
+ QMetaObject::invokeMethod(this, "setState", Qt::QueuedConnection, Q_ARG(State, m_oldState));
+}
+
+/**
+ * !reimp
+ */
+State MediaObject::state() const
+{
+ return m_state;
+}
+
+/**
+ * !reimp
+ */
+bool MediaObject::hasVideo() const
+{
+ return m_hasVideo;
+}
+
+/**
+ * !reimp
+ */
+bool MediaObject::isSeekable() const
+{
+ return true;
+}
+
+/**
+ * !reimp
+ */
+qint64 MediaObject::currentTime() const
+{
+ if (m_resumeState)
+ return m_oldPos;
+
+ switch (state()) {
+ case Phonon::PausedState:
+ case Phonon::BufferingState:
+ case Phonon::PlayingState:
+ return currentPos;
+ case Phonon::StoppedState:
+ case Phonon::LoadingState:
+ return 0;
+ case Phonon::ErrorState:
+ break;
+ }
+ return -1;
+}
+
+/**
+ * !reimp
+ */
+qint32 MediaObject::tickInterval() const
+{
+ return m_tickInterval;
+}
+
+/**
+ * !reimp
+ */
+void MediaObject::setTickInterval(qint32 newTickInterval)
+{
+ m_tickInterval = newTickInterval;
+ if (m_tickInterval <= 0) {
+ m_tickTimer->setInterval(100);
+ } else
+ m_tickTimer->setInterval(newTickInterval);
+}
+
+/**
+ * !reimp
+ */
+void MediaObject::play()
+{
+ if(m_state == Phonon::PlayingState)
+ return;
+ if(m_state == Phonon::ErrorState)
+ return;
+
+ if(m_state != Phonon::PausedState)
+ m_tickTimer->stop();
+
+ m_prefinishMarkReachedNotEmitted = true;
+ m_aboutToFinishEmitted = false;
+
+ setState(Phonon::PlayingState);
+ m_resumeState = false;
+ m_tickTimer->start();
+}
+
+/**
+ * !reimp
+ */
+QString MediaObject::errorString() const
+{
+ return m_errorString;
+}
+
+/**
+ * !reimp
+ */
+Phonon::ErrorType MediaObject::errorType() const
+{
+ return m_error;
+}
+
+void MediaObject::setState(State newstate)
+{
+ if (m_state == newstate)
+ return;
+
+ switch (newstate) {
+ case Phonon::PausedState:
+ m_pendingState = Phonon::PausedState;
+ emit stateChanged(newstate, m_state);
+ m_state = newstate;
+ break;
+ case Phonon::StoppedState:
+ m_pendingState = Phonon::StoppedState;
+ emit stateChanged(newstate, m_state);
+ m_state = newstate;
+ break;
+ case Phonon::PlayingState:
+ m_pendingState = Phonon::PlayingState;
+ emit stateChanged(newstate, m_state);
+ m_state = newstate;
+ break;
+ case Phonon::ErrorState:
+ emit stateChanged(newstate, m_state);
+ m_state = newstate;
+ break;
+ case Phonon::BufferingState:
+ case Phonon::LoadingState:
+ emit stateChanged(newstate, m_state);
+ m_state = newstate;
+ break;
+ }
+}
+
+qint64 MediaObject::totalTime() const
+{
+ return m_totalTime;
+}
+
+qint32 MediaObject::prefinishMark() const
+{
+ return m_prefinishMark;
+}
+
+qint32 MediaObject::transitionTime() const
+{
+ return m_transitionTime;
+}
+
+void MediaObject::setTransitionTime(qint32 time)
+{
+ m_transitionTime = time;
+}
+
+qint64 MediaObject::remainingTime() const
+{
+ if(currentTime() > totalTime())
+ return 0;
+
+ return totalTime() - currentTime();
+}
+
+MediaSource MediaObject::source() const
+{
+ return m_source;
+}
+
+void MediaObject::setNextSource(const MediaSource &source)
+{
+ if (source.type() == MediaSource::Invalid &&
+ source.type() == MediaSource::Empty)
+ return;
+ m_nextSource = source;
+}
+
+/*
+ * !reimp
+ */
+void MediaObject::setSource(const MediaSource &source)
+{
+ QMultiMap<QString, QString> ret;
+
+ ret.insert(QLatin1String("ARTIST"), "Nokia Dude");
+ ret.insert(QLatin1String("ALBUM"), "Sound of silence");
+ ret.insert(QLatin1String("DATE"), "2009");
+
+ m_error = Phonon::NoError;
+ setState(Phonon::LoadingState);
+
+ m_source = source;
+ currentPos = 0;
+
+ if((source.fileName().contains(".avi")) ||
+ (source.fileName().contains(".mp4"))) {
+ m_hasVideo = true;
+ emit hasVideoChanged(m_hasVideo);
+ }
+ if(source.fileName().contains(".wav")) {
+ QFile file(source.fileName());
+ if (file.open(QIODevice::ReadOnly)) {
+ int len = file.read((char*)&header, sizeof(CombinedHeader));
+ if(len == sizeof(CombinedHeader)) {
+ if(memcmp(&header.riff.descriptor.id, riffId, 4) != 0) {
+ // Not a valid wav file, to satisfy unit test for mediaobject
+ m_error = Phonon::FatalError;
+ //m_state = Phonon::ErrorState;
+ m_errorString = "Invalid wav file";
+ setState(Phonon::ErrorState);
+ file.close();
+ return;
+ }
+ }
+ file.close();
+ }
+ }
+ emit metaDataChanged(ret);
+ emit currentSourceChanged(source);
+ emit totalTimeChanged(m_totalTime);
+
+ setState(Phonon::StoppedState);
+}
+
+void MediaObject::setPrefinishMark(qint32 newPrefinishMark)
+{
+ m_prefinishMark = newPrefinishMark;
+ if (currentTime() < totalTime() - m_prefinishMark) // not about to finish
+ m_prefinishMarkReachedNotEmitted = true;
+}
+
+void MediaObject::pause()
+{
+ if (state() != Phonon::PausedState)
+ setState(Phonon::PausedState);
+ m_resumeState = false;
+ m_tickTimer->stop();
+}
+
+void MediaObject::stop()
+{
+ if (state() != Phonon::StoppedState) {
+ if(m_state != Phonon::ErrorState) {
+ setState(Phonon::StoppedState);
+ }
+ m_prefinishMarkReachedNotEmitted = true;
+ }
+ m_resumeState = false;
+ m_tickTimer->stop();
+}
+
+void MediaObject::emitTick()
+{
+ if (m_resumeState) {
+ return;
+ }
+ if(m_tickInterval > 0)
+ currentPos += m_tickInterval;
+ else
+ currentPos += 100;
+
+ qint64 currentTime = currentPos;
+ qint64 totalTime = m_totalTime;
+
+ if (m_tickInterval > 0 && currentTime != m_previousTickTime) {
+ emit tick(currentTime);
+ m_previousTickTime = currentTime;
+ }
+ if (m_state == Phonon::PlayingState) {
+ if (currentTime >= totalTime - m_prefinishMark) {
+ if (m_prefinishMarkReachedNotEmitted) {
+ m_prefinishMarkReachedNotEmitted = false;
+ emit prefinishMarkReached(totalTime - currentTime);
+ }
+ }
+ // Prepare load of next source
+ if (currentTime >= totalTime - 500) {
+ if (!m_aboutToFinishEmitted) {
+ m_aboutToFinishEmitted = true; // track is about to finish
+ emit aboutToFinish();
+ }
+ }
+ if(currentTime >= totalTime) {
+ m_tickTimer->stop();
+ if(m_nextSource.type() != MediaSource::Invalid &&
+ m_nextSource.type() != MediaSource::Empty) {
+ setSource(m_nextSource);
+ m_nextSource = MediaSource();
+ m_pendingState = Phonon::PlayingState;
+ } else {
+ setState(Phonon::PausedState);
+ currentPos = 0;
+ emit finished();
+ }
+ }
+ }
+}
+
+void MediaObject::seek(qint64 time)
+{
+ // We will assume no buffering in the object so this is not needed.
+ currentPos = time;
+}
+
+} // ns Dummy
+} // ns Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_mediaobject.cpp"
diff --git a/tests/auto/mediaobject/dummy/mediaobject.h b/tests/auto/mediaobject/dummy/mediaobject.h
new file mode 100644
index 0000000..a20873b
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/mediaobject.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHONON_DUMMY_MEDIAOBJECT_H
+#define PHONON_DUMMY_MEDIAOBJECT_H
+
+#include "backend.h"
+#include <phonon/mediaobjectinterface.h>
+#include <phonon/addoninterface.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtCore/QObject>
+#include <QtCore/QDate>
+#include <QtCore/QEvent>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class QTimer;
+typedef QMultiMap<QString, QString> TagMap;
+
+namespace Phonon
+{
+namespace Dummy
+{
+
+class VideoWidget;
+class AudioPath;
+class VideoPath;
+class AudioOutput;
+
+class MediaObject : public QObject, public MediaObjectInterface
+{
+ friend class Stream;
+ Q_OBJECT
+ Q_INTERFACES(Phonon::MediaObjectInterface
+ )
+
+public:
+
+ MediaObject(Backend *backend, QObject *parent);
+ ~MediaObject();
+ Phonon::State state() const;
+
+ bool hasVideo() const;
+ bool isSeekable() const;
+
+ qint64 currentTime() const;
+ qint32 tickInterval() const;
+
+ void setTickInterval(qint32 newTickInterval);
+
+ void play();
+ void pause();
+ void stop();
+ void seek(qint64 time);
+
+ QString errorString() const;
+ Phonon::ErrorType errorType() const;
+
+ QUrl url() const;
+ qint64 totalTime() const;
+
+ qint32 prefinishMark() const;
+ void setPrefinishMark(qint32 newPrefinishMark);
+
+ qint32 transitionTime() const;
+ void setTransitionTime(qint32);
+ qint64 remainingTime() const;
+
+ void setSource(const MediaSource &source);
+ void setNextSource(const MediaSource &source);
+ MediaSource source() const;
+
+ void saveState();
+ void resumeState();
+
+public Q_SLOTS:
+ void setState(State);
+
+Q_SIGNALS:
+ void currentSourceChanged(const MediaSource &newSource);
+ void stateChanged(Phonon::State newstate, Phonon::State oldstate);
+ void tick(qint64 time);
+ void metaDataChanged(QMultiMap<QString, QString>);
+ void seekableChanged(bool);
+ void hasVideoChanged(bool);
+
+ void finished();
+ void prefinishMarkReached(qint32);
+ void aboutToFinish();
+ void totalTimeChanged(qint64 length);
+ void bufferStatus(int percentFilled);
+
+ QMultiMap<QString, QString> metaData();
+ void setMetaData(QMultiMap<QString, QString> newData);
+
+private Q_SLOTS:
+ void emitTick();
+
+private:
+ bool m_resumeState;
+ State m_oldState;
+ quint64 m_oldPos;
+ quint64 currentPos;
+ bool m_hasVideo;
+ qint32 m_tickInterval;
+ QTimer *m_tickTimer;
+ Phonon::ErrorType m_error;
+ QString m_errorString;
+ qint64 m_totalTime;
+ qint32 m_prefinishMark;
+ qint32 m_transitionTime;
+ MediaSource m_source;
+ MediaSource m_nextSource;
+ bool m_prefinishMarkReachedNotEmitted;
+ bool m_aboutToFinishEmitted;
+ int m_previousTickTime;
+
+ State m_state;
+ State m_pendingState;
+
+ 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;
+ quint32 xFreq1;
+ chunk fact;
+ quint32 xfact;
+ chunk data;
+ };
+
+ struct DATAHeader
+ {
+ chunk descriptor;
+ quint8 data[];
+ };
+
+ struct CombinedHeader
+ {
+ RIFFHeader riff;
+ WAVEHeader wave;
+ DATAHeader data;
+ };
+
+ CombinedHeader header;
+};
+}
+} //namespace Phonon::Dummy
+
+QT_END_NAMESPACE
+
+#endif // PHONON_DUMMY_MEDIAOBJECT_H
diff --git a/tests/auto/mediaobject/dummy/videowidget.cpp b/tests/auto/mediaobject/dummy/videowidget.cpp
new file mode 100644
index 0000000..f46704a
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/videowidget.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** 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 test suite module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videowidget.h"
+#include <QtCore/QEvent>
+#include <QtGui/QResizeEvent>
+#include <QtGui/QPalette>
+#include <QtGui/QImage>
+#include <QtGui/QPainter>
+#include <QtGui/QBoxLayout>
+#include <QApplication>
+#include "mediaobject.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+namespace Dummy
+{
+
+VideoWidget::VideoWidget(Backend *backend, QWidget *parent) :
+ QWidget(parent),
+ m_aspectRatio(Phonon::VideoWidget::AspectRatioAuto),
+ m_brightness(0.0),
+ m_hue(0.0),
+ m_contrast(0.0),
+ m_saturation(0.0),
+ m_scaleMode(Phonon::VideoWidget::FitInView)
+{
+ Q_UNUSED(backend)
+
+}
+
+VideoWidget::~VideoWidget()
+{
+}
+
+void VideoWidget::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event)
+}
+
+void VideoWidget::setVisible(bool val)
+{
+ Q_UNUSED(val)
+}
+
+Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
+{
+ return m_aspectRatio;
+}
+
+QSize VideoWidget::sizeHint() const
+{
+ return QSize(640, 480);
+}
+
+void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio)
+{
+ Q_UNUSED(aspectRatio)
+}
+
+Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
+{
+ return m_scaleMode;
+}
+
+QRect VideoWidget::scaleToAspect(QRect srcRect, int w, int h) const
+{
+ float width = srcRect.width();
+ float height = srcRect.width() * (float(h) / float(w));
+ if (height > srcRect.height()) {
+ height = srcRect.height();
+ width = srcRect.height() * (float(w) / float(h));
+ }
+ return QRect(0, 0, (int)width, (int)height);
+}
+
+/***
+ * Calculates the actual rectangle the movie will be presented with
+ **/
+QRect VideoWidget::calculateDrawFrameRect() const
+{
+ QRect widgetRect = rect();
+ QRect drawFrameRect;
+ // Set m_drawFrameRect to be the size of the smallest possible
+ // rect conforming to the aspect and containing the whole frame:
+ switch (aspectRatio()) {
+
+ case Phonon::VideoWidget::AspectRatioWidget:
+ drawFrameRect = widgetRect;
+ // No more calculations needed.
+ return drawFrameRect;
+
+ case Phonon::VideoWidget::AspectRatio4_3:
+ drawFrameRect = scaleToAspect(widgetRect, 4, 3);
+ break;
+
+ case Phonon::VideoWidget::AspectRatio16_9:
+ drawFrameRect = scaleToAspect(widgetRect, 16, 9);
+ break;
+
+ case Phonon::VideoWidget::AspectRatioAuto:
+ default:
+ drawFrameRect = QRect(0, 0, movieSize().width(), movieSize().height());
+ break;
+ }
+
+ // Scale m_drawFrameRect to fill the widget
+ // without breaking aspect:
+ float widgetWidth = widgetRect.width();
+ float widgetHeight = widgetRect.height();
+ float frameWidth = widgetWidth;
+ float frameHeight = drawFrameRect.height() * float(widgetWidth) / float(drawFrameRect.width());
+
+ switch (scaleMode()) {
+ case Phonon::VideoWidget::ScaleAndCrop:
+ if (frameHeight < widgetHeight) {
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ case Phonon::VideoWidget::FitInView:
+ default:
+ if (frameHeight > widgetHeight) {
+ frameWidth *= float(widgetHeight) / float(frameHeight);
+ frameHeight = widgetHeight;
+ }
+ break;
+ }
+ drawFrameRect.setSize(QSize(int(frameWidth), int(frameHeight)));
+ drawFrameRect.moveTo(int((widgetWidth - frameWidth) / 2.0f),
+ int((widgetHeight - frameHeight) / 2.0f));
+ return drawFrameRect;
+}
+
+void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode)
+{
+ Q_UNUSED(scaleMode)
+}
+
+qreal VideoWidget::brightness() const
+{
+ return m_brightness;
+}
+
+qreal clampedValue(qreal val)
+{
+ if (val > 1.0 )
+ return 1.0;
+ else if (val < -1.0)
+ return -1.0;
+ else return val;
+}
+
+void VideoWidget::setBrightness(qreal newValue)
+{
+ Q_UNUSED(newValue)
+}
+
+qreal VideoWidget::contrast() const
+{
+ return m_contrast;
+}
+
+void VideoWidget::setContrast(qreal newValue)
+{
+ Q_UNUSED(newValue)
+}
+
+qreal VideoWidget::hue() const
+{
+ return m_hue;
+}
+
+void VideoWidget::setHue(qreal newValue)
+{
+ Q_UNUSED(newValue)
+}
+
+qreal VideoWidget::saturation() const
+{
+ return m_saturation;
+}
+
+void VideoWidget::setSaturation(qreal newValue)
+{
+ Q_UNUSED(newValue)
+}
+
+bool VideoWidget::event(QEvent *event)
+{
+ return QWidget::event(event);
+}
+
+void VideoWidget::setMovieSize(const QSize &size)
+{
+ m_movieSize = size;
+ widget()->updateGeometry();
+ widget()->update();
+}
+
+}
+} //namespace Phonon::Dummy
+
+QT_END_NAMESPACE
+
+#include "moc_videowidget.cpp"
diff --git a/tests/auto/mediaobject/dummy/videowidget.h b/tests/auto/mediaobject/dummy/videowidget.h
new file mode 100644
index 0000000..615aa02
--- /dev/null
+++ b/tests/auto/mediaobject/dummy/videowidget.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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 test sutie 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 PHONON_DUMMY_VIDEOWIDGET_H
+#define PHONON_DUMMY_VIDEOWIDGET_H
+
+#include <phonon/videowidget.h>
+#include <phonon/videowidgetinterface.h>
+
+#include "backend.h"
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+namespace Phonon
+{
+namespace Dummy
+{
+
+class VideoWidget : public QWidget, public Phonon::VideoWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Phonon::VideoWidgetInterface)
+public:
+ VideoWidget(Backend *backend, QWidget *parent = 0);
+ ~VideoWidget();
+
+ void paintEvent(QPaintEvent *event);
+ void setVisible(bool);
+
+ Phonon::VideoWidget::AspectRatio aspectRatio() const;
+ void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio);
+ Phonon::VideoWidget::ScaleMode scaleMode() const;
+ void setScaleMode(Phonon::VideoWidget::ScaleMode);
+ qreal brightness() const;
+ void setBrightness(qreal);
+ qreal contrast() const;
+ void setContrast(qreal);
+ qreal hue() const;
+ void setHue(qreal);
+ qreal saturation() const;
+ void setSaturation(qreal);
+ void setMovieSize(const QSize &size);
+ QSize sizeHint() const;
+ QRect scaleToAspect(QRect srcRect, int w, int h) const;
+ QRect calculateDrawFrameRect() const;
+
+ QSize movieSize() const {
+ return m_movieSize;
+ }
+
+ bool event(QEvent *);
+
+ QWidget *widget() {
+ return this;
+ }
+
+protected:
+ QSize m_movieSize;
+
+private:
+ Phonon::VideoWidget::AspectRatio m_aspectRatio;
+ qreal m_brightness, m_hue, m_contrast, m_saturation;
+ Phonon::VideoWidget::ScaleMode m_scaleMode;
+};
+
+}
+} //namespace Phonon::Dummy
+
+QT_END_NAMESPACE
+
+#endif // PHONON_DUMMY_VIDEOWIDGET_H
diff --git a/tests/auto/mediaobject/media/sax.mp3 b/tests/auto/mediaobject/media/sax.mp3
new file mode 100644
index 0000000..0a078b1
--- /dev/null
+++ b/tests/auto/mediaobject/media/sax.mp3
Binary files differ
diff --git a/tests/auto/mediaobject/media/sax.ogg b/tests/auto/mediaobject/media/sax.ogg
new file mode 100644
index 0000000..12be04a
--- /dev/null
+++ b/tests/auto/mediaobject/media/sax.ogg
Binary files differ
diff --git a/tests/auto/mediaobject/media/sax.wav b/tests/auto/mediaobject/media/sax.wav
new file mode 100644
index 0000000..f3e814c
--- /dev/null
+++ b/tests/auto/mediaobject/media/sax.wav
Binary files differ
diff --git a/tests/auto/mediaobject/media/test.sdp b/tests/auto/mediaobject/media/test.sdp
new file mode 100644
index 0000000..0d8706c
--- /dev/null
+++ b/tests/auto/mediaobject/media/test.sdp
@@ -0,0 +1,32 @@
+v=0
+o=- 3476526279 2351211129 IN IP4 XXX.XXX.XXX.XXX
+s=SOME STRING
+e=support@localhost
+c=IN IP4 XXX.XXX.XXX.XXX
+t=0 0
+a=range:npt=now-
+a=random_access_denied
+a=control:rtsp://link
+m=video 0 RTP/AVP 96
+b=AS:100
+b=RR:2500
+b=RS:2500
+a=control:rtsp://link
+a=rtpmap:96 MP4V-ES/90000
+a=3GPP-Adaptation-Support:1
+a=cliprect:0,0,144,176
+a=mpeg4-esid:201
+a=x-envivio-verid:00022B15
+a=fmtp:96 profile-level-id=2;config=000001b002000001b50ea020202f000001000000012000c788ba9850584121463f
+a=framerate:15.0
+m=audio 0 RTP/AVP 97
+b=AS:14
+b=RR:350
+b=RS:350
+a=control:rtsp://link
+a=rtpmap:97 AMR/8000
+a=3GPP-Adaptation-Support:1
+a=mpeg4-esid:101
+a=x-envivio-verid:00022B15
+a=fmtp:97 octet-align=1
+a=maxptime:200
diff --git a/tests/auto/mediaobject/mediaobject.pro b/tests/auto/mediaobject/mediaobject.pro
new file mode 100755
index 0000000..23ec56b
--- /dev/null
+++ b/tests/auto/mediaobject/mediaobject.pro
@@ -0,0 +1,24 @@
+############################################################
+# Project file for autotest for file mediaobject.h
+############################################################
+
+load(qttest_p4)
+
+contains(QT_CONFIG, phonon):QT += phonon
+SOURCES += tst_mediaobject.cpp
+HEADERS += qtesthelper.h
+RESOURCES += mediaobject.qrc
+
+wince*{
+ DEPLOYMENT_PLUGIN += phonon_waveout
+ DEFINES += tst_MediaObject=tst_MediaObject_waveout
+}
+
+symbian:{
+ addFiles.files = media/test.sdp
+ addFiles.path = media
+ DEPLOYMENT += addFiles
+ LIBS += -lCommDb -lconnmon
+ TARGET.CAPABILITY += "NetworkServices"
+}
+
diff --git a/tests/auto/mediaobject/mediaobject.qrc b/tests/auto/mediaobject/mediaobject.qrc
new file mode 100644
index 0000000..77954f4
--- /dev/null
+++ b/tests/auto/mediaobject/mediaobject.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+<file>media/sax.wav</file>
+<file>media/sax.ogg</file>
+<file>media/sax.mp3</file>
+<file>media/test.sdp</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/mediaobject/qtesthelper.h b/tests/auto/mediaobject/qtesthelper.h
new file mode 100644
index 0000000..9b1ea18
--- /dev/null
+++ b/tests/auto/mediaobject/qtesthelper.h
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/* This file is part of the KDE project
+ Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef QTESTHELPER_H
+#define QTESTHELPER_H
+
+#include <QtCore/QEventLoop>
+#include <QtCore/QTimer>
+#include <QtTest/QSignalSpy>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+namespace QTest
+{
+
+ /**
+ * Starts an event loop that runs until the given signal is received. Optionally the event loop
+ * can return earlier on a timeout.
+ *
+ * \return \p true if the requested signal was received
+ * \p false on timeout
+ */
+ bool waitForSignal(QObject *obj, const char *signal, int timeout = 0)
+ {
+ QEventLoop loop;
+ QObject::connect(obj, signal, &loop, SLOT(quit()));
+ QTimer timer;
+ QSignalSpy timeoutSpy(&timer, SIGNAL(timeout()));
+ if (timeout > 0) {
+ QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
+ timer.setSingleShot(true);
+ timer.start(timeout);
+ }
+ loop.exec();
+ return timeoutSpy.isEmpty();
+ }
+
+
+// template<>
+ char *toString(const Phonon::State &state)
+ {
+ switch (state) {
+ case Phonon::LoadingState:
+ return qstrdup("LoadingState");
+ case Phonon::StoppedState:
+ return qstrdup("StoppedState");
+ case Phonon::PlayingState:
+ return qstrdup("PlayingState");
+ case Phonon::BufferingState:
+ return qstrdup("BufferingState");
+ case Phonon::PausedState:
+ return qstrdup("PausedState");
+ case Phonon::ErrorState:
+ return qstrdup("ErrorState");
+ }
+ return 0;
+ }
+
+// template<>
+ char *toString(const QVariant::Type &type)
+ {
+ switch (type) {
+ case QVariant::Invalid:
+ return qstrdup("QVariant::Invalid");
+ case QVariant::BitArray:
+ return qstrdup("QVariant::BitArray");
+ case QVariant::Bitmap:
+ return qstrdup("QVariant::Bitmap");
+ case QVariant::Bool:
+ return qstrdup("QVariant::Bool");
+ case QVariant::Brush:
+ return qstrdup("QVariant::Brush");
+ case QVariant::ByteArray:
+ return qstrdup("QVariant::ByteArray");
+ case QVariant::Char:
+ return qstrdup("QVariant::Char");
+ case QVariant::Color:
+ return qstrdup("QVariant::Color");
+ case QVariant::Cursor:
+ return qstrdup("QVariant::Cursor");
+ case QVariant::Date:
+ return qstrdup("QVariant::Date");
+ case QVariant::DateTime:
+ return qstrdup("QVariant::DateTime");
+ case QVariant::Double:
+ return qstrdup("QVariant::Double");
+ case QVariant::Font:
+ return qstrdup("QVariant::Font");
+ case QVariant::Icon:
+ return qstrdup("QVariant::Icon");
+ case QVariant::Image:
+ return qstrdup("QVariant::Image");
+ case QVariant::Int:
+ return qstrdup("QVariant::Int");
+ case QVariant::KeySequence:
+ return qstrdup("QVariant::KeySequence");
+ case QVariant::Line:
+ return qstrdup("QVariant::Line");
+ case QVariant::LineF:
+ return qstrdup("QVariant::LineF");
+ case QVariant::List:
+ return qstrdup("QVariant::List");
+ case QVariant::Locale:
+ return qstrdup("QVariant::Locale");
+ case QVariant::LongLong:
+ return qstrdup("QVariant::LongLong");
+ case QVariant::Map:
+ return qstrdup("QVariant::Map");
+ case QVariant::Matrix:
+ return qstrdup("QVariant::Matrix");
+ case QVariant::Transform:
+ return qstrdup("QVariant::Transform");
+ case QVariant::Palette:
+ return qstrdup("QVariant::Palette");
+ case QVariant::Pen:
+ return qstrdup("QVariant::Pen");
+ case QVariant::Pixmap:
+ return qstrdup("QVariant::Pixmap");
+ case QVariant::Point:
+ return qstrdup("QVariant::Point");
+ case QVariant::PointF:
+ return qstrdup("QVariant::PointF");
+ case QVariant::Polygon:
+ return qstrdup("QVariant::Polygon");
+ case QVariant::Rect:
+ return qstrdup("QVariant::Rect");
+ case QVariant::RectF:
+ return qstrdup("QVariant::RectF");
+ case QVariant::RegExp:
+ return qstrdup("QVariant::RegExp");
+ case QVariant::Region:
+ return qstrdup("QVariant::Region");
+ case QVariant::Size:
+ return qstrdup("QVariant::Size");
+ case QVariant::SizeF:
+ return qstrdup("QVariant::SizeF");
+ case QVariant::SizePolicy:
+ return qstrdup("QVariant::SizePolicy");
+ case QVariant::String:
+ return qstrdup("QVariant::String");
+ case QVariant::StringList:
+ return qstrdup("QVariant::StringList");
+ case QVariant::TextFormat:
+ return qstrdup("QVariant::TextFormat");
+ case QVariant::TextLength:
+ return qstrdup("QVariant::TextLength");
+ case QVariant::Time:
+ return qstrdup("QVariant::Time");
+ case QVariant::UInt:
+ return qstrdup("QVariant::UInt");
+ case QVariant::ULongLong:
+ return qstrdup("QVariant::ULongLong");
+ case QVariant::Url:
+ return qstrdup("QVariant::Url");
+ case QVariant::UserType:
+ return qstrdup("QVariant::UserType");
+ case QVariant::LastType:
+ return qstrdup("QVariant::LastType");
+ default:
+ return 0;
+ }
+ }
+} // namespace QTest
+QT_END_NAMESPACE
+
+#endif // QTESTHELPER_H
diff --git a/tests/auto/mediaobject/tst_mediaobject.cpp b/tests/auto/mediaobject/tst_mediaobject.cpp
new file mode 100644
index 0000000..b29a6db
--- /dev/null
+++ b/tests/auto/mediaobject/tst_mediaobject.cpp
@@ -0,0 +1,1220 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) version 3.
+
+ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QtTest/QtTest>
+#include <QtCore/QDate>
+#include <QtCore/QDebug>
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
+
+#ifndef QT_NO_PHONON
+#include <phonon/path.h>
+#include <phonon/audiooutput.h>
+#include <phonon/mediaobject.h>
+#include <phonon/phononnamespace.h>
+#include <phonon/audiooutput.h>
+#include <phonon/seekslider.h>
+#include <phonon/mediaobject.h>
+#include <phonon/volumeslider.h>
+#include <phonon/videowidget.h>
+#include <phonon/backendcapabilities.h>
+
+#include "qtesthelper.h"
+#include <cstdlib>
+#endif
+
+#ifndef Q_WS_WIN
+#include <unistd.h>
+#endif
+
+#ifdef Q_OS_WINCE
+#define MEDIA_FILE "/sax.wav"
+#define MEDIA_FILEPATH ":/media/sax.wav"
+const qint64 SEEK_BACKWARDS = 2000;
+const qint64 ALLOWED_TIME_FOR_SEEKING = 1500; // 1.5s
+const qint64 SEEKING_TOLERANCE = 250;
+#else
+#if defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(Q_OS_SYMBIAN)
+#define MEDIA_FILE "/sax.mp3"
+#define MEDIA_FILEPATH ":/media/sax.mp3"
+#else
+#define MEDIA_FILE "/sax.ogg"
+#define MEDIA_FILEPATH ":/media/sax.ogg"
+#endif
+const qint64 SEEK_BACKWARDS = 4000;
+const qint64 ALLOWED_TIME_FOR_SEEKING = 1000; // 1s
+const qint64 SEEKING_TOLERANCE = 0;
+#endif //Q_OS_WINCE
+
+#ifdef Q_OS_SYMBIAN
+#include <cdbcols.h>
+#include <cdblen.h>
+#include <commdb.h>
+#include <rconnmon.h>
+
+const QString KDefaultIAP = QLatin1String("default");
+const QString KInvalidIAP = QLatin1String("invalid IAP");
+
+class CConnectionObserver : public CBase, public MConnectionMonitorObserver
+{
+public:
+ static CConnectionObserver* NewL()
+ {
+ CConnectionObserver* self = new (ELeave) CConnectionObserver();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+ QString currentIAP()
+ {
+ return m_currentIAPName;
+ }
+ ~CConnectionObserver()
+ {
+ m_connMon.Close();
+ }
+private:
+ CConnectionObserver()
+ {
+ }
+ void ConstructL()
+ {
+ m_connMon.ConnectL();
+ m_connMon.NotifyEventL(*this);
+ }
+ void EventL (const CConnMonEventBase &aConnEvent)
+ {
+ TInt event = aConnEvent.EventType();
+ TUint connId = aConnEvent.ConnectionId();
+ TRequestStatus status;
+ switch (event) {
+ case EConnMonCreateConnection: {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ m_connMon.GetStringAttribute(connId, 0, KIAPName, iapName, status);
+ User::WaitForRequest(status);
+ m_currentIAPName = QString(reinterpret_cast<const QChar *>(iapName.Ptr()), iapName.Length());
+ qDebug() << "A new connection created using: " << m_currentIAPName;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+private:
+ RConnectionMonitor m_connMon;
+ QString m_currentIAPName;
+};
+
+#endif
+
+
+class tst_MediaObject : public QObject
+{
+ Q_OBJECT
+ public:
+ tst_MediaObject()
+ : m_success(false)
+ {
+ qputenv("PHONON_GST_AUDIOSINK", "fake");
+ }
+
+#ifndef QT_NO_PHONON
+
+ Q_SIGNALS:
+ void continueTestPlayOnFinish();
+
+ protected Q_SLOTS:
+ void enqueueMedia();
+ void setMediaAndPlay();
+ void stateChanged(Phonon::State, Phonon::State);
+ private Q_SLOTS:
+ void init();
+ void cleanup();
+
+ void testPlayFromResource();
+ void testPlayIllegalFile();
+ void initTestCase();
+ void checkForDefaults();
+
+ // state change tests
+ void stopToStop();
+ void stopToPause();
+ void stopToPlay();
+ void playToPlay();
+ void playToPause();
+ void playToStop();
+ void pauseToPause();
+ void pauseToPlay();
+ void pauseToStop();
+ void playSDP();
+ void playUrl_data();
+ void playUrl();
+
+ void testPrefinishMark();
+ void testSeek();
+ void testTickSignal();
+ void testJustInTimeQueuing();
+ void testPlayOnFinish();
+ void testPlayBeforeFinish();
+ void testPauseOnFinish();
+ void testReconnectBetweenTwoMediaObjects();
+ void volumeSliderMuteVisibility();
+ void cleanupTestCase();
+ private:
+ void _startPlayback(Phonon::State currentState = Phonon::StoppedState);
+ void _stopPlayback(Phonon::State currentState);
+ void _pausePlayback();
+ void _testOneSeek(qint64 seekTo);
+
+ QUrl m_url;
+ Phonon::MediaObject *m_media;
+ QSignalSpy *m_stateChangedSignalSpy;
+ QString m_tmpFileName;
+#ifdef Q_OS_SYMBIAN
+ CConnectionObserver *m_iapConnectionObserver;
+ QString getValidIAPL();
+#endif //Q_OS_SYMBIAN
+
+ static void copyMediaFile(const QString &original,
+ const QString &name,
+ QString &resultFilePath,
+ QUrl *const asURL = 0);
+#endif //QT_NO_PHONON
+ bool m_success;
+};
+
+#ifndef QT_NO_PHONON
+
+#define startPlayback() _startPlayback(); if (!m_success) return; m_success = false;
+#define startPlayback2(currentState) _startPlayback(currentState); if (!m_success) return; m_success = false;
+#define stopPlayback(currentState) _stopPlayback(currentState); if (!m_success) return; m_success = false;
+#define pausePlayback() _pausePlayback(); if (!m_success) return; m_success = false;
+#define testOneSeek(seekTo) _testOneSeek(seekTo); if (!m_success) return; m_success = false;
+
+const qint64 ALLOWED_SEEK_INACCURACY = 300; // 0.3s
+const qint64 ALLOWED_TICK_INACCURACY = 350; // allow +/- 350 ms inaccuracy
+
+using namespace Phonon;
+
+static qint64 castQVariantToInt64(const QVariant &variant)
+{
+ return *reinterpret_cast<const qint64 *>(variant.constData());
+}
+
+static qint32 castQVariantToInt32(const QVariant &variant)
+{
+ return *reinterpret_cast<const qint32 *>(variant.constData());
+}
+
+void tst_MediaObject::stateChanged(Phonon::State newstate, Phonon::State oldstate)
+{
+ if (newstate == Phonon::ErrorState)
+ QWARN(QByteArray(QByteArray(QTest::toString(oldstate)) + " to " + QByteArray(QTest::toString(newstate))));
+}
+
+void tst_MediaObject::testPlayFromResource()
+{
+ MediaObject media;
+ media.setCurrentSource(QString(MEDIA_FILEPATH));
+ QVERIFY(media.state() != Phonon::ErrorState);
+ if (media.state() != Phonon::StoppedState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 10000);
+ QCOMPARE(media.state(), Phonon::StoppedState);
+ media.play();
+ if (media.state() != Phonon::PlayingState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 10000);
+ QCOMPARE(media.state(), Phonon::PlayingState);
+}
+
+void tst_MediaObject::testPlayIllegalFile()
+{
+ QString filename = QDir::tempPath() + QString("/test.wav");
+ QFile::remove(filename);
+ QFile file(filename);
+ file.open(QIODevice::WriteOnly);
+ for (int i=0;i<0xffff;i++) {
+ int r = qrand();
+ file.write((const char*)&r, 2);
+ }
+ file.close();
+ MediaObject media;
+ media.setCurrentSource(filename);
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 10000);
+ QCOMPARE(media.state(), Phonon::ErrorState);
+ media.play();
+ QCOMPARE(media.state(), Phonon::ErrorState);
+ QFile::remove(filename);
+}
+
+void tst_MediaObject::init()
+{
+ QCOMPARE(m_media->outputPaths().size(), 1);
+ if (m_media->state() == Phonon::ErrorState) {
+ m_media->setCurrentSource(m_url);
+ if (m_media->state() == Phonon::ErrorState) {
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
+ }
+ if (m_media->state() == Phonon::LoadingState) {
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
+ }
+ m_stateChangedSignalSpy->clear();
+ }
+
+ // Ensure that m_media is in StoppedState
+ if (m_media->state() != Phonon::StoppedState) {
+ m_media->stop();
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
+ QCOMPARE(m_media->state(), Phonon::StoppedState);
+ }
+}
+
+void tst_MediaObject::cleanup()
+{
+ switch (m_media->state()) {
+ case Phonon::PlayingState:
+ case Phonon::BufferingState:
+ case Phonon::PausedState:
+ stopPlayback(m_media->state());
+ break;
+ default:
+ break;
+ }
+ m_stateChangedSignalSpy->clear();
+}
+
+void tst_MediaObject::_startPlayback(Phonon::State currentState)
+{
+ m_stateChangedSignalSpy->clear();
+ Phonon::State s = m_media->state();
+ QCOMPARE(s, currentState);
+ m_media->play();
+ while (s != Phonon::PlayingState) {
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 3000);
+ QApplication::processEvents();
+ }
+ while (!m_stateChangedSignalSpy->isEmpty()) {
+ QList<QVariant> args = m_stateChangedSignalSpy->takeFirst();
+ Phonon::State laststate = qvariant_cast<Phonon::State>(args.at(1));
+ QCOMPARE(laststate, s);
+ s = qvariant_cast<Phonon::State>(args.at(0));
+ QVERIFY(s == Phonon::BufferingState || s == Phonon::PlayingState);
+ }
+ }
+ QCOMPARE(s, Phonon::PlayingState);
+ QCOMPARE(m_media->state(), Phonon::PlayingState);
+ m_success = true;
+}
+
+void tst_MediaObject::_stopPlayback(Phonon::State currentState)
+{
+ QVERIFY(currentState != Phonon::ErrorState);
+ m_stateChangedSignalSpy->clear();
+ Phonon::State s = m_media->state();
+ QCOMPARE(s, currentState);
+ m_media->stop();
+ while (s != Phonon::StoppedState) {
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 4000));
+ }
+ while (!m_stateChangedSignalSpy->isEmpty()) {
+ QList<QVariant> args = m_stateChangedSignalSpy->takeFirst();
+ Phonon::State laststate = qvariant_cast<Phonon::State>(args.at(1));
+ QCOMPARE(laststate, s);
+ s = qvariant_cast<Phonon::State>(args.at(0));
+ if (s == Phonon::StoppedState) {
+ QVERIFY(m_stateChangedSignalSpy->isEmpty());
+ break;
+ }
+ QVERIFY(s == Phonon::BufferingState || s == Phonon::PlayingState);
+ }
+ }
+ QCOMPARE(s, Phonon::StoppedState);
+ QCOMPARE(m_media->state(), Phonon::StoppedState);
+ m_success = true;
+}
+
+void tst_MediaObject::_pausePlayback()
+{
+ m_stateChangedSignalSpy->clear();
+ Phonon::State s = m_media->state();
+ m_media->pause();
+ while (s != Phonon::PausedState) {
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
+ }
+ while (!m_stateChangedSignalSpy->isEmpty()) {
+ QList<QVariant> args = m_stateChangedSignalSpy->takeFirst();
+ Phonon::State laststate = qvariant_cast<Phonon::State>(args.at(1));
+ QCOMPARE(laststate, s);
+ s = qvariant_cast<Phonon::State>(args.at(0));
+ if (s == Phonon::PausedState) {
+ QVERIFY(m_stateChangedSignalSpy->isEmpty());
+ break;
+ }
+ QVERIFY(s == Phonon::BufferingState || s == Phonon::PlayingState);
+ }
+ }
+ QCOMPARE(s, Phonon::PausedState);
+ QCOMPARE(m_media->state(), Phonon::PausedState);
+ m_success = true;
+}
+
+/*!
+ Copies the file \a name to the testing area. The resulting file name path is
+ returned in resultFilePath, and also set as a URL in \a asURL.
+ */
+void tst_MediaObject::copyMediaFile(const QString &original,
+ const QString &name,
+ QString &resultFilePath,
+ QUrl *const asURL)
+{
+ resultFilePath = QDir::toNativeSeparators(QDir::tempPath() + name);
+ if (asURL)
+ *asURL = QUrl::fromLocalFile(resultFilePath);
+
+ QFile::remove(resultFilePath);
+ QVERIFY(QFile::copy(original, resultFilePath));
+ QFile::setPermissions(resultFilePath, QFile::permissions(resultFilePath) | QFile::WriteOther);
+}
+
+void tst_MediaObject::initTestCase()
+{
+ QCoreApplication::setApplicationName("tst_MediaObject");
+ m_stateChangedSignalSpy = 0;
+ m_media = 0;
+
+#ifdef Q_OS_WINCE
+ QString pluginsPath = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+#ifdef DEBUG
+ QVERIFY(QFile::exists(pluginsPath + "/phonon_backend/phonon_waveoutd4.dll") || QFile::exists(pluginsPath + "/phonon_backend/phonon_phonon_ds9d4.dll"));
+#else
+ QVERIFY(QFile::exists(pluginsPath + "/phonon_backend/phonon_waveout4.dll") || QFile::exists(pluginsPath + "/phonon_backend/phonon_phonon_ds94.dll"));
+#endif
+#endif
+
+
+ m_url = qgetenv("PHONON_TESTURL");
+ m_media = new MediaObject(this);
+ connect(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), SLOT(stateChanged(Phonon::State, Phonon::State)));
+ m_stateChangedSignalSpy = new QSignalSpy(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
+ QVERIFY(m_stateChangedSignalSpy->isValid());
+ m_stateChangedSignalSpy->clear();
+
+ if (m_url.isEmpty())
+ copyMediaFile(MEDIA_FILEPATH, MEDIA_FILE, m_tmpFileName, &m_url);
+
+ qDebug() << "Using url:" << m_url.toString();
+
+ // AudioOutput is needed else the backend might have no time source
+ AudioOutput *audioOutput = new AudioOutput(Phonon::MusicCategory, this);
+ //audioOutput->setVolume(0.0f);
+
+ QSignalSpy totalTimeChangedSignalSpy(m_media, SIGNAL(totalTimeChanged(qint64)));
+ QVERIFY(m_media->queue().isEmpty());
+ QCOMPARE(m_media->currentSource().type(), MediaSource::Empty);
+ QCOMPARE(m_media->state(), Phonon::LoadingState);
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+
+ m_media->setCurrentSource(m_url);
+ QCOMPARE(m_media->currentSource().type(), MediaSource::Url);
+ QCOMPARE(m_media->currentSource().url(), m_url);
+
+ int emits = m_stateChangedSignalSpy->count();
+ Phonon::State s = m_media->state();
+ if (s == Phonon::LoadingState) {
+ // still in LoadingState, there should be no state change
+ QCOMPARE(emits, 0);
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 6000);
+ emits = m_stateChangedSignalSpy->count();
+ s = m_media->state();
+ }
+ if (s != Phonon::LoadingState) {
+ // there should exactly be one state change
+ QCOMPARE(emits, 1);
+ QList<QVariant> args = m_stateChangedSignalSpy->takeFirst();
+ Phonon::State newstate = qvariant_cast<Phonon::State>(args.at(0));
+ Phonon::State oldstate = qvariant_cast<Phonon::State>(args.at(1));
+
+ QCOMPARE(Phonon::LoadingState, oldstate);
+ QCOMPARE(s, newstate);
+ if (Phonon::ErrorState == s) {
+#ifdef Q_WS_WIN
+ if (m_media->errorString().contains(QLatin1String("no audio hardware is available")))
+ QSKIP("On Windows we need an audio devide to perform the MediaObject tests", SkipAll);
+ else
+#endif
+ QFAIL("Loading the URL put the MediaObject into the ErrorState. Check that PHONON_TESTURL is set to a valid URL.");
+ }
+ QCOMPARE(Phonon::StoppedState, s);
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+
+ // check for totalTimeChanged signal
+ QVERIFY(totalTimeChangedSignalSpy.count() > 0);
+ args = totalTimeChangedSignalSpy.takeLast();
+ QCOMPARE(m_media->totalTime(), castQVariantToInt64(args.at(0)));
+ } else {
+ QFAIL("Still in LoadingState after a stateChange signal was emitted. Cannot go on.");
+ }
+
+ Path path = createPath(m_media, audioOutput);
+ QVERIFY(path.isValid());
+
+
+ QCOMPARE(m_media->outputPaths().size(), 1);
+ QCOMPARE(audioOutput->inputPaths().size(), 1);
+
+#ifdef Q_OS_SYMBIAN
+ TRAP_IGNORE(m_iapConnectionObserver = CConnectionObserver::NewL());
+#endif //Q_OS_SYMBIAN
+
+}
+
+void tst_MediaObject::checkForDefaults()
+{
+ QCOMPARE(m_media->tickInterval(), qint32(0));
+ QCOMPARE(m_media->prefinishMark(), qint32(0));
+}
+
+void tst_MediaObject::stopToStop()
+{
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+ QCOMPARE(m_media->state(), Phonon::StoppedState);
+ m_media->stop();
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 2000);
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+ QCOMPARE(m_media->state(), Phonon::StoppedState);
+}
+
+void tst_MediaObject::stopToPause()
+{
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+ QCOMPARE(m_media->state(), Phonon::StoppedState);
+ m_media->pause();
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 6000));
+ }
+ QCOMPARE(m_stateChangedSignalSpy->count(), 1);
+ QCOMPARE(m_media->state(), Phonon::PausedState);
+}
+
+void tst_MediaObject::stopToPlay()
+{
+ startPlayback();
+ QTest::waitForSignal(m_media, SIGNAL(finished()), 1000);
+ stopPlayback(Phonon::PlayingState);
+}
+
+void tst_MediaObject::playToPlay()
+{
+ startPlayback();
+
+ m_media->play();
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+ QCOMPARE(m_media->state(), Phonon::PlayingState);
+
+ stopPlayback(Phonon::PlayingState);
+}
+
+void tst_MediaObject::playToPause()
+{
+ startPlayback();
+ QCOMPARE(m_media->state(), Phonon::PlayingState);
+ pausePlayback();
+ stopPlayback(Phonon::PausedState);
+}
+
+void tst_MediaObject::playToStop()
+{
+ startPlayback();
+ stopPlayback(Phonon::PlayingState);
+}
+
+void tst_MediaObject::pauseToPause()
+{
+ startPlayback();
+ pausePlayback();
+
+ m_media->pause();
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+ QCOMPARE(m_media->state(), Phonon::PausedState);
+
+ stopPlayback(Phonon::PausedState);
+}
+
+void tst_MediaObject::pauseToPlay()
+{
+ startPlayback();
+ pausePlayback();
+ startPlayback2(Phonon::PausedState);
+ stopPlayback(Phonon::PlayingState);
+}
+
+void tst_MediaObject::pauseToStop()
+{
+ startPlayback();
+ pausePlayback();
+ stopPlayback(Phonon::PausedState);
+}
+
+/*!
+
+ We attempt to play a SDP file. An SDP file essentially describes different
+ media streams and is hence a layer in front of the actual media(s).
+ Sometimes the backend handles the SDP file, in other cases not.
+
+ Some Phonon backends doesn't support SDP at all, ifdef appropriately. Real
+ Player and Helix, the two backends for Symbian, are known to support SDP.
+ */
+void tst_MediaObject::playSDP()
+{
+#ifdef Q_OS_SYMBIAN
+ QString sdpFile;
+ copyMediaFile(QLatin1String(":/media/test.sdp"), QLatin1String("test.sdp"), sdpFile);
+
+ // Let's verify our test setup.
+ QVERIFY(QFileInfo(sdpFile).isReadable());
+
+ // We need a window in order to setup the video.
+ QWidget widget;
+ widget.show();
+
+ const MediaSource oldSource(m_media->currentSource());
+ const MediaSource sdpSource(sdpFile);
+ m_media->setCurrentSource(sdpSource);
+ if (m_media->state() != Phonon::StoppedState)
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 10000);
+
+ // MediaObject should have loaded the SDP, but be in error state due to absent media
+ const bool stateMatch = (m_media->state() == Phonon::ErrorState);
+ const bool errorStringMatch = (m_media->errorString() == QString::fromLatin1("Loading clip failed: Unknown error (-39)"));
+
+ // Ensure that m_media is back in ground state prior to starting next test step
+ m_media->setCurrentSource(oldSource);
+ if (m_media->state() != Phonon::StoppedState)
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
+ QCOMPARE(m_media->state(), Phonon::StoppedState);
+
+ QVERIFY(stateMatch);
+ QVERIFY(errorStringMatch);
+
+#else
+ QSKIP("Unsupported on this platform.", SkipAll);
+#endif
+}
+
+/*!
+ Attempt to play from an RTSP link, and, on Symbian, to specify the IAP that
+ should be used to connect to the network. This test requires the unit under test
+ to have a default internet connection that will support streaming media, and ideally
+ one other internet connection that will also support streaming.
+ */
+void tst_MediaObject::playUrl_data()
+{
+ QTest::addColumn<QUrl>("url");
+#ifdef Q_OS_SYMBIAN
+ QTest::addColumn<QString>("iap");
+#endif //Q_OS_SYMBIAN
+
+ QUrl rtspLink("rtsp://v1.cache8.c.youtube.com/CjgLENy73wIaLwnoDBCE7tF7fxMYESARFEIJbXYtZ29vZ2xlSARSB3Jlc3VsdHNgpbWqq7L7je5KDA==/0/0/0/video.3gp");
+ QUrl httpLink("http://www.theflute.co.uk/media/BachCPE_SonataAmin_1.wma");
+
+#ifdef Q_OS_SYMBIAN
+ QTest::newRow("default_IAP_rtsp") << rtspLink << KDefaultIAP;
+ QTest::newRow("invalid_IAP_rtsp") << rtspLink << KInvalidIAP;
+ //don't test HTTP link with invalid or default IAP as it will prompt the user
+ //Add tests with a valid IAP if we can get one from CommsDB
+ QString validIAP;
+ TRAPD(err, validIAP = getValidIAPL());
+ if (KErrNone == err) {
+ QTest::newRow("valid_IAP_rtsp") << rtspLink << validIAP;
+ QTest::newRow("valid_IAP_http") << httpLink << validIAP;
+ }
+#else
+ QTest::newRow("default_IAP_rtsp") << rtspLink;
+ QTest::newRow("invalid_IAP_rtsp") << rtspLink;
+#endif //Q_OS_SYMBIAN
+}
+
+#ifdef Q_OS_SYMBIAN
+QString tst_MediaObject::getValidIAPL()
+{
+ CCommsDatabase* commsDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(commsDb);
+ commsDb->ShowHiddenRecords();
+ CCommsDbTableView* view = commsDb->OpenTableLC(TPtrC(IAP));
+ QString validIAP;
+ TBool found = EFalse;
+ TInt record = view->GotoFirstRecord();
+ while (KErrNotFound != record) {
+ TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
+ view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
+ validIAP = QString::fromUtf16(iapName.Ptr(),iapName.Length());
+ //We don't want the "Easy WLAN" IAP as it will try and prompt the user
+ if ("Easy WLAN" != validIAP) {
+ qDebug() << "playUrl_data() adding a valid IAP test: " << validIAP;
+ found = ETrue;
+ break;
+ }
+ record = view->GotoNextRecord();
+ }
+ CleanupStack::PopAndDestroy(2);
+ if (!found)
+ User::Leave(KErrNotFound);
+ return validIAP;
+}
+#endif //Q_OS_SYMBIAN
+
+void tst_MediaObject::playUrl()
+{
+ QFETCH(QUrl, url);
+#ifdef Q_OS_SYMBIAN
+ QFETCH(QString, iap);
+#endif
+ MediaObject media(this);
+
+ //Create a proper media path for video and audio
+ VideoWidget videoOutput;
+ Path path = createPath(&media, &videoOutput);
+ QVERIFY(path.isValid());
+ AudioOutput audioOutput(Phonon::MusicCategory, this);
+ path = createPath(&media, &audioOutput);
+ QVERIFY(path.isValid());
+
+#ifdef Q_OS_SYMBIAN
+ //The Symbian backend allows the IAP used for streaming connections to be specified
+ //by the application, using the "InternetAccessPointName" property.
+ if (KDefaultIAP != iap)
+ media.setProperty("InternetAccessPointName", iap);
+#endif //Q_OS_SYMBIAN
+ media.setCurrentSource(Phonon::MediaSource(url));
+ QVERIFY(media.state() != Phonon::ErrorState);
+
+ //we use a long 30s timeout here as it can take a long time for the streaming source to
+ //be sucessfully prepared depending on the network.
+ if (media.state() != Phonon::StoppedState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 30000);
+ QCOMPARE(media.state(), Phonon::StoppedState);
+
+ media.play();
+ if (media.state() != Phonon::PlayingState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 15000);
+ QCOMPARE(media.state(), Phonon::PlayingState);
+
+ //sleep and allow some of the stream to be played
+ QTest::qSleep(10000);
+
+#ifdef Q_OS_SYMBIAN
+ // Verify that the specified IAP is actually being used when we're not doing negative tests
+ if ((KDefaultIAP == iap || KInvalidIAP == iap) == false) {
+ if (m_iapConnectionObserver)
+ QCOMPARE(iap,m_iapConnectionObserver->currentIAP());
+ }
+#endif //Q_OS_SYMBIAN
+
+ media.stop();
+ if (media.state() != Phonon::StoppedState)
+ QTest::waitForSignal(&media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 15000);
+ QCOMPARE(media.state(), Phonon::StoppedState);
+}
+
+void tst_MediaObject::testPrefinishMark()
+{
+ const qint32 requestedPrefinishMarkTime = 2000;
+ m_media->setPrefinishMark(requestedPrefinishMarkTime);
+ QCOMPARE(m_media->prefinishMark(), requestedPrefinishMarkTime);
+ QSignalSpy prefinishMarkReachedSpy(m_media, SIGNAL(prefinishMarkReached(qint32)));
+ QSignalSpy finishSpy(m_media, SIGNAL(finished()));
+ startPlayback();
+ if (m_media->isSeekable()) {
+ m_media->seek(m_media->totalTime() - SEEK_BACKWARDS - requestedPrefinishMarkTime); // give it 4 seconds
+ }
+ int wait = 10000;
+ int total = 0;
+ while (prefinishMarkReachedSpy.count() == 0 && (m_media->state() == Phonon::PlayingState ||
+ m_media->state() == Phonon::BufferingState)) {
+ wait = qMax(1000, wait / 2);
+ QTest::waitForSignal(m_media, SIGNAL(prefinishMarkReached(qint32)), wait);
+ total += wait;
+ if (total >= 60*1000) // we wait 1 minute
+ QFAIL("Timeout failure waiting for signal");
+ }
+ // at this point the media should be about to finish playing
+ qint64 r = m_media->remainingTime();
+ Phonon::State state = m_media->state();
+ QCOMPARE(prefinishMarkReachedSpy.count(), 1);
+ const qint32 prefinishMark = castQVariantToInt32(prefinishMarkReachedSpy.first().at(0));
+ QVERIFY(prefinishMark <= requestedPrefinishMarkTime + 150); // allow it to be up to 150ms too early
+ if (state == Phonon::PlayingState || state == Phonon::BufferingState) {
+ if (r > prefinishMark) {
+ qDebug() << "remainingTime =" << r;
+ QFAIL("remainingTime needs to be less than or equal to prefinishMark");
+ }
+ QVERIFY(r <= prefinishMark);
+ QTest::waitForSignal(m_media, SIGNAL(finished()), 10000);
+ } else {
+ QVERIFY(prefinishMark >= 0);
+ }
+ QCOMPARE(finishSpy.count(), 1);
+}
+
+void tst_MediaObject::enqueueMedia()
+{
+ m_media->enqueue(m_url);
+}
+
+Q_DECLARE_METATYPE(Phonon::MediaSource)
+void tst_MediaObject::testJustInTimeQueuing()
+{
+#ifdef Q_OS_WINCE
+ QSKIP("crashes on Windows CE", SkipAll);
+#endif
+ qRegisterMetaType<Phonon::MediaSource>("Phonon::MediaSource");
+ QSignalSpy currentSourceChanged(m_media, SIGNAL(currentSourceChanged(const Phonon::MediaSource &)));
+ QSignalSpy finished(m_media, SIGNAL(finished()));
+ connect(m_media, SIGNAL(aboutToFinish()), SLOT(enqueueMedia()));
+
+ startPlayback();
+ if (m_media->isSeekable()) {
+ m_media->seek(m_media->totalTime() - SEEK_BACKWARDS);
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(aboutToFinish()), 6000));
+ } else {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(aboutToFinish()), 3000 + m_media->remainingTime()));
+ }
+ disconnect(m_media, SIGNAL(aboutToFinish()), this, SLOT(enqueueMedia()));
+ if (currentSourceChanged.isEmpty()) {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(currentSourceChanged(const Phonon::MediaSource &)), 3000));
+ }
+ QCOMPARE(currentSourceChanged.size(), 1);
+ QCOMPARE(finished.size(), 0);
+ QVERIFY(m_media->queue().isEmpty());
+ stopPlayback(m_media->state());
+}
+
+void tst_MediaObject::testPauseOnFinish()
+{
+ startPlayback();
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 1000);
+ QCOMPARE(m_media->state(), Phonon::PlayingState);
+ if (m_media->isSeekable() && m_media->totalTime() > 2000)
+ m_media->seek(m_media->totalTime() - 2000);
+ QTest::waitForSignal(m_media, SIGNAL(finished()), 4000);
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 1000);
+
+ QCOMPARE(m_media->state(), Phonon::PausedState);
+ connect(m_media, SIGNAL(finished()), m_media, SLOT(stop()));
+ m_media->seek(m_media->totalTime() - 2000);
+ m_media->play();
+
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 1000);
+ QCOMPARE(m_media->state(), Phonon::PlayingState);
+ QTest::waitForSignal(m_media, SIGNAL(finished()), 4000);
+ QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 1000);
+ stopPlayback(Phonon::StoppedState);
+}
+
+void tst_MediaObject::testReconnectBetweenTwoMediaObjects(){
+ // Purpose: Test that phonon can handle switching the same sink
+ // between different media objects.
+
+ Phonon::MediaObject obj1;
+ Phonon::MediaObject obj2;
+ Phonon::AudioOutput audio1;
+ Phonon::Path p1 = Phonon::createPath(&obj1, &audio1);
+ QVERIFY(p1.isValid());
+
+ QVERIFY(p1.reconnect(&obj1, &audio1));
+ QVERIFY(p1.isValid());
+ QVERIFY(p1.reconnect(&obj2, &audio1));
+ QVERIFY(p1.isValid());
+ QVERIFY(p1.reconnect(&obj1, &audio1));
+ QVERIFY(p1.isValid());
+
+ // Repeat the same test while playing:
+ QFile file(MEDIA_FILEPATH);
+ obj1.setCurrentSource(&file);
+ QFile file2(MEDIA_FILEPATH);
+ obj2.setCurrentSource(&file2);
+ obj1.play();
+ obj2.play();
+
+ QVERIFY(p1.reconnect(&obj1, &audio1));
+ QVERIFY(p1.isValid());
+ QVERIFY(p1.reconnect(&obj2, &audio1));
+ QVERIFY(p1.isValid());
+ QVERIFY(p1.reconnect(&obj1, &audio1));
+ QVERIFY(p1.isValid());
+}
+
+void tst_MediaObject::testPlayOnFinish()
+{
+ connect(m_media, SIGNAL(finished()), SLOT(setMediaAndPlay()));
+ startPlayback();
+ if (m_media->isSeekable()) {
+ m_media->seek(m_media->totalTime() - SEEK_BACKWARDS);
+ QVERIFY(QTest::waitForSignal(this, SIGNAL(continueTestPlayOnFinish()), 6000));
+ } else {
+ QVERIFY(QTest::waitForSignal(this, SIGNAL(continueTestPlayOnFinish()), 3000 + m_media->remainingTime()));
+ }
+ QTest::waitForSignal(m_media, SIGNAL(finished()), 1000);
+ stopPlayback(m_media->state());
+}
+
+void tst_MediaObject::testTickSignal()
+{
+ QTime start1;
+ QTime start2;
+#ifdef Q_OS_WINCE //On Windows CE we only provide ticks above 400ms
+ for (qint32 tickInterval = 400; tickInterval <= 1000; tickInterval *= 2)
+#else
+ for (qint32 tickInterval = 80; tickInterval <= 500; tickInterval *= 2)
+#endif
+ {
+ QSignalSpy tickSpy(m_media, SIGNAL(tick(qint64)));
+ //qDebug() << "Test 20 ticks with an interval of" << tickInterval << "ms";
+ m_media->setTickInterval(tickInterval);
+ QVERIFY(m_media->tickInterval() <= tickInterval);
+ QVERIFY(m_media->tickInterval() >= tickInterval/2);
+ QVERIFY(tickSpy.isEmpty());
+ m_media->seek(0); //let's go back to the beginning
+ start1.start();
+ startPlayback();
+ start2.start();
+ int lastCount = 0;
+ qint64 s1, s2 = start2.elapsed();
+ while (tickSpy.count() < 20 && (m_media->state() == Phonon::PlayingState || m_media->state() == Phonon::BufferingState))
+ {
+ if (tickSpy.count() > lastCount)
+ {
+ s1 = start1.elapsed();
+ qint64 tickTime = castQVariantToInt64(tickSpy.last().at(0));
+ lastCount = tickSpy.count();
+ // s1 is the time from before the beginning of the playback to
+ // after the tick signal
+ // s2 is the time from after the beginning of the playback to
+ // before the tick signal
+ // so: s2 <= s1
+ QVERIFY(tickTime <= m_media->currentTime());
+ if (s1 + ALLOWED_TICK_INACCURACY < tickTime || s2 - ALLOWED_TICK_INACCURACY > tickTime) {
+ qDebug()
+ << "\n" << lastCount << "ticks have been received"
+ << "\ntime from before playback was started to after the tick signal was received:" << s1 << "ms"
+ << "\ntime from after playback was started to before the tick signal was received:" << s2 << "ms"
+ << "\nreported tick time:" << tickTime << "ms"
+ << "\nallowed inaccuracy: +/-" << ALLOWED_TICK_INACCURACY << "ms";
+ for (int i = 0; i < tickSpy.count(); ++i) {
+ qDebug() << castQVariantToInt64(tickSpy[i].at(0));
+ }
+ }
+ QVERIFY(s1 + ALLOWED_TICK_INACCURACY >= tickTime);
+ QVERIFY(s2 - ALLOWED_TICK_INACCURACY <= tickTime);
+#ifndef Q_OS_WINCE
+ QVERIFY(s1 >= lastCount * m_media->tickInterval());
+#else
+ QVERIFY(s1 >= lastCount * m_media->tickInterval() - ALLOWED_TICK_INACCURACY);
+#endif
+ if (s2 > (lastCount + 1) * m_media->tickInterval())
+ QWARN(qPrintable(QString("%1. tick came too late: %2ms elapsed while this tick should have come before %3ms")
+ .arg(lastCount).arg(s2).arg((lastCount + 1) * m_media->tickInterval())));
+ } else if (lastCount == 0 && s2 > 20 * m_media->tickInterval()) {
+ QFAIL("no tick signals are being received");
+ }
+ s2 = start2.elapsed();
+ QTest::waitForSignal(m_media, SIGNAL(tick(qint64)), 2000);
+ }
+#ifndef Q_OS_WINCE //the shorter wave file is finished on Windows CE...
+ stopPlayback(Phonon::PlayingState);
+#else
+ stopPlayback(m_media->state());
+#endif
+ }
+}
+
+void tst_MediaObject::testSeek()
+{
+ m_media->seek(0); // let's seek back to the beginning
+ startPlayback();
+ QTime timer;
+ timer.start();
+ qint64 t = m_media->totalTime();
+ qint64 c = m_media->currentTime();
+ qint64 r = m_media->remainingTime();
+ int elapsed = timer.elapsed();
+ if (c + r > t + elapsed || c + r < t - elapsed) {
+ // qDebug() << "currentTime:" << c
+ // << "remainingTime:" << r
+ // << "totalTime:" << t;
+ QFAIL("currentTime + remainingTime doesn't come close enough to totalTime");
+ }
+
+ QVERIFY(c + r <= t + elapsed);
+ QVERIFY(c + r >= t - elapsed);
+ if (m_media->isSeekable())
+ if (r > 0)
+ {
+ m_media->setTickInterval(20);
+ qint64 s = c + r / 2;
+ testOneSeek(s);
+
+ s /= 2;
+ testOneSeek(s);
+ s = s * 3 / 2;
+ testOneSeek(s);
+
+ pausePlayback();
+
+ s = s * 3 / 2;
+ testOneSeek(s);
+ s /= 2;
+ testOneSeek(s);
+
+ m_media->setTickInterval(0);
+
+
+ stopPlayback(Phonon::PausedState);
+ return;
+ }
+ else
+ QWARN("didn't test seeking as the MediaObject reported a remaining size <= 0");
+ else
+ QWARN("didn't test seeking as the MediaObject is not seekable");
+ stopPlayback(Phonon::PlayingState);
+}
+
+
+void tst_MediaObject::setMediaAndPlay()
+{
+ m_stateChangedSignalSpy->clear();
+ QCOMPARE(m_stateChangedSignalSpy->count(), 0);
+
+ QSignalSpy totalTimeChangedSignalSpy(m_media, SIGNAL(totalTimeChanged(qint64)));
+ QVERIFY(m_media->currentSource().type() != MediaSource::Invalid);
+ Phonon::State state = m_media->state();
+ QVERIFY(state == Phonon::StoppedState || state == Phonon::PlayingState || Phonon::PausedState);
+ m_media->setCurrentSource(m_url);
+ // before calling play() we better make sure that if play() finishes very fast that we don't get
+ // called again
+ disconnect(m_media, SIGNAL(finished()), this, SLOT(setMediaAndPlay()));
+ state = m_media->state();
+ startPlayback2(state);
+
+ emit continueTestPlayOnFinish();
+}
+
+void tst_MediaObject::testPlayBeforeFinish()
+{
+ startPlayback();
+ QCOMPARE(m_stateChangedSignalSpy->size(), 0);
+ Phonon::State state = m_media->state();
+ QCOMPARE(state, Phonon::PlayingState);
+ m_media->setCurrentSource(m_url);
+ m_media->play();
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 4000));
+ }
+ // first (optional) state to reach is StoppedState
+ QList<QVariant> args = m_stateChangedSignalSpy->takeFirst();
+ Phonon::State oldstate = qvariant_cast<Phonon::State>(args.at(1));
+ QCOMPARE(oldstate, state);
+ state = qvariant_cast<Phonon::State>(args.at(0));
+ if (state == Phonon::StoppedState) {
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 4000));
+ }
+ args = m_stateChangedSignalSpy->takeFirst();
+ oldstate = qvariant_cast<Phonon::State>(args.at(1));
+ QCOMPARE(oldstate, state);
+ state = qvariant_cast<Phonon::State>(args.at(0));
+ }
+ // next LoadingState
+ QCOMPARE(state, Phonon::LoadingState);
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 4000));
+ }
+ // next either BufferingState or PlayingState
+ args = m_stateChangedSignalSpy->takeFirst();
+ oldstate = qvariant_cast<Phonon::State>(args.at(1));
+ QCOMPARE(oldstate, state);
+ state = qvariant_cast<Phonon::State>(args.at(0));
+ if (state == Phonon::BufferingState) {
+ if (m_stateChangedSignalSpy->isEmpty()) {
+ QVERIFY(QTest::waitForSignal(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), 4000)); // buffering can take a while
+ }
+ args = m_stateChangedSignalSpy->takeFirst();
+ oldstate = qvariant_cast<Phonon::State>(args.at(1));
+ QCOMPARE(oldstate, state);
+ state = qvariant_cast<Phonon::State>(args.at(0));
+ }
+#ifdef Q_WS_MAC
+ // m_media->setCurrentSource(m_url) in phonon frontend will always call
+ // 'stop' on the backend before calling 'setSource'. So the QT7 backend
+ // goes into stop, and naturally remains there after setting the new source.
+ // So going into playing state cannot happend when the backend is synchronized.
+ // Thats the reason for the ifdef.
+ QCOMPARE(state, Phonon::StoppedState);
+#else
+ stopPlayback(Phonon::PlayingState);
+#endif
+}
+
+void tst_MediaObject::cleanupTestCase()
+{
+ if (m_stateChangedSignalSpy)
+ delete m_stateChangedSignalSpy;
+ if (m_media)
+ delete m_media;
+#ifdef Q_OS_WINCE
+ QTest::qWait(200);
+#endif
+ if (!m_tmpFileName.isNull()) {
+ QVERIFY(QFile::remove(m_tmpFileName));
+ }
+#ifdef Q_OS_SYMBIAN
+ if (m_iapConnectionObserver)
+ delete m_iapConnectionObserver;
+#endif //Q_OS_SYMBIAN
+}
+
+void tst_MediaObject::_testOneSeek(qint64 seekTo)
+{
+ qint64 t = m_media->totalTime();
+ qint64 oldTime = m_media->currentTime();
+ if (oldTime == seekTo) {
+ return;
+ }
+
+ QTime seekDuration;
+ seekDuration.start();
+ m_media->seek(seekTo);
+
+ QVERIFY(oldTime == 0 || seekTo == 0 || m_media->currentTime() != 0);
+
+ int bufferingTime = 0;
+ Phonon::State s = m_media->state();
+ QTime timer;
+ if (s == Phonon::BufferingState) {
+ timer.start();
+ }
+ QEventLoop loop;
+ connect(m_media, SIGNAL(tick(qint64)), &loop, SLOT(quit()));
+ connect(m_media, SIGNAL(stateChanged(Phonon::State,Phonon::State)), &loop, SLOT(quit()));
+
+ qint64 c = m_media->currentTime();
+ qint64 r = m_media->remainingTime();
+ int elapsed = 0;
+ while (qAbs(c - seekTo) > ALLOWED_SEEK_INACCURACY){
+ QTimer::singleShot(ALLOWED_TIME_FOR_SEEKING, &loop, SLOT(quit()));
+
+ loop.exec();
+ c = m_media->currentTime();
+ r = m_media->remainingTime();
+ if (s == Phonon::BufferingState) {
+ bufferingTime += timer.restart();
+ } else {
+ timer.start();
+ }
+ s = m_media->state();
+ elapsed = seekDuration.elapsed();
+ QVERIFY(elapsed - bufferingTime < (ALLOWED_TIME_FOR_SEEKING + SEEKING_TOLERANCE));
+ }
+
+ QVERIFY(c >= seekTo - ALLOWED_SEEK_INACCURACY);
+ if (s == Phonon::PausedState) {
+ QVERIFY(bufferingTime == 0);
+ elapsed = 0;
+ }
+ if (c > seekTo + ALLOWED_SEEK_INACCURACY + elapsed - bufferingTime) {
+ QFAIL("currentTime is greater than the requested time + the time that elapsed since the seek started.");
+ }
+ if (c + r > t + 200 || c + r < t - 200) {
+ QFAIL("currentTime + remainingTime doesn't come close enough to totalTime");
+ }
+ m_success = true;
+}
+
+void tst_MediaObject::volumeSliderMuteVisibility()
+{
+ //this test doesn't really belong to mediaobject
+ // ### see if we should create a realy Phonon::VolumeSlider autotest
+ Phonon::VolumeSlider slider;
+ QVERIFY(slider.isMuteVisible()); // that is the default value
+ slider.setMuteVisible(true);
+ QVERIFY(slider.isMuteVisible());
+
+ //let's check that changing the visibility of the slider itself
+ //doesn't change what the slider reports
+ slider.setVisible(false);
+ QVERIFY(slider.isMuteVisible());
+ slider.setVisible(true);
+
+ slider.setMuteVisible(false);
+ QVERIFY(!slider.isMuteVisible());
+ slider.setMuteVisible(true);
+ QVERIFY(slider.isMuteVisible());
+}
+
+
+#endif //QT_NO_PHONON
+
+
+QTEST_MAIN(tst_MediaObject)
+
+#include "tst_mediaobject.moc"
+// vim: sw=4 ts=4
diff --git a/tests/auto/mediaobject_wince_ds9/dummy.cpp b/tests/auto/mediaobject_wince_ds9/dummy.cpp
new file mode 100644
index 0000000..27f7121
--- /dev/null
+++ b/tests/auto/mediaobject_wince_ds9/dummy.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** 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 test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+
+QTEST_NOOP_MAIN
+
diff --git a/tests/auto/mediaobject_wince_ds9/mediaobject_wince_ds9.pro b/tests/auto/mediaobject_wince_ds9/mediaobject_wince_ds9.pro
new file mode 100644
index 0000000..ec3cd59
--- /dev/null
+++ b/tests/auto/mediaobject_wince_ds9/mediaobject_wince_ds9.pro
@@ -0,0 +1,18 @@
+############################################################
+# Project file for autotest for file mediaobject.h
+############################################################
+
+load(qttest_p4)
+
+contains(QT_CONFIG, phonon):QT += phonon
+
+wince*{
+ SOURCES += ../mediaobject/tst_mediaobject.cpp
+ HEADERS += ../mediaobject/qtesthelper.h
+ RESOURCES += ../mediaobject/mediaobject.qrc
+ DEPLOYMENT_PLUGIN += phonon_ds9
+ DEFINES += tst_MediaObject=tst_MediaObject_ds9
+} else {
+ SOURCES += dummy.cpp
+}
+
diff --git a/tests/auto/phonon.pro b/tests/auto/phonon.pro
new file mode 100644
index 0000000..7549428
--- /dev/null
+++ b/tests/auto/phonon.pro
@@ -0,0 +1,5 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ mediaobject \
+# mediaobject_wince_ds9 \ This is Windows CE only (we test the second phonon backend ds9 here)
+
diff --git a/tests/global/.gitignore b/tests/global/.gitignore
new file mode 100644
index 0000000..1e49c60
--- /dev/null
+++ b/tests/global/.gitignore
@@ -0,0 +1,2 @@
+Makefile
+global.pro