Added qmafw-gst-subtitles-renderer-0.0.55 for Meego Harmattan 1.2
authorRoman Moravcik <roman.moravcik@gmail.com>
Thu, 23 Jun 2011 12:02:17 +0000 (14:02 +0200)
committerRoman Moravcik <roman.moravcik@gmail.com>
Thu, 23 Jun 2011 12:02:17 +0000 (14:02 +0200)
102 files changed:
qmafw-gst-subtitles-renderer/com.nokia.mafw.context_provider.libqmafw_gst_renderer.context [new file with mode: 0644]
qmafw-gst-subtitles-renderer/com.nokia.mafw.plugin.libqmafw_gst_renderer_plugin.service [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/changelog [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/compat [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/control [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/copyright [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/dirs [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/libqmafw-gst-subtitles-renderer.install [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/libqmafw-gst-subtitles-renderer.postinst [new file with mode: 0644]
qmafw-gst-subtitles-renderer/debian/rules [new file with mode: 0755]
qmafw-gst-subtitles-renderer/inc/MafwBlankingPreventer.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstRenderer.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstRendererDolby.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstRendererHaltState.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstRendererNetworkMonitor.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstRendererPlaylistFileUtility.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstRendererPlugin.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstRendererVolume.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwGstScreenshot.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/MafwMmcMonitor.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-seeker.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-utils.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-worker.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/mafw-gst-renderer-plugin.conf [new file with mode: 0644]
qmafw-gst-subtitles-renderer/qmafw-gst-subtitles-renderer.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwBlankingPreventer.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstRenderer.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstRendererDolby.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstRendererHaltState.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstRendererNetworkMonitor.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstRendererPlaylistFileUtility.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstRendererPlugin.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstRendererVolume.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwGstScreenshot.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/MafwMmcMonitor.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-seeker.c [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-utils.c [new file with mode: 0644]
qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-worker.c [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/LibCredsStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/MafwBasicRendererStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/MafwPlaylistFileUtilityStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/MafwRendererPolicyStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/MafwRendererPolicyStub.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/MafwRoutingInfoHandlerStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/MafwStubHelper.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/MafwStubHelper.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/QNetworkStubs.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/QNetworkStubs.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/common/renderer-worker-stub.c [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/media [new symlink]
qmafw-gst-subtitles-renderer/unittests/run_all_tests.sh [new file with mode: 0755]
qmafw-gst-subtitles-renderer/unittests/run_valgrind.sh [new file with mode: 0755]
qmafw-gst-subtitles-renderer/unittests/test.suppressions [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/ContextFWStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/MafwGstRendererDolbyStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/MafwMmcMonitorStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/QSettingsStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/QmSystemStub.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/Ut_MafwGstRenderer.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/Ut_MafwGstRenderer.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/ut_MafwGstRenderer.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/Ut_MafwGstRendererPlugin.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/Ut_MafwGstRendererPlugin.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/ut_MafwGstRendererPlugin.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker_stubs.c [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/MafwVolumeStubs.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.avi [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.wav [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/testframe.png [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitorStubs.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.cpp [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.h [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.pro [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test-station.pls [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test-station_invalid.pls [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test.asf [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/valgrind.xsl [new file with mode: 0644]
qmafw-gst-subtitles-renderer/unittests/valgrind_report.sh [new file with mode: 0755]

diff --git a/qmafw-gst-subtitles-renderer/com.nokia.mafw.context_provider.libqmafw_gst_renderer.context b/qmafw-gst-subtitles-renderer/com.nokia.mafw.context_provider.libqmafw_gst_renderer.context
new file mode 100644 (file)
index 0000000..e222b15
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<provider xmlns="http://contextkit.freedesktop.org/Provider"
+          bus="session" service="com.nokia.mafw.context_provider.libqmafw_gst_renderer">
+  <key name="Media.NowPlaying"/>
+</provider>
diff --git a/qmafw-gst-subtitles-renderer/com.nokia.mafw.plugin.libqmafw_gst_renderer_plugin.service b/qmafw-gst-subtitles-renderer/com.nokia.mafw.plugin.libqmafw_gst_renderer_plugin.service
new file mode 100644 (file)
index 0000000..e323c3a
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=com.nokia.mafw.plugin.libqmafw_gst_renderer_plugin
+Exec=/usr/bin/qmafw-dbus-wrapper /usr/lib/qmafw-plugin/libqmafw-gst-renderer-plugin.so
diff --git a/qmafw-gst-subtitles-renderer/debian/changelog b/qmafw-gst-subtitles-renderer/debian/changelog
new file mode 100644 (file)
index 0000000..f1b69f7
--- /dev/null
@@ -0,0 +1,1276 @@
+qmafw-gst-subtitles-renderer (0.0.55-1+0m6-1) unstable; urgency=low
+
+  * Added subtitles support.
+  * Added Subtitles control panel applet.
+
+ -- Roman Moravcik <roman.moravcik@gmail.com>  Wed, 22 Jun 2011 08:48:29 +0200
+
+qmafw-gst-renderer (0.0.55-1+0m6) unstable; urgency=low
+
+  * This entry has been added by BIFH queue processor
+    version has been changed to 0.0.55-1+0m6
+
+ -- BIFH Bot <sysint@maemo.research.nokia.com>  Mon, 23 May 2011 20:10:36 +0300
+
+qmafw-gst-renderer (0.0.55-1) unstable; urgency=low
+
+  * Fixes: NB#258573 - Never played , most played , recently payed queries does not yield any results
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 23 May 2011 20:10:35 +0300
+
+qmafw-gst-renderer (0.0.54-1) unstable; urgency=low
+
+  * Fixes: NB#253849 - “Can’t play the video because it’s the wrong format” error throws while trying to play any video when music suite is in background.
+  * MafwGstRenderer creates video-sink only if XID is set.
+  * Dependency to new gstreamer added.
+  * Fixing coverity findings.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 11 May 2011 07:44:56 +0300
+
+qmafw-gst-renderer (0.0.53-1) unstable; urgency=low
+
+  * Fixes: NB#240728 - Resources are granted too early
+  * Fixes: NB#250212 - Possible memory leak [+1332kB] could be seen in qmafw-dbus-wrapper
+  * VideoResource PID usage plus resources released even with non-seekable 
+    streams.
+  * GstBuffer now deleted with gst_buffer_unref (GstBuffer does not inherit 
+    GstObject).
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 05 May 2011 13:29:33 +0300
+
+qmafw-gst-renderer (0.0.52-1) unstable; urgency=low
+
+  * Fixes: NB#248815 - Dolby setting changes has no effect after relaunching application
+  * Check the values of the audio/video route ContextProperty instances after 
+    creating them.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 02 May 2011 19:46:02 +0300
+
+qmafw-gst-renderer (0.0.51-1) unstable; urgency=low
+
+  * Fixes: NB#245854 - [SSU-Package Manager]:error seen at 'CRITICAL [contextc.cpp:109:int context_provider_init(DBusBusType, const char*)] Service already initialized' after SSU when opening video
+  * Fixes: NB#246993 - Renderer crashes if network is disabled during stream playback
+  * MAFW GStreamer renderer's latency-time setting changed back to 300000.
+  * Added global variable to monitor the initialisation state of process wide 
+    singleton inside context fw.
+  * Also stopped setting some properties that omapxvsink doesn't have.
+  * MafwGstRenderer can handle network changes for simple streams.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 20 Apr 2011 18:30:41 +0300
+
+qmafw-gst-renderer (0.0.50-1) unstable; urgency=low
+
+  * Fixes: NB#244162 - "Unable to play unsupported video format" is displayed while playing 1080p video file.
+  * Fixes: NB#242441 - wrong error message displayed when stream is not reachable
+  * Fixes: NB#242345 - Renderer goes to buffering loop when playing online stream
+  * MafwGstRenderer correctly generates unsupported resolution error.
+  * MafwGstRenderer sends URINotAvailable error for not found streams.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 07 Apr 2011 10:01:57 +0300
+
+qmafw-gst-renderer (0.0.49-1) unstable; urgency=low
+
+  * Removed obsolete code for pausing playback when headphones get disconnected.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 05 Apr 2011 07:48:12 +0300
+
+qmafw-gst-renderer (0.0.48-1) unstable; urgency=low
+
+  * Fixes: NB#236498 - Music suite does not continue internet radio playback after internet connection is renegotiated.
+  * Fixes: NB#238504 - Handover from WLAN to 3G does not happen when streaming audio
+  * Fixes: NB#240756 - <coverity> defects from qmafw-gst-renderer/0.0.46-1_0m6
+  * Fixes: NB#239983 - Remove dependencies to DRM Subsystem
+  * Fixes: NB#239428 - Black thumbnail displayed in minimized view after seek and swiping during online playback
+  * MafwGstRenderer tries to handle network changes gracefully.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 30 Mar 2011 20:55:34 +0300
+
+qmafw-gst-renderer (0.0.47-1) unstable; urgency=low
+
+  * Fixes: NB#235660 - The note "Unable to play song, file not found" is shown with some music clips
+  * Adds proper encoding for file URI in some cases. Affects file paths which 
+    contain non-ASCII characters.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 24 Mar 2011 19:04:58 +0200
+
+qmafw-gst-renderer (0.0.46-1) unstable; urgency=low
+
+  * Fixes: NB#238161 - Playback fails until reboot after playing unsupported media file
+  * Fixes: NB#236869 - Names with special characters are not shown correctly in Music Player
+  * Fixes: NB#237491 - nie:usageCounter isn't updated if one of nie:usageCounter and nie:contentAccessed is missing
+  * Fixes: NB#237464 - Song play count is not updated properly.
+  * Dependencies modified for new DRM packaging.
+  * MafwGstRenderer returns duration as position in eos if query is not 
+    succesful.
+  * Gst Renderer now uses QString::fromUtf8 to read in the UTF-8 (or ASCII) 
+    tags from GStreamer.
+  * MafwGstRenderer updates usageCounter for repeating media.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 22 Mar 2011 21:39:56 +0200
+
+qmafw-gst-renderer (0.0.45-1) unstable; urgency=low
+
+  * Fixes: NB#236498 - Music suite does not continue internet radio playback after internet connection is renegotiated.
+  * Fixes: NB#233404 - Renderer removed when play->stop actions are repeated many times
+  * Fixes: NB#229794 - Music Player failed to handle empty playlists (qtn_musi_empty_playlist not shown)
+  * MafwBasicRenderer better handling for stopped to pause transitions for 
+    updating the mediaChanged() signal.
+  * MafwGstRenderer tries to restart infinite length streams when EOS 
+    encountered.
+  * Switch to using the new policy context keys.
+  * Changed critical message to just warning and added hint why it maybe printed.
+  * Error signalling when trying to play empty playlist file.
+  * libqttracker removed from mafw.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 17 Mar 2011 14:12:12 +0200
+
+qmafw-gst-renderer (0.0.44-1) unstable; urgency=low
+
+  * Fixes: NB#225667 - First frame flashes for fraction of sec just before playback resumes from previously watched position
+  * Fixes: NB#231298 - libqmafw-gst-renderer pulls gstreamer0.10-plugins-good-extra
+  * Fixes: NB#225941 - While Adding two songs via BT,One song goes to never played playlist and other goes to  recently played playlist.
+  * Removed some unnecessary dependencies.
+  * Removed the dependency to plugins-good-extra.
+  * Unit testing for played stamping fixed.
+  * Fix for played stamping if piece was not harvested when it is played.
+  * MafwGstRenderer duration is signaled, among others.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 03 Mar 2011 22:23:09 +0200
+
+qmafw-gst-renderer (0.0.43-1) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2666
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 25 Feb 2011 06:20:50 +0200
+
+qmafw-gst-renderer (0.0.42-1) unstable; urgency=low
+
+  * Fixes: NB#228964 - Video Rendrer crashes randomly on tapping next.
+  * Fixes: NB#219808 - Renderer state doesn't change, when video stream is launched.
+  * Removed unnecessary XError handling from mafw-gst-renderer.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 22 Feb 2011 18:22:29 +0200
+
+qmafw-gst-renderer (0.0.41-1) unstable; urgency=low
+
+  * Fixes: NB#219808 - Renderer state doesn't change, when video stream is launched.
+  * MACHINE READABLE LINE: pre-release commit.
+  * ABI BREAK: Changes MafwRenderer::play(QUrl) to accept starting position to 
+    start playback from as parameter
+  * MACHINE READABLE LINE: pre-release commit.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 21 Feb 2011 10:17:29 +0200
+
+qmafw-gst-renderer (0.0.40-1) unstable; urgency=low
+
+  * ABI BREAK: Changes MafwRenderer::play(QUrl) to accept starting position to 
+    start playback from as parameter.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 17 Feb 2011 23:26:02 +0200
+
+qmafw-gst-renderer (0.0.39-1) unstable; urgency=low
+
+  * Fixes: NB#224017 - Hash marks are double encoded in renderer's metadataChanged signals
+  * MafwRenderer URL encoding handling improvements. Delimiter characters 
+    handled correctly.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Sun, 13 Feb 2011 22:06:45 +0200
+
+qmafw-gst-renderer (0.0.38-1) unstable; urgency=low
+
+  * Fixes: NB#207278 - Fast forward /rewind can not work during playing special MPEG4 video clip.
+  * Fixes: NB#222381 - pauseframes don't have unique names
+  * MafwGstRenderer tries to do better seek if a key frame seeks does not 
+    advance or even goes backwards. It tries to find the next key frame.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 08 Feb 2011 06:21:07 +0200
+
+qmafw-gst-renderer (0.0.37-1) unstable; urgency=low
+
+  * Fixes: NB#214335 - Unable to play. file not found message appears before the online playback starts
+  * Fixes: NB#217783 - Seekbar information and timer increment mismatch for particular .AAC clip.
+  * Fixes: NB#180798 - Music does not stop playing after DUT and  PC were connected as Mass storage mode
+  * Now the playlist file playback doesn't report errors about individual uris.
+  * The possible error is reported only after the last uri has also been tried.
+  * MafwGstRenderer does not sent duration in nanosecond precision in some 
+    scenarios.
+  * MafwGstRenderer listens for pre-unmount signal from usb_moded.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 03 Feb 2011 19:54:23 +0200
+
+qmafw-gst-renderer (0.0.36-1) unstable; urgency=low
+
+  * Fixes: NB#220938 - Buffering banner not displayed for Iradio applet if applet invoked first time(Before Audio Player) after flashing
+  * Fixes: NB#210899 - Playback is stopped after TV-Out cable is plugged and unplugged for DRM restricted video
+  * MafwGstRenderer pauses when unallowed route switch occurs.
+  * MafwGstRenderer updates duration to tracker, also MafwBasicRenderer 
+    provides duration metadata in MafwMediaInfo with doPlay().
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 31 Jan 2011 08:30:21 +0200
+
+qmafw-gst-renderer (0.0.35-2) unstable; urgency=low
+
+  * Version increased for reintegration.
+  * Pause frame timer now takes milliseconds instead of seconds and default is 
+    now 700 ms.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 27 Jan 2011 11:18:14 +0200
+
+qmafw-gst-renderer (0.0.35-1) unstable; urgency=low
+
+  * Pause frame timer now takes milliseconds instead of seconds and default is 
+    now 700 ms.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 24 Jan 2011 06:17:12 +0200
+
+qmafw-gst-renderer (0.0.34-1) unstable; urgency=low
+
+  * Fixes: NB#213693 - TVandvideo releases playback resources too early
+  * Fixes: NB#217389 - Black screen is displayed in video pause mode when an incoming call comes
+  * Png encoder now uses compression-level 1. This should improve performance.
+  * MafwGstRenderer copies gstbuffer for further handling of pause. Also 
+    resources are informed as being released only when they are released.
+  * Pause frame pipeline is now reused.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 18 Jan 2011 22:11:19 +0200
+
+qmafw-gst-renderer (0.0.33-2) unstable; urgency=low
+
+  * Fixes: NB#215967 - When tapped during first 3 secs of playback seekbar behaves strangely in online player
+  * Fixes: NB#211139 - Pause button shown instead of stop for non seekable streams
+  * Fixes: NB#214376 - getPosition starts returning constant value after setPosition for nonseekable stream
+  * Version increased.
+  * Added resetting the error flag of the pipeline, if the playback attempt 
+    ends because of DRM destination check, before the pipeline gets actually used.
+  * Changed the redirect message test case.
+  * MafwGstRenderer duration query fixes for media startup.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 17 Jan 2011 09:42:43 +0200
+
+qmafw-gst-renderer (0.0.32-1) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2546
+  * Fixes: NB#214969 - No audio while playback when auto advance is set 'off' and then 'on' in a particular scenario
+  * Fixes: NB#213330 - Whitespaces are not encoded in renderer's metadataChanged signals
+  * Fixes: NB#206030 - Music playback prevents reaching 60 fps panning performance
+  * Added MafwGstScreenshot.cpp and .h to .pro file.
+  * Added MafwGstScreenshot.h and .cpp to pro file.
+  * mmcPreUnmount is back.
+  * MAFW_METADATA_KEY_URI emitted in encoded form.
+  * MafwGstRenderer latency-time tuning.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 04 Jan 2011 08:17:20 +0200
+
+qmafw-gst-renderer (0.0.31-1) unstable; urgency=low
+
+  * Fixes: NB#194458 - CJSE:NFT:AudioPlayer:CJSE_NFT13 test case is failing
+  * Fixes: NB#211505 - Internet stream URI metadata not emitted
+  * Fixes: NB#209526 - Noise heard on DRM protected clip playback attempt
+  * Fixed few TYPOs on ut_MafwMmcMonitor.
+  * Wrong notification was displayed if text file which was not playlist were 
+    tried to be played without mime type.
+  * MafwGstRenderer MMC monitoring.
+  * trackerRelease call added to gst-renderer unit tests cleanup.
+  * MAFW error code DRM error for clock not set added.
+  * Playback outputs are checked for DRM clips before starting playback.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 21 Dec 2010 12:35:49 +0200
+
+qmafw-gst-renderer (0.0.30-1) unstable; urgency=low
+
+  * Fixes: NB#206367 - calling pauseAt(uint) emits playing state signal before pause signal
+  * MafwGstRenderer does not send playing state first when calling pauseAt.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 13 Dec 2010 06:49:56 +0200
+
+qmafw-gst-renderer (0.0.29-1) unstable; urgency=low
+
+  * Fixes: NB#207882 - Seek does not work for the attached mp3 clip.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 09 Dec 2010 10:55:48 +0200
+
+qmafw-gst-renderer (0.0.28-1) unstable; urgency=low
+
+  * Fixes: NB#208336 - Wrong notification is displayed when playing 1080p video clip.
+  * Fixes: NB#207288 - Video playback starts from beginning when resumed playback in certain scenario
+  * Fixes: NB#207837 - Dolby effectss not preserved after reconnecting the headset
+  * There was a logical error in the for loop, which caused infinite loop with 
+    some medias.
+  * Some files were earlier left out of the commit (pipeline configurability) 
+    because of conflicts.
+  * Duration handling removed in ready state.
+  * MafwGstRenderer can be configured via text file.
+  * Bug changed video settings as the active ones when reconnecting headset. 
+    Now works correctly.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 07 Dec 2010 21:50:59 +0200
+
+qmafw-gst-renderer (0.0.27-1) unstable; urgency=low
+
+  * Fixes: NB#208106 - Playback starts from the beginning of the clip on Resume after a call
+  * g_asserts removed from release builds.
+  * Added dependency to gstreamer0.10-plugins-bad
+  * There was a small error in the logic of handling the duration 
+    unavailability.
+  * Now the last known seekability value is actually used, if the duration is 
+    not known.
+  * Small fixes for MMS stream buffer size handling.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 03 Dec 2010 08:27:33 +0200
+
+qmafw-gst-renderer (0.0.26-1) unstable; urgency=low
+
+  * Fixes: NB#199374 - Unable to stream ASF videos
+  * Fixes: NB#199405 - Unable to stream WMV videos through MMS and http
+  * Fixes: NB#203058 - “Unable to play song, Media format is not supported” pops up after the special playback is finished.
+  * Fixes: NB#207747 - WMA with Multichannel encoding not playing
+  * Fixes: NB#208036 - "unable to play song, media format not supported" is displayed for few WMA files.
+  * CI Test case for bug that timers for calling playNextURIFromPlaylist are 
+    not cancelled.
+  * Fallback mechanism for playlist file playback error.
+  * Changed flags from 99 to 67 when using DHM to support "unsupported" audio.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 30 Nov 2010 21:14:12 +0200
+
+qmafw-gst-renderer (0.0.25-1) unstable; urgency=low
+
+  * Fixes: NB#204996 - COREWEB: /usr/bin/qmafw-dbus-wrapper 'QString::operator< qMapLessThanKey findNode value MafwMediaInfo::firstMetaData'
+  * Fixes: NB#206947 - Duplicated is-seekable metadata received
+  * MafwGstRenderer does not send same metadata value again
+  * Added cancellation of screenshot capture into various cases.
+  * It is a strong assumption that 204996 is caused by the screenshot never 
+    being cancelled.
+  * MafwGstRenderer does not send seekability metadata unless it changes.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Sun, 28 Nov 2010 18:32:23 +0200
+
+qmafw-gst-renderer (0.0.24-1) unstable; urgency=low
+
+  * Fixes: NB#206561 - Playback fails after multiple seek of mms stream
+  * Fixes: NB#205172 - Audio not heard for the next file playable when "codec not found" error pops up
+  * MafwGstRenderer: Improved handling of seeking-buffering-pause sequences
+  * MafwGstRenderer reuses audio elements when reconstructing pipeline.
+
+ -- Jukka Heikkilä <ext-jukka.1.heikkila@nokia.com>  Thu, 25 Nov 2010 08:26:54 +0200
+
+qmafw-gst-renderer (0.0.23-1) unstable; urgency=low
+
+  * Fixes: NB#202071 - Unable to stream WMA audio through MMS.
+  * Added dependency to gstreamer0.10-plugins-good-extra.
+  * It is needed because it provides png encoder.
+
+ -- Jukka Heikkilä <ext-jukka.1.heikkila@nokia.com>  Fri, 19 Nov 2010 08:16:55 +0200
+
+qmafw-gst-renderer (0.0.22-1) unstable; urgency=low
+
+  * Fixes: NB#203250 - Dropping sdpdemux patch from meego gstreamer -bad package
+  * Fixes: NB#203010 - ‘Playback error: 326’ pops up when seeked till end during playback
+  * Fixes: NB#197812 - Error message displayed while resuming an rtsp stream playback
+  * Use "element-added" signal to get queue2 element from the pipeline.
+  * rm ==> rm -f
+
+ -- Jukka Heikkilä <ext-jukka.1.heikkila@nokia.com>  Thu, 11 Nov 2010 12:59:59 +0200
+
+qmafw-gst-renderer (0.0.21-1) unstable; urgency=low
+
+  * GstRenderer remove unnecessary context provider check from initialize.
+  * Default room size of Dolby effect changed from 0 to 2.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 08 Nov 2010 16:24:07 +0200
+
+qmafw-gst-renderer (0.0.20-1) unstable; urgency=low
+
+  * Fixes: NB#201764 - Playing online stream doesn't always start
+  * Fixes: NB#201569 - Play count and content accessed data not available when video clip is played with uri.
+  * Fixes: NB#199784 - No audio output for YouTube video when audio is paused from music application by unplug the headset.
+  * Removed one buffer size optimisation (setting buffer-duration in playbin2)
+    as it seemed to make gstreamer a bit unstable.
+  * Replaced Qt keywords with appropriate macros.
+  * MAFW to use libqmsystem2.
+  * Replaced emit and signals keywords with corresponding macros to make the 
+    test compile again.
+  * Removing code that is nowadays unnecessary and causing valgrind findings.
+  * Gst renderer updating usageCount and contentAccessed in play URI case
+  * MafwGstRenderer now releases resources when headphones are disconnected, 
+    which causes playback to pause.
+  * Added one more suppression related to g_type_register_static.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 04 Nov 2010 22:54:27 +0200
+
+qmafw-gst-renderer (0.0.19-2) unstable; urgency=low
+
+  * Version increased.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 02 Nov 2010 14:56:39 +0200
+
+qmafw-gst-renderer (0.0.19-1) unstable; urgency=low
+
+  * Fixes: NB#199965 - mafw-gst-renderer fails to build with GLib 2.26
+  * The error code mapping was changed earlier. Now correcting the unit test 
+    accordingly.
+  * Disabled moc keywords from mafw-gst-renderer.
+  * CI tests for dbus-wrapper lingering.
+  * Generalised libc6 library condition in some suppresions.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 01 Nov 2010 13:52:03 +0200
+
+qmafw-gst-renderer (0.0.18-1) unstable; urgency=low
+
+  * Removed unnecessary LKM stubs from unit tests and enabled -Werror where it 
+    was disabled because of LKM-caused warnings.
+  * Little formatting change in mafw-gst-renderer and error code fix when 
+    mapping gstreamer errors to worker errors.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 29 Oct 2010 10:46:35 +0300
+
+qmafw-gst-renderer (0.0.17-1) unstable; urgency=low
+
+  * Removed unnecessary LKM stubs from unit tests and enabled -Werror where it 
+    was disabled because of LKM-caused warnings.
+  * Little formatting change in mafw-gst-renderer and error code fix when 
+    mapping gstreamer errors to worker errors
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 28 Oct 2010 13:50:53 +0300
+
+qmafw-gst-renderer (0.0.16-1) unstable; urgency=low
+
+  * Fixes: NB#197421 - Seeking back functions as 'Next', and also jumps to every second video in a yt playlist after seek back at an end of a clip once
+  * Fixes: NB#196798 - Total duration of a seekable stream is not seen if a playlist is present already
+  * Fixes: NB#197812 - Error message displayed while resuming an rtsp stream playback
+  * Gst renderer regression fixed when resuming from ready state now works.
+  * Live source seeking is now delayed in Paused state. CITA test fixes, plus 
+    last version info commits.
+  * Removed temporary fixes to counter build break on x86 target: DRM libraries 
+    are again required for all architectures and temporary stubs are removed.
+  * Added initilization for m_pendingCall member on MafwGstRendererVolume.
+  * Dolby mixer enabled.
+  * MafwGstRenderer behaves correctly and sends only one playing state change 
+    even when seeking while in playing state.
+  * A bug prevented DRM playback because drm_create_uri() was given 0 as 
+    maximum length of string.
+  * Seekability is now send as false, when duration is unknown.
+  * DRM stub definitions changed to function declarations.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 26 Oct 2010 22:07:05 +0300
+
+qmafw-gst-renderer (0.0.15-1) unstable; urgency=low
+
+  * Removed volume intialization at gst renderer startup. Volume is currently 
+    set by system component and volume initialization at gst-renderer startup 
+    causes unneeded processing.
+  * DRM client i486 support was removed. Implemented temporary stubs for those 
+    used in i486 target.
+  * Updated DRM library version numbers to dependencies and removed dependency 
+    to DRM from non-ARM.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 18 Oct 2010 21:10:09 +0300
+
+qmafw-gst-renderer (0.0.14-1) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2457
+  * Fixes: NB#197668 - Unable to play DRM clip second time using the same renderer and not more than twice using any renderer
+  * Fixes: NB#186008 - MaFW play for audio streaming taking long time
+  * Fixes: NB#196891 - Sometimes resume is not working when called after audiopolicy is given back to music-suite
+  * Adaptation to API change in libdrm-playready0.
+  * Moved clearing worker->destinations from _reset_pipeline_and_worker() to 
+    mafw_gst_renderer_worker_exit().
+  * Increased mmsh buffer duration.
+  * Added usage of connection-speed and buffer-duration properties of playbin2. 
+    Subsequent task is needed to make more elegant final solution, but this 
+    should be enough for the bug.
+  * MafwGstRenderer handles earpiece audio route as builtin speaker route.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 14 Oct 2010 15:42:56 +0300
+
+qmafw-gst-renderer (0.0.13-1) unstable; urgency=low
+
+  * Fixes: NB#196975 - <coverity> defects from MAFW
+  * Dolby effect disabled for now.
+  * Part VIII: MafwGstRenderer unittest valgrind suppression file updated.
+  * Part VII: MafwGstRenderer unittest valgrind suppression file updated.
+  * Coverity findings fixed.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 11 Oct 2010 12:09:24 +0300
+
+qmafw-gst-renderer (0.0.12-1) unstable; urgency=low
+
+  * MafwGstRenderer unittest valgrind suppression file updated.
+  * Unittests for Dolby effect.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 08 Oct 2010 09:47:20 +0300
+
+qmafw-gst-renderer (0.0.11-1) unstable; urgency=low
+
+  * Fixes: NB#196267 - Renderer is lost after random qmafw-dbus-wrapper crash, only reflash the way out
+  * Fixes: NB#196026 - Renderer gets stuck on performing playback by 'Play uri' for a particular m3u playlist
+  * GstRenderer and YoutubeSource plugins dbus .service file naming convention.
+  * Moved Dolby initialization to worker initialization and added check for 
+    m_worker.
+  * Added Dolby effect audio route handling.
+  * MafwGstRenderer send playbackCompleted() even if error case when playing 
+    playlistURI. Fixes faulty cleanup in mafw-gst-renderer-worker.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 06 Oct 2010 19:57:13 +0300
+
+qmafw-gst-renderer (0.0.10-1) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-1820
+  * Fixes: NB#182065 - BT downloaded music clip does not play while camera is open in still picture mode.
+  * Added initialization list to get correct behavior.
+  * Added support for Dolby Headphone feature.
+  * GstRenderer fix in render-rectangle parsing.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 05 Oct 2010 08:23:43 +0300
+
+qmafw-gst-renderer (0.0.9-1) unstable; urgency=low
+
+  * Fixes: NB#188929 - The Audio is not heard through wired headset when already connected BT headset is disconnected
+  * In MafwGstRenderer bluetooth headset disconnecting is handled in same way 
+    as wired headset.
+  * Correct error code emission for DRM "no license" case.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 01 Oct 2010 10:53:27 +0300
+
+qmafw-gst-renderer (0.0.8-1) unstable; urgency=low
+
+  * Fixes: NB#194221 - Seekability value is wrong for Internet radio streams
+  * Partial fix for #194442. MafwGstRenderer does more robust network change 
+    observations
+  * We don't send out a gstreamer query in case we don't know the duration.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 29 Sep 2010 18:29:54 +0300
+
+qmafw-gst-renderer (0.0.7-1) unstable; urgency=low
+
+  * Fixes: NB#193425 - Video image it not seen when starting playback in some cases
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 23 Sep 2010 20:46:07 +0300
+
+qmafw-gst-renderer (0.0.6-1) unstable; urgency=low
+
+  * Fixes: NB#193662 - qmafw package may have resource token problem with Tracker, please verify.
+  * Fixes: NB#193682 - qmafw-gst-renderer package may have resource token problem with Tracker, please verify.
+  * Fixes: NB#186008 - MaFW play for audio streaming taking long time
+  * Fixes: NB#190121 - Online video clip fails to play from the position where it was paused before
+  * Fixes: NB#192157 - qmafw-shared: add pkg-config to build-deps
+  * Added API documentation about the required credentials.
+  * Decreased the buffer size to 30 % of the original. It takes another second 
+    off the stream start delay.
+  * gst-renderer seeks live streams in PLAYING state.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 22 Sep 2010 21:20:17 +0300
+
+qmafw-gst-renderer (0.0.5-1) unstable; urgency=low
+
+  * Fixes: NB#192243 - Pause->resume->pause->resume sequence causes some videos to start from beginning.
+  * Fixes: NB#191257 - performance problem after renderer pause playback
+  * InvalidURI was sometimes incorrectly received as error code. Changed to 
+    correct UNSUPPRTED TYPE code.
+  * Added a check for seekability request's result validity. If unknown is
+  * passed as a value, it's ignored.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 20 Sep 2010 07:35:57 +0300
+
+qmafw-gst-renderer (0.0.4-1) unstable; urgency=low
+
+  * Fixes: NB#190307 - Black frame displayed when tap on screen after swiping to next clip
+  * Fixes: NB#189621 - Stream Playback starts playing from the beginning after a call or pause/resume after few seconds.
+  * Fixes: NB#190121 - Online video clip fails to play from the position where it was paused before
+  * MafwGstRenderer resumes from correct position after resources released in 
+    pause state when streaming content.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 17 Sep 2010 05:42:44 +0300
+
+qmafw-gst-renderer (0.0.3-1) unstable; urgency=low
+
+  * Implemented: MMAFW-2416
+  * Fixes: NB#190752 - Music player does not plays after invalid video is played
+  * MafwGstRenderer reacts to network changes by emitting and error when 
+    streaming cannot continue.
+  * Version dependency for playready packages updated.
+  * Fixed bug that stream playback is resumed automatically after a call.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 15 Sep 2010 07:51:45 +0300
+
+qmafw-gst-renderer (0.0.2-1) unstable; urgency=low
+
+  * Fixes: NB#190393 - Stream buffers after 1-2 seconds of playback ,everytime after playback is initiated
+  * Fixes: NB#186008 - MaFW play for audio streaming taking long time
+  * Streaming optimization for mms streams.
+  * added CONFIG += plugin in .pro file
+  * fallback to alsasink in worker code
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 10 Sep 2010 13:22:17 +0300
+
+qmafw-gst-renderer (0.0.1-73) unstable; urgency=low
+
+  * Buffering optimization for mms streams.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 08 Sep 2010 06:54:04 +0300
+
+qmafw-gst-renderer (0.0.1-72) unstable; urgency=low
+
+  * Fixes: NB#189707 - Playback from a playlist differs with the presence of local playlist
+  * Added getUriList function to MafwPlaylistFileUtilityStub so that the
+    untitests can pass.
+  * Added a waiting time for the playlist parser so that playing URI lists
+    doesn't stop when empty items are found before parsing the list far enough.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 06 Sep 2010 22:24:21 +0300
+
+qmafw-gst-renderer (0.0.1-71) unstable; urgency=low
+
+  * Lintian warnings fixed.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Sun, 05 Sep 2010 21:58:13 +0300
+
+qmafw-gst-renderer (0.0.1-70) unstable; urgency=low
+
+  * mafw-gst-renderer rebuild needed because of libplayready packaging changes.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 02 Sep 2010 10:47:27 +0300
+
+qmafw-gst-renderer (0.0.1-69) unstable; urgency=low
+
+  * Implemented: MMAFW-2006
+  * Fixes: NB#187115 - DRM playback stops and throws a error on receiving a call.
+  * Fixes: NB#188378 - End of playlist reached after playing first song/stream in the Playlist file
+  * Fixes to playlist URI playing and signalling.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 31 Aug 2010 10:08:44 +0300
+
+qmafw-gst-renderer (0.0.1-68) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2006
+  * Implemented: SWP#MMAFW-2243
+  * Fixes: NB#183176 - Resuming music after playing video with music in paused state doesn't work
+  * Fixes: NB#176434 - When pausing a song, music-suite does not release audio resource
+  * Signalling paused-thumbnail-uri metadata fixed.
+  * Playlist file playback support in gst-renderer.
+  * Pause state releases resources, although 2 seconds later.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 26 Aug 2010 13:56:02 +0300
+
+qmafw-gst-renderer (0.0.1-67) unstable; urgency=low
+
+  * Implemented: MMAFW-2331
+  * Fixes: NB#184640 - Fast seek makes playback unreliable
+  * Related metadata added to pause-frame-uri metadata: URI to video file the 
+    frame is from and the position in seconds.
+  * RTSP redirect MAFW implementation.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 23 Aug 2010 15:46:40 +0300
+
+qmafw-gst-renderer (0.0.1-66) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2261
+  * Implemented: SWP#MMAFW-2359
+  * Fixes: NB#184583 - audio continues even after playback is completed when tried to play an online video
+  * No longer automatic resume when buffering after seek after EOS.
+  * Bypasses bug of resetting render-rectangle values does not work.
+  * Werror compile flag back to use.
+  * GstRenderer media routing info provider's credential check.
+  * Missing unittests change for render rectangle added.
+  * gstreamer X Overlay render rectangle setting possible via mafwgstrenderer.
+  * colorkey reverted back to 0x080810.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 18 Aug 2010 07:30:56 +0300
+
+qmafw-gst-renderer (0.0.1-65) unstable; urgency=low
+
+  * Fixes to pkg-config usage, now pointing PKG_CONFIG_PATH into -uninstalled 
+    .pc files makes it possible to compile mafw, mafw-shared and mafw-gst-plugin.
+  * Video sink colorkey is now 0xff00ff.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 12 Aug 2010 15:05:34 +0300
+
+qmafw-gst-renderer (0.0.1-64) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2358
+  * Implemented: SWP#MMAFW-380
+  * Pause playback when headset disconnected.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 09 Aug 2010 09:38:36 +0300
+
+qmafw-gst-renderer (0.0.1-63) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-918
+  * Fixes: NB#183564 - Video doesn't play when tap on a video file in VideosandTv application
+  * Explicit version for libdrm-playready0-dev build dependency.
+  * Enhancements to gstscreenshot code.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 06 Aug 2010 07:46:00 +0300
+
+qmafw-gst-renderer (0.0.1-62) unstable; urgency=low
+
+  * Fixes: NB#176165 - MAFW should not wait for gst state changes to complete
+  * Fixes mafw-gst-renderer unittests. Policy functionality changes in 
+    MafwBasicRenderer changed the API
+
+ -- Tuomas Inkeroinen <ext-tuomas.1.inkeroinen@nokia.com>  Thu, 29 Jul 2010 12:43:20 +0300
+
+qmafw-gst-renderer (0.0.1-61) unstable; urgency=low
+
+  * Fixes: NB#179733 - 
+  * Fix for bug 179733 - Multiple seek beyond the duration of the video clip 
+    hangs playback
+
+ -- Tuomas Inkeroinen <ext-tuomas.1.inkeroinen@nokia.com>  Mon, 26 Jul 2010 10:58:33 +0300
+
+qmafw-gst-renderer (0.0.1-60) unstable; urgency=low
+
+  * Fixes: NB#179782 - When a video is continuously skipped forward by 10 seconds in playing state, the pause control changes to play, while video continues to play
+  
+ -- Tuomas Inkeroinen <ext-tuomas.1.inkeroinen@nokia.com>  Thu, 22 Jul 2010 08:54:27 +0300
+
+qmafw-gst-renderer (0.0.1-59) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2330
+  * We now use pngenc for pause frames instead of jpegenc
+
+ -- Jukka Heikkilä <ext-jukka.1.heikkila@nokia.com>  Thu, 15 Jul 2010 09:55:39 +0300
+
+qmafw-gst-renderer (0.0.1-58) unstable; urgency=low
+
+  * Fixes: NB#177617 - Playcount does not increase when a clip is played repeatedly in player view
+  * Coverity issues fixed.
+  * mafw-gst-renderer usageCounter and contentAccessed update on replay
+
+ -- Jukka Heikkilä <ext-jukka.1.heikkila@nokia.com>  Tue, 13 Jul 2010 12:34:26 +0300
+
+qmafw-gst-renderer (0.0.1-57) unstable; urgency=low
+
+  * Fixes: NB#176727 - Invalid pause frame given with pauseAt
+  * GstRenderer policy-context-daemon security token check
+
+
+ -- Jukka Heikkilä <ext-jukka.1.heikkila@nokia.com>  Thu, 08 Jul 2010 12:55:38 +0300
+
+qmafw-gst-renderer (0.0.1-56) unstable; urgency=low
+
+  * Fixes: NB#177006 - MAFW crash when playing regina spectres album.
+  * Earlier the "Next" URI was read from MafwMediaInfo into QString instead of 
+    QUrl.
+  * This caused the uri that was passed to be percent encoded.
+  * Syslog routines then failed with because they assumed the uri to specify 
+    format containing variables to be replaced.
+  * Append 'release'/'debug' into CONFIG variable rather than overwrite it.
+  * Earlier version caused extra 'strip' command into the Makefile. This in 
+    turn, cause dbg-package to be empty.
+
+ -- Jukka Heikkilä <ext-jukka.1.heikkila@nokia.com>  Tue, 29 Jun 2010 13:01:33 +0300
+
+qmafw-gst-renderer (0.0.1-55) unstable; urgency=low
+
+  * Fixes: NB#176077 - Screen blanking doesn't happen on playing videos in from video suite with TV-out connected
+  * Removed accidentally forgot wrt dependencies from pro file.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 24 Jun 2010 13:10:05 +0300
+
+qmafw-gst-renderer (0.0.1-54) unstable; urgency=low
+
+  * Remove lisence fething from mafw and only report error from gst-renderer.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 23 Jun 2010 10:14:45 +0300
+
+qmafw-gst-renderer (0.0.1-53) unstable; urgency=low
+
+  * Volume robustness test failing fixed.
+  * Build-Depends for libqttracker-dev (>= 1~6.9.5) and Depends for 
+    libqttracker1pre6 (>= 1~6.9.5) added, Standards-Version: 3.8.0 updated where 
+    needed.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 17 Jun 2010 07:47:49 +0300
+
+qmafw-gst-renderer (0.0.1-52) unstable; urgency=low
+
+  * Fixes: NB#170773 - Renderer doesn't show up in MTG atall, if MTG gets closed before the renderer loads for the first time
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Sat, 12 Jun 2010 12:53:51 +0300
+
+qmafw-gst-renderer (0.0.1-51) unstable; urgency=low
+
+  * Fixes: NB#172047 - Resuming a song from paused state updates usageCount and contentAccessed
+  * Fixes: NB#170238 - Volume level of music is set to the same as alarm level (maximum)
+  * Fixes: NB#172330 - Video Rendrer crash on playing a video
+  * Temporarily removing DRM check.
+  * Getting lkm service interface commented temporarily out.
+  * Adapted changes in drmclient.h so that gst-renderer compiles: 
+    drm_check_destination stub updated.
+  * Adapted changes in drmclient.h so that gst-renderer compiles. Actual fix 
+    will come later...
+  * Fix for bug "Volume level of music is set to the same as alarm level 
+    (maximum)".
+  * Removing unnecessary debian configuration.
+  * mafw-gst-renderer now informs of visual content when going to playing state.
+  * Mafwgstrenderer debian package building fix for servicehandler lib changes.
+  * Fix to get mafw-gstrenderer to compile againts lkm 1.7
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 11 Jun 2010 12:45:20 +0300
+
+qmafw-gst-renderer (0.0.1-50) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2024
+  * Added a missing wrt lib for linking.
+  * Video resource is released when it is not needed.
+  * Undoing resource usage optimization when paused.
+  * mafw-gst-renderer libqttracker/dbus usage optimization.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 02 Jun 2010 22:41:04 +0300
+
+qmafw-gst-renderer (0.0.1-49) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2243
+  * Implemented: SWP#MMAFW-2288
+  * Fixes: NB#169418 - Playback resumption after 'pause at' set starts the playback from beginning
+  * Optimize resource usage when paused.
+  * Gst-renderer config file has a separate uuid for the in-process renderer. 
+    When loaded in-process, the plugin creates the renderer with that uuid.
+  * New CI-test testInProcessPlayUri.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 31 May 2010 19:41:45 +0300
+
+qmafw-gst-renderer (0.0.1-48) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-1925
+  * Fixes: NB#170621 - qmafw crash while playing a video which blocks videoandTV testing
+  * When the reconnect to pulse audio was done, earlier the old connection was 
+    unref'd synchronously. This caused problems in libdbus-qeventloop so now the
+    unref (and the reconnect) is done asynchronously in a separate event.
+  * Merge from fremantle:  Bug 149945 -  mafw-gst-renderer leaks some GStreamer 
+    messages
+  * Merge from fremantle:     Bug 137609 -  UPnP: playback pauses often when 
+    seek the attached content.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 27 May 2010 22:55:54 +0300
+
+qmafw-gst-renderer (0.0.1-47) unstable; urgency=low
+
+  * Fixes: NB#169742 - Seekbar Maximum Value: Actual Length of the video clip is not displayed in Player view
+  * Merge from fremantle:   Bug 141508 -  Specific video file (mjpeg) makes 
+    Mediaplayer unusable
+  * Use wildcard for the target name in the suppression file.
+  * Merge from fremantle:  Bug 143429 -  [PR1.2 proposal] memory fragemntation 
+    & unneeded copies
+  * Merge from fremantle: Bug 134495 - [PR1.1 proposal] State changed signal 
+    does not come sometimes when stream is played
+  * Corrected Ut_MafwGstRendererWorker::basicPlaybackTestCase() to expect 
+    test.wav duration 3 instead of 2 because of new changed duration rounding.
+  * Fixed one memory leak in a unittest and added some suppressions for glib 
+    related leaks.
+  * Merge from fremantle: Bug 143972 - [PR1.2 proposal] bundle g_object_set 
+    calls
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 24 May 2010 20:42:03 +0300
+
+qmafw-gst-renderer (0.0.1-46) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2237
+  * Added the destructor stub to the QmDisplayState stub (the real destructor 
+    assumed that the constructor created a private class instance).
+  * More robustness for using pulseaudio dbus volume API.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 20 May 2010 13:04:53 +0300
+
+qmafw-gst-renderer (0.0.1-45) unstable; urgency=low
+
+  * Fixes: NB#167753 - Playback state does not change and focus does not move to next clip in this scenario
+  * Pending volume calls cancelled at destructor.
+  * So added internal stop when the license check fails.
+  * Fixed memory leak in ut_MafwGstRenderer.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 17 May 2010 13:50:15 +0300
+
+qmafw-gst-renderer (0.0.1-44) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2243
+  * Implemented: SWP#MMAFW-2189
+  * Fixes: NB#166855 - Tv and Video does not release Xv resources correctly
+  * Optimize resource usage when paused.
+  * MafwRenderer now has playbackCompleted signal.
+  * libtimed-dev added as a build dependency.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 12 May 2010 09:49:05 +0300
+
+qmafw-gst-renderer (0.0.1-43) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2053
+  * Implemented: SWP#MMAFW-2138
+  * Fixes: NB#167042 - MAFW video seeking is very slow
+  * debian/changelog files copied from tag to trunk.
+  * Fixes to renderer(s) when using pauseAt with too large value. Also required 
+    changes to unittests. Plus proxyplaylist test fix.
+  * Prepared for the upcoming omapxvsink (patch from Rene Stadler)
+  * Updated handle screen blanking in video playback appropriately, when TV-OUT 
+    cable is connected.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Sat, 08 May 2010 11:35:09 +0300
+
+qmafw-gst-renderer (0.0.1-42) unstable; urgency=low
+
+  * Version increased.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 07 May 2010 12:57:26 +0300
+
+qmafw-gst-renderer (0.0.1-41) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2156
+  * Fixes: NB#166473 - Volume resets to zero from the second instance of MTG launch, after resetting it for the first time
+  * Modified valgrind.xls for new valgring version.
+  * Volume resets to zero from the second instance of MTG launch, after 
+    resetting it for the first time.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 03 May 2010 22:07:19 +0300
+
+qmafw-gst-renderer (0.0.1-40) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2156
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 29 Apr 2010 13:34:15 +0300
+
+qmafw-gst-renderer (0.0.1-39) unstable; urgency=low
+
+  * Fixes: NB#165339 - Renderer crash on playing mp3s in music suite
+  * Added a NULL pointer check to gotoindex implementation of playlist handler.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 28 Apr 2010 19:48:12 +0300
+
+qmafw-gst-renderer (0.0.1-38) unstable; urgency=low
+
+  * Audio routing to TV-out was not taken into account.
+  * Tv-out CF property should be "tvout", not "tv-out".
+  * A potential bug fix included: mafw_gst_renderer_worker_exit() is called in 
+    the destructor before anything else.
+  * Added a check against NULL ptr for blanking__control_handler callback in 
+    the worker code.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 27 Apr 2010 20:09:41 +0300
+
+qmafw-gst-renderer (0.0.1-37) unstable; urgency=low
+
+  * Missing library dependencies temporarily added with debian/shlibs.local 
+    file.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 26 Apr 2010 18:35:27 +0300
+
+qmafw-gst-renderer (0.0.1-36) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-918
+  * DRM content playback restrictions.
+  * Added missing contextsubscriber-1.0 into pro -file.
+  * Added libcontextsubscriber-dev into mafw-gst-renderer debian/control.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 22 Apr 2010 19:32:42 +0300
+
+qmafw-gst-renderer (0.0.1-35) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2138
+  * Handle screen blanking in video playback appropriately, when TV-OUT cable 
+    is connected. ContextFW provides com.nokia.policy.video_route property 
+    that is used to check TV-OUT cable status.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Sun, 18 Apr 2010 22:18:37 +0300
+
+qmafw-gst-renderer (0.0.1-34) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-1532
+  * Fixes: NB#163774 - First absolute seek fails after playback start
+  * Fixes: NB#158231 - Last video frame is displayed briefly when playback has stopped and it's started again
+  * Gst-renderer, show last video frame when video at end.
+  * Making unittests to be compiled as single process on build-bot.
+  * Removed deprecated MafwRenderer API parts.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 15 Apr 2010 11:42:07 +0300
+
+qmafw-gst-renderer (0.0.1-33) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2057
+  * Support "force aspect ratio" property in qmafw-gst-renderer.
+  * Removed deprecated MafwRenderer API parts.
+  * Updating run_valgrind.sh script for new valgring version.
+  * Two little coverity findings fixed.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 12 Apr 2010 11:49:28 +0300
+
+qmafw-gst-renderer (0.0.1-32) unstable; urgency=low
+
+  * Fixes: NB#163168 - Qmafw renderer crash on youtube playback
+  * Fixes: NB#162434 - Removing items from a playing MafwPlaylist disturbs playback
+  * MafwGstRenderer no longer makes an LKM check for remote URI's.
+  * MafwProxyPlaylist caches size and current index as much as possible.
+  * dh_shlibdeps commented in debian/rules.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 06 Apr 2010 13:29:47 +0300
+
+qmafw-gst-renderer (0.0.1-31) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-728
+  * DRM fulfills the OVI service authentication (LKM) requirements.
+  * Moved LKM/CP stuff to common dir.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 01 Apr 2010 09:18:29 +0300
+
+qmafw-gst-renderer (0.0.1-30) unstable; urgency=low
+
+  * Implemented: SW#MMAFW-2129
+  * Implemented MafwGstRenderer property playback-speed.
+  * GstRenderer does not show the first frame when starting from certain point 
+    in video media.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 24 Mar 2010 07:47:26 +0200
+
+qmafw-gst-renderer (0.0.1-29) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2114
+  * Implemented: SWP#MMAFW-2137
+  * Video pause frame must not be scaled in MAFW.
+  * MafwRenderer pauseAt addition plus bunch of changes.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 22 Mar 2010 07:04:25 +0200
+
+qmafw-gst-renderer (0.0.1-28) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2137
+  * RHL: Video pause frame must not be scaled in MAFW
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 18 Mar 2010 15:24:05 +0200
+
+qmafw-gst-renderer (0.0.1-27) unstable; urgency=low
+
+  * Fixes: NB#160986 - qmafw-gst-renderer Disappears on attempting to play.
+  * Added the build dependency needed by libplayready0
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 17 Mar 2010 13:57:44 +0200
+
+qmafw-gst-renderer (0.0.1-26) unstable; urgency=low
+
+  * Fixes: NB#159904 - libqmafw-gst-renderer depends on libosso1
+  * Gst renderer use QmSystem instead of libosso in screen blanking prevention.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 17 Mar 2010 06:58:27 +0200
+
+qmafw-gst-renderer (0.0.1-25) unstable; urgency=low
+
+  * Fixes: NB#158438 - Playback of the next clip does not happen after the DRM licence fetch error dialog is displayed.
+  * GstRenderer can be issued pause command quickly after play command has been 
+    issued.
+  * Added clearing of the worker->is_error after drm check failure. As the 
+    worker was exited, the is_error state wasn't handled in anyway later on.
+  * Removed unnecessary libosso from gst renderer's .pro file.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 15 Mar 2010 10:13:50 +0200
+
+qmafw-gst-renderer (0.0.1-24) unstable; urgency=low
+
+  * Changed the initialisation test so that the default policy assignment 
+    always fails.
+  * Even if it fails always, it doesn't affect the rest of the tests in anyway. 
+    Just gives us more complete unittest.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 08 Mar 2010 15:42:57 +0200
+
+qmafw-gst-renderer (0.0.1-23) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2053
+  * Implemented: SWP#MMAFW-871
+  * Fixes: NB#156704 - Youtube playback_Play/Pause toggle gets reset on a seek operation
+  * Policy mgmt in qmafw-gst-renderer.
+  * Removed renderer error handling from state-machine. Now gst-renderer goes 
+    into STOPPED state if there is an error that requires that. Updated 
+    MafwRendererStateMachine unittest.
+  * Fixed coverity findings.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 04 Mar 2010 15:16:11 +0200
+
+qmafw-gst-renderer (0.0.1-22) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-1964
+  * Fixes: NB#158196 - Pausing the video right after playback starts will put renderer to invalid state
+  * If pause comes during seeking, now it is performed after the seek is 
+    completed.
+  * MafwBasicRenderer has readonly property for policy override.
+  * New test.suppression files for valgrind.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 01 Mar 2010 18:26:17 +0200
+
+qmafw-gst-renderer (0.0.1-21) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-2100
+  * GST renderer publishing media duration to context framework.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 22 Feb 2010 20:39:08 +0200
+
+qmafw-gst-renderer (0.0.1-20) unstable; urgency=low
+
+  * Unittests pass rate to 100% for mafw-gst-renderer.
+  * CI test and unittest for getCurrentMediaInfo.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 18 Feb 2010 21:43:24 +0200
+
+qmafw-gst-renderer (0.0.1-19) unstable; urgency=low
+
+  * Implemented: SWP#MMAFW-1827
+  * Implemented: SWP#MMAFW-1898
+  * Fixes: NB#155284 - Tapping on the Player View - View Menu - Play Album stops the playback of the current playing song.
+  * Fixes: NB#155820 - Renderer goes into Stopped state after automatic next instead of Transitioning state.
+  * Only necessary headers are exported.
+  * MafwInMemoryPlaylist updates the current index based on the changes in the 
+    playlist.
+  * MafwBasicRenderer also acts better to changes in the playlist contents.
+  * Removed the "fixes" statements from the changelog, because of current 
+    problems in integration systems.
+  * Renderer goes into Stopped state after automatic next instead of 
+    Transitioning state.
+  * Implemented MafwRenderer::getCurrentMediaInfo().
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 09 Feb 2010 21:18:53 +0200
+
+qmafw-gst-renderer (0.0.1-18) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Version increased.
+
+ -- Toni Mäki <ext-toni.2.maki@nokia.com>  Mon, 08 Feb 2010 09:39:31 +0200
+
+qmafw-gst-renderer (0.0.1-17) unstable; urgency=low
+
+  * Bug 155343 removed - Last entry of a playlist plays twice when it comes to focus by 'Next' function
+  * context provider DBus name fixed not to conflict with MAFW plugin DBus name.
+  * Replace/Remove unnecessary includes.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 03 Feb 2010 15:16:30 +0200
+
+qmafw-gst-renderer (0.0.1-16) unstable; urgency=low
+
+  * Version increased.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 02 Feb 2010 10:22:49 +0200
+
+qmafw-gst-renderer (0.0.1-15) unstable; urgency=low
+
+  * Removing added renederer from registry at GstRenderer plugin destructor.
+  * implemented provider for context framework core property Media.NowPlaying
+  * provider for old context framework properties removed
+  * Versions increased.
+  * Maintainer and Standards-Version updated.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 02 Feb 2010 10:08:24 +0200
+
+qmafw-gst-renderer (0.0.1-14) unstable; urgency=low
+
+  * Version increased.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Wed, 27 Jan 2010 15:40:40 +0200
+
+qmafw-gst-renderer (0.0.1-13) unstable; urgency=low
+
+  * Version increased.
+  * Rebuild.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 26 Jan 2010 12:39:48 +0200
+
+qmafw-gst-renderer (0.0.1-12) unstable; urgency=low
+
+  * MafwRenderer can be given a parent.
+  * MafwRenderer API Harmonization step1. Both scenarios supported with or 
+    without callback slots.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 25 Jan 2010 09:22:23 +0200
+
+qmafw-gst-renderer (0.0.1-11) unstable; urgency=low
+
+  * Mafw-Gst-renderer returns 0 for getPosition() when gstreamer isn't playing 
+    or paused.
+  * Renderer property API tests for gst-renderer.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Thu, 21 Jan 2010 15:18:07 +0200
+
+qmafw-gst-renderer (0.0.1-10) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Version increased.
+
+ -- Toni Mäki <ext-toni.2.maki@nokia.com>  Tue, 19 Jan 2010 08:29:28 +0200
+
+qmafw-gst-renderer (0.0.1-9) unstable; urgency=low
+
+  * Version increased.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Mon, 18 Jan 2010 13:42:48 +0200
+
+qmafw-gst-renderer (0.0.1-8) unstable; urgency=low
+
+  * Mostly editorial fixes based on code review.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Fri, 15 Jan 2010 13:24:47 +0200
+
+qmafw-gst-renderer (0.0.1-7) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Version increased after release.
+
+ -- Toni Mäki <ext-toni.2.maki@nokia.com>  Fri, 15 Jan 2010 08:57:03 +0200
+
+qmafw-gst-renderer (0.0.1-6) unstable; urgency=low
+
+  * Fixes: NB#151525 - qmafw fails to build with cs2009q1 toolchain
+  * Play URI implemented in renderer state-machine.
+  * Increased the version numbers for unstable repo delivery.
+  * Next & previous will wrap in first and last item respectively.
+  * qmafw gst renderer added libqttracker-dev to build-depends.
+  * qmafw gst renderer include path change did not help undo.
+  * good GStreamer error mapping.
+  * qmafw gst renderer's QtTracker includepath.
+  * gst renderer usageCounter and contentAccessed update.
+  * Error signal from renderer now goes all the way through to MTG
+  * Various changes to Renderer CI and unittests because of new 
+    qmafw-gst-renderer and changed playlist API.
+  * setting global_drm_uri to NULL in init().
+  * context framework fixes.
+  * MafwRenderer can now signal that is doesn't have a playlist to play, via 
+    playlistChanged signal.
+  * Added seek functionality to MafwBasicRenderer, with additional fixes to URL 
+    handling. Was doubly encoded sometimes.
+  * Changes after the updated toolchain.
+  * Also some changes after the playlist sorting API.
+  * better drm testing.
+  * added gettersTestCase and improved coverage.
+  * added resumeDelayedTestCase.
+  * merged mafw-gst-renderer from branch to trunk.
+  * merged drm stuff from fmafw trunk gst-renderer.
+
+ -- Mika Tapojärvi <ext-mika.tapojarvi@nokia.com>  Tue, 12 Jan 2010 09:08:17 +0200
+
+qmafw-gst-renderer (0.0.1-5) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Version increased.
+
+ -- Toni Mäki <ext-toni.2.maki@nokia.com>  Fri, 08 Jan 2010 11:14:06 +0200
+
+qmafw-gst-renderer (0.0.1-4) unstable; urgency=low
+
+  * Version increased.
+
+ -- Toni Mäki <ext-toni.2.maki@nokia.com>  Thu, 07 Jan 2010 11:28:58 +0200
+
+qmafw-gst-renderer (0.0.1-3) unstable; urgency=low
+
+  * Version increased.
+
+ -- Toni Mäki <ext-toni.2.maki@nokia.com>  Wed, 23 Dec 2009 11:53:04 +0200
+
+qmafw-gst-renderer (0.0.1-2) unstable; urgency=low
+
+  * compiled with new toolchain
+  * Non-maintainer upload.
+  * Version increased.
+
+ -- Toni Mäki <ext-toni.2.maki@nokia.com>  Mon, 21 Dec 2009 15:15:34 +0200
+
+qmafw-gst-renderer (0.0.1-1) unstable; urgency=low
+
+  * Initial release
+
+ -- Seppo Yliklaavu <seppo.yliklaavu@nokia.com>  Tue, 27 Oct 2009 11:01:57 +0200
+
diff --git a/qmafw-gst-subtitles-renderer/debian/compat b/qmafw-gst-subtitles-renderer/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/qmafw-gst-subtitles-renderer/debian/control b/qmafw-gst-subtitles-renderer/debian/control
new file mode 100644 (file)
index 0000000..61b45c2
--- /dev/null
@@ -0,0 +1,30 @@
+Source: qmafw-gst-subtitles-renderer
+Section: debug
+Priority: extra
+Maintainer: Roman Moravcik <roman.moravcik@gmail.com>
+XSBC-Original-Maintainer: Mika Tapojarvi <ext-mika.tapojarvi@nokia.com>
+Build-Depends: debhelper (>= 4), libqmafw0-dev, libglib2.0-dev,
+ libgstreamer0.10-dev (>= 0.10.32.2), libgq-gconf-dev,
+ libgstreamer-plugins-base0.10-dev (>= 0.10.28.3),
+ libqmsystem2-dev,libcontextprovider-dev,
+ libqtsparql-dev, libcontextsubscriber-dev, 
+ libdbus-qeventloop-dev, libtotem-plparser-dev, usb-moded-dev,
+ pkg-config
+Standards-Version: 3.8.0
+Homepage: http://mafwsubrenderer.garage.maemo.org/
+Vcs-Browser: https://garage.maemo.org/plugins/ggit/browse.php/?p=mafwsubrenderer
+Vcs-Git: https://vcs.maemo.org/git/mafwsubrenderer
+
+Package: libqmafw-gst-subtitles-renderer
+Architecture: any
+Depends: ${shlibs:Depends}, libqtsparql0, libqtsparql-tracker, libdbus-qeventloop1, gstreamer0.10-plugins-bad (>= 0.10.21), gstreamer0.10-plugins-base-subtitles (>= 0.10.34-0maemo1+0m6)
+Replaces: qmafw-gst-renderer
+Description: QMAFW GStreamer renderer with subtitles support
+ GStreamer based renderer plugin for QMAFW.
+
+Package: libqmafw-gst-subtitles-renderer-dbg
+Architecture: any
+Depends: libqmafw-gst-subtitles-renderer (= ${binary:Version})
+Priority: extra
+Description: Debug symbols for QMAFW GStreamer renderer with subtitles support
+ Debug symbols for QMAFW GStreamer renderer, makes debugging fun.
diff --git a/qmafw-gst-subtitles-renderer/debian/copyright b/qmafw-gst-subtitles-renderer/debian/copyright
new file mode 100644 (file)
index 0000000..269555d
--- /dev/null
@@ -0,0 +1,3 @@
+Copyright (C) 2009 Nokia Corporation. All rights reserved.
+
+Contact: Visa Smolander <visa.smolander@nokia.com>
diff --git a/qmafw-gst-subtitles-renderer/debian/dirs b/qmafw-gst-subtitles-renderer/debian/dirs
new file mode 100644 (file)
index 0000000..6845771
--- /dev/null
@@ -0,0 +1 @@
+usr/lib
diff --git a/qmafw-gst-subtitles-renderer/debian/libqmafw-gst-subtitles-renderer.install b/qmafw-gst-subtitles-renderer/debian/libqmafw-gst-subtitles-renderer.install
new file mode 100644 (file)
index 0000000..6b70264
--- /dev/null
@@ -0,0 +1,4 @@
+usr/lib/qmafw-plugin/*
+usr/share/dbus-1/services/*
+usr/share/contextkit/providers/*
+usr/share/qmafw/*
diff --git a/qmafw-gst-subtitles-renderer/debian/libqmafw-gst-subtitles-renderer.postinst b/qmafw-gst-subtitles-renderer/debian/libqmafw-gst-subtitles-renderer.postinst
new file mode 100644 (file)
index 0000000..56b8eb4
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -e
+
+chmod 444 /usr/share/qmafw/mafw-gst-renderer-plugin.conf
diff --git a/qmafw-gst-subtitles-renderer/debian/rules b/qmafw-gst-subtitles-renderer/debian/rules
new file mode 100755 (executable)
index 0000000..b681d05
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+APPNAME = qmafw-gst-subtitles-renderer
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       MODE=debug
+else
+       MODE=release
+endif
+
+configure: configure-stamp
+configure-stamp:
+       dh_testdir
+       # Add here commands to configure the package.
+       qmake PREFIX=/usr MODE=$(MODE) $(APPNAME).pro && $(MAKE)
+
+       touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+       dh_testdir
+
+       # Add here commands to compile the package.
+       $(MAKE)
+       #docbook-to-man debian/qmafw-gst-renderer.sgml > qmafw-gst-renderer.1
+
+       touch $@
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp configure-stamp
+
+       # Add here commands to clean up after the build process.
+       -rm -f debian/build-stamp
+       [ ! -f Makefile ] || $(MAKE) distclean
+
+       dh_clean 
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k 
+       dh_installdirs
+
+       # Add here commands to install the package into debian/app_name
+       $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/$(APPNAME) install
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installchangelogs 
+       dh_installdocs
+       dh_installexamples
+       dh_install -a --sourcedir=debian/$(APPNAME)
+#      dh_installmenu
+#      dh_installdebconf       
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+#      dh_python
+#      dh_installinit
+#      dh_installcron
+#      dh_installinfo
+       dh_installman
+       dh_link
+       dh_strip --dbg-package=libqmafw-gst-subtitles-renderer-dbg
+       dh_compress
+       dh_fixperms
+#      dh_perl
+       dh_makeshlibs
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwBlankingPreventer.h b/qmafw-gst-subtitles-renderer/inc/MafwBlankingPreventer.h
new file mode 100644 (file)
index 0000000..14bf085
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFW_BLANKING_PREVENTER_H
+#define MAFW_BLANKING_PREVENTER_H
+
+#include <QObject>
+#include <QTimer>
+
+namespace MeeGo
+{
+    class QmDisplayState;
+};
+
+/**
+ * Helper class for preventing screen blanking.
+ */
+class MafwBlankingPreventer : public QObject
+{
+    Q_OBJECT
+
+public:
+    MafwBlankingPreventer(QObject* parent);
+
+    /**
+      * Disable screen blanking.
+      */
+    void blankingProhibit();
+
+    /**
+      * Enable screen blanking.
+      */
+    void blankingAllow();
+
+private Q_SLOTS:
+    void refresh();
+
+private:
+    QTimer m_refreshTimer;
+    MeeGo::QmDisplayState *m_display;
+};
+
+#endif // MAFW_BLANKING_PREVENTER_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstRenderer.h b/qmafw-gst-subtitles-renderer/inc/MafwGstRenderer.h
new file mode 100644 (file)
index 0000000..9e3fcb0
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFW_GSTRENDERER_INTERFACE_H
+#define MAFW_GSTRENDERER_INTERFACE_H
+
+#include "mafw-gst-renderer-worker.h"
+#include "MafwGstRendererHaltState.h"
+
+#include <MafwBasicRenderer.h>
+#include <MafwError.h>
+#include <MafwMediaInfo.h>
+
+#include <QTimer>
+#include <glib.h>
+
+class MafwBlankingPreventer;
+class MafwGstRendererVolume;
+class MafwGstRendererDolby;
+class MafwGstRendererNetworkMonitor;
+class ContextProperty;
+class QDBusMessage;
+class MafwGstRendererPlaylistFileUtility;
+class MafwMmcMonitor;
+class QSettings;
+class MafwGstScreenshot;
+class MafwGstRendererHaltState;
+
+class QSparqlConnection;
+class QSparqlResult;
+
+/**
+ * Implements MAFW GStreamer renderer.
+ * @credential TrackerReadAccess  Tracker read access
+ * @credential TrackerWriteAccess  Tracker write access
+ *
+ */
+class MafwGstRenderer : public MafwBasicRenderer
+{
+    Q_OBJECT
+
+private:
+    /**
+    * Callback function that gets called when the GStreamer worker pipeline has
+    * gone to playing state.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    */
+    static void playCallback(MafwGstRendererWorker *worker, gpointer owner);
+
+    /**
+    * Callback function that gets called when the GStreamer worker pipeline has
+    * gone to paused state.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    */
+    static void pauseCallback(MafwGstRendererWorker *worker, gpointer owner);
+
+    /**
+    * Callback function that gets called when the GStreamer worker pipeline has
+    * reached EOS state.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    */
+    static void eosCallback(MafwGstRendererWorker *worker, gpointer owner);
+
+    /**
+    * Callback for informing when resources are no longer used in PAUSED state.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    */
+    static void readyStateCallback(MafwGstRendererWorker *worker, gpointer owner);
+
+    /**
+    * Callback function that gets called when the GStreamer worker signals an
+    * error.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    * @param error Pointer to signalled error
+    */
+    static void errorCallback(MafwGstRendererWorker *worker,
+                              gpointer owner,
+                              const GError *error);
+
+    /**
+    * Callback function that gets called when the GStreamer worker signals
+    * new metadata.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    * @param key Metadata key indicating what metadata is signalled
+    * @param type Type of signalled metadata
+    * @param value Pointer to actual metadata value
+    */
+    static void metadataCallback(MafwGstRendererWorker *worker,
+                                 gpointer owner,
+                                 gint key,
+                                 GType type,
+                                 gpointer value);
+
+    /**
+    * Callback function that gets called when the GStreamer worker signals
+    * a (new) property value.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    * @param id ID indicating what property is signalled
+    * @param value Pointer to actual property value
+    */
+    static void propertyCallback(MafwGstRendererWorker *worker,
+                                 gpointer owner,
+                                 gint id,
+                                 GValue *value);
+
+    /**
+    * Callback function that gets called when the GStreamer worker signals
+    * a status when it is buffering a stream.
+    * @param worker Pointer to GStreamer worker instance
+    * @param owner Pointer to GStreamer worker owner (instance of this class)
+    * @param percent Buffering percentage value
+    */
+    static void bufferStatusCallback(MafwGstRendererWorker *worker,
+                                     gpointer owner,
+                                     gdouble percent);
+
+    static void blankingControlCallback(MafwGstRendererWorker *worker,
+                                        gpointer owner,
+                                        gboolean prohibit);
+
+    /**
+     * Callback funtion that gets called when we save new pause frame.
+     * @param worker Pointer to GStreamer worker instance
+     * @param owner Pointer to GStreamer worker owner (instence of this class)
+     * @param buffer Pointer to GstBuffer that contains pause frame data
+     * @param filename Location where the pause frame is saved
+     * @param cancel True if pause frame saving is canceled
+     */
+    static void screenshotCallback(MafwGstRendererWorker *worker,
+                                   gpointer owner,
+                                   GstBuffer *buffer,
+                                   const char *filename,
+                                   gboolean cancel);
+
+   /**
+    * Helper function to convert a GValue to a QVariant
+    * @param v Pointer to GValue to be converted
+    * @return QVariant holding the same value as the GValue held
+    */
+    static QVariant getValue(const GValue *v);
+
+    /**
+     * Mapping between GStreamer worker metadata vs mafw metadata
+     */
+    static const QHash<int, QString>& metadataMap();
+
+    /**
+     * Mapping of obtained audio route to internal type
+     */
+    static const QHash<QString, QList<int> >& audioRouteMap();
+
+    /**
+     * Mapping of obtained video route to internal type
+     */
+    static const QHash<QString, QList<int> >& videoRouteMap();
+
+    /**
+     * Mapping between GStreamer worker errors vs mafw errors
+     */
+    static const QHash<int, MafwError::Code>& errorMap();
+
+public:
+
+    MafwGstRenderer(const QString& uuid,
+                    const QString& pluginName,
+                    const QString& name,
+                    QObject* parent = 0);
+    /**
+     * Desctructor
+     */
+    ~MafwGstRenderer();
+
+    /**
+     * Initializes the renderer.
+     * @param settings Settings to use for configuration
+     * @return True on success, false otherwise
+     */
+    bool initialize(QSettings *settings);
+
+public: //MafwBasicRenderer implementation
+
+    void doPlay(const MafwContent& content);
+    void doPlay(const MafwMediaInfo& mediaInfo);
+
+    void doStop();
+
+    void doPause();
+
+    void doResume();
+
+    void doSeek(int position, MafwRenderer::SeekMode);
+
+    bool doNextHint(const MafwContent& next);
+    bool doNextHint(const MafwMediaInfo& nextMediaInfo);
+
+public: // MafwRenderer implementation
+    bool getPosition(QObject* resultsReceiver, const char* resultsMember);
+
+    bool setMafwProperty(const QString& name, const QVariant& value);
+    bool mafwProperty(QString& name, QObject* receiver, const char* member);
+    bool getCurrentMediaInfo(QObject* receiver, const char* member, const QString& metadataKey=0);
+
+private: //functionality
+    void playURI(const QString& uri);
+    void sendMediaInfo(const MafwMediaInfo& content, QObject* receiver, const char* member);
+    bool connectNameOwnerChanged();
+    void setConfiguration(QSettings *settings);
+    QVariant readSettingsValue(QSettings *settings, const QString &valueName,
+                               const QVariant &defaultValue) const;
+    /*Helper function for metadataCallback(). Appends related metadata to the result list for emitting metadataChanged().*/
+    void appendRelatedMetadata(const QString key, QList<QVariant>* results);
+    void stampIt(const QString& node, int usageCount, int mediaDuration);
+    /**
+     * Helper function which sets the error code to be RendererError_UnsupportedResolution if
+     * resolution is above boundaries 720 x 1280, otherwise error code is to
+     * RendererError_UnsupportedResolution.
+     * @param error reference to error which code is set.
+     */
+    void handleResolutionError(MafwError& error);
+    /** Helper function for creating a MafwError from GError */
+    MafwError constructMafwError(const GError* error);
+
+private Q_SLOTS:
+
+   /**
+    * Slot to call when the current playback position queried.
+    * @param resultsReceiver Pointer to object where to deliver result
+    * @param resultsMember Pointer to member where to deliver result
+    */
+    void slotGetPosition(QObject* resultsReceiver,
+                         const char* resultsMember);
+
+   /**
+    * Slot to call when a property value is queried.
+    * @param name Property name to be queried
+    * @param receiver Pointer to object where to deliver result
+    * @param member Pointer to member where to deliver result
+    */
+    void slotMafwProperty(const QString& name, QObject* receiver, const char* member);
+
+    /**
+     * Store usageCounter and contentAccessed properties of currently playing media to Tracker.
+     */
+    void slotStamp();
+
+    /**
+     * Slot to call when stampit has finished.
+     */
+    void slotStampItDone();
+
+    /**
+     * usageCounter query ready in play uri case
+     */
+    void slotStampQueryReady();
+
+    /**
+     * Commands the next URI to be played.
+     */
+    void playNext();
+
+    /**
+     * Tries to play the next URI from the given playlist URI. If no next
+     * URI commands playNext()
+     */
+    void playNextURIFromPlaylist();
+
+    /**
+     * Slot to call asynchronously to restart playback
+     * (e.g. when internet radio disconnect due to network issues)
+     */
+    void restartPlay();
+
+    /**
+     * Query metadata from currently played clip or stream.
+     */
+    void slotGetCurrentMediaInfo(QObject* receiver, const char* member, const QString& metadataKey);
+
+    /**
+     * Called when volume has been changed.
+     */
+    void handleVolumeChange(uint level);
+
+    /**
+     * Slot called when audio/video route context framework property changes.
+     */
+    void slotRouteChanged();
+
+    /**
+     * Called when a property has been changed.
+     */
+    void handlePropertyChanged(const QString& name, const QVariant& value);
+
+    /**
+     * Called when Dolby Headphones Mobile music property has been changed.
+     */
+    void handleDHMMusicPropertyChanged();
+
+    /**
+     * Called when Dolby Headphones Mobile video property has been changed.
+     */
+    void handleDHMVideoPropertyChanged();
+
+    /**
+      * Handle NameOwnerChanged signal of policy-context-daemon.
+      */
+    void handleContextProviderRemoval( const QDBusMessage& message );
+
+    /**
+     * Starts playing playlist file. This is called when parsing has been done.
+     */
+    void startPlayingPlaylistFile();
+
+    /**
+     * Handles the errors occured while parsing playlist file.
+     * @param succeeded true if no errors occured.
+     */
+    void handlePlaylistFileParsingErrors(bool succeeded);
+
+    /**
+     * Stops streaming if necessary
+     */
+    void stopStreaming();
+
+    /**
+     * Halts streaming if necessary, stores the needed info for future reference (@see MafwGstRenderer::continueStreaming())
+     */
+    void haltStreaming();
+
+    /**
+     * Continues streaming
+     */
+    void continueStreaming();
+
+    /**
+     * Any timers e.g. playlist file util & stamping timers will be stopped here
+     */
+    void stopTimers();
+
+    /**
+     * Called when new pause frame is ready or
+     * when there was error with pause frame encoding.
+     */
+    void handleScreenshot(char *location, GError *error);
+
+    /**
+     * Called when pause frame is cancelled.
+     */
+    void cancelScreenshot();
+
+    /**
+      * MMC going to be unmounted.
+      */
+    void mmcPreUnmount();
+
+Q_SIGNALS:
+    void signalGetPosition(QObject* resultsReceiver,
+                           const char* resultsMember);
+
+    void signalMafwProperty(const QString& name, QObject* receiver,
+                            const char* member);
+
+    void signalGetCurrentMediaInfo(QObject*, const char*, const QString);
+
+private: //data
+
+    /**
+     * Has this instance been initialized?
+     */
+    bool m_initialized;
+
+    /**
+     * Helps determining whether to request a new item to play
+     */
+    MafwRenderer::State m_currentState;
+
+    /**
+     * The next Content to play, if any.
+     */
+    MafwMediaInfo m_nextContent;
+
+    /**
+     * The currently to be played Content
+     */
+    MafwMediaInfo m_currentContent;
+
+    QMap<QString, QList<QVariant> > m_currentMetaData;
+
+    /**
+     * What item is the renderer currently playing?
+     */
+    MafwRendererPlayingUri m_playingItem;
+
+    /**
+     * GStreamer renderer worker
+     */
+    MafwGstRendererWorker *m_worker;
+
+    /**
+      * Timer for stamping media usageCount and contentAccessed
+      */
+    QTimer m_playedStampTimer;
+
+    MafwBlankingPreventer* m_blankingPreventer;
+
+    MafwGstScreenshot* m_screenshot;
+
+    /**
+     * Help to monitor network access
+     */
+    MafwGstRendererNetworkMonitor *m_networkMonitor;
+
+    /**
+     * "Halt" state to store state when changing network access point
+     */
+    MafwGstRendererHaltState m_haltState;
+
+    /**
+     * Object to handle volume
+     */
+    MafwGstRendererVolume* m_volume;
+
+    /**
+     * Object to handle Dolby Headphones Mobile plugin
+     */
+    MafwGstRendererDolby* m_dolby;
+
+    /**
+     * Context framework property for video route
+     */
+    ContextProperty *m_videoRoute;
+
+    /**
+     * Context framework property for audio route
+     */
+    ContextProperty *m_audioRoute;
+
+    /**
+      * Is contentAccessed and usageCount of current playing item already updated. (Update process has started)
+      */
+    bool m_playedStamped;
+    int m_playedStampTryCounter;
+
+    /**
+      * Used to stamp usageCount and updated duration
+      */
+    QSparqlConnection *m_sparqlConnection;
+    /**
+     * If playing just an URI this result is used to get the tracker urn for it
+     */
+    QSparqlResult *m_urnQueryResult;
+
+    /**
+     * Result handle for stampit actions
+     */
+    QSparqlResult *m_stampItResult;
+
+    /**
+     * Pointer to playlist file parsing utility
+     */
+    MafwGstRendererPlaylistFileUtility* m_playlistFileUtil;
+
+    /**
+     * Timer to try to play next item from given playlist URI, totem parser can be slow sometimes.
+     */
+    QTimer m_playlistNextTimer;
+
+    /**
+     * Flag indicating whether we are playing playlist file.
+     */
+    bool m_playingPlaylistFile;
+
+    /**
+     * The error we got when we have possibly tried gstreamer to play playlist file.
+     */
+    GError* m_unsupportedTypeError;
+
+    /**
+     * Flag indicating whether we have already played an item from URI playlist.
+     * I.e. an URI was given which points to a playlist, this flag
+     * tells if rendererPlaying() signal has already been sent for URI.
+     */
+    bool m_playedPlaylistItem;
+
+    MafwMmcMonitor* m_mmcMonitor;
+};
+
+#endif // MAFW_GSTRENDERER_INTERFACE_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstRendererDolby.h b/qmafw-gst-subtitles-renderer/inc/MafwGstRendererDolby.h
new file mode 100644 (file)
index 0000000..6382000
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFWGSTRENDERERDOLBY_H
+#define MAFWGSTRENDERERDOLBY_H
+
+#include <QObject>
+#include <GConfItem>
+
+/**
+ * Provides volume setting, getting and listening functionality using
+ * PulseAudioMainVolume DBus API.
+ */
+class MafwGstRendererDolby : public QObject
+{
+    Q_OBJECT
+public:
+    /**
+     * Constructor
+     */
+    MafwGstRendererDolby( QObject* parent );
+    ~MafwGstRendererDolby();
+    void initialize();
+    bool setMusicDolbyState (uint value);
+    bool setMusicDolbyRoom (int value);
+    bool setMusicDolbyColor (int value);
+    uint getMusicDolbyState ();
+    int getMusicDolbyRoom ();
+    int getMusicDolbyColor ();
+    bool setVideoDolbyState (uint value);
+    bool setVideoDolbyRoom (int value);
+    bool setVideoDolbyColor (int value);
+    uint getVideoDolbyState ();
+    int getVideoDolbyRoom ();
+    int getVideoDolbyColor ();
+
+Q_SIGNALS:
+    /**
+     * Signal telling that music surround is OFF/ON/AUTO.
+     */
+    void mafwDHMMusicPropertyChanged();
+    /**
+     * Signal telling that video surround is OFF/ON/AUTO.
+     */
+    void mafwDHMVideoPropertyChanged();
+
+private Q_SLOTS:
+    void valueMusicChanged();
+    void valueVideoChanged();
+
+private:
+    uint m_currentMusicDolbyState;
+    int m_currentMusicDolbyRoom;
+    int m_currentMusicDolbyColor;
+    uint m_currentVideoDolbyState;
+    int m_currentVideoDolbyRoom;
+    int m_currentVideoDolbyColor;
+
+    GConfItem *m_dolbyConfMusic;
+    GConfItem *m_dolbyConfMusicRoom;
+    GConfItem *m_dolbyConfMusicColor;
+    GConfItem *m_dolbyConfVideo;
+    GConfItem *m_dolbyConfVideoRoom;
+    GConfItem *m_dolbyConfVideoColor;
+};
+
+#endif // MAFWGSTRENDERERDOLBY_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstRendererHaltState.h b/qmafw-gst-subtitles-renderer/inc/MafwGstRendererHaltState.h
new file mode 100644 (file)
index 0000000..d7168d1
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFWGSTRENDERERHALTSTATE_H
+#define MAFWGSTRENDERERHALTSTATE_H
+
+#include <MafwRenderer.h>
+
+#include <QTimer>
+
+class MafwGstRendererHaltState : public QObject
+{
+    Q_OBJECT
+public:
+    static int DECAY_TIME;
+public:
+    MafwGstRendererHaltState();
+    MafwGstRendererHaltState(const QString &uri, MafwRenderer::State state, int position);
+    ~MafwGstRendererHaltState();
+
+    /**
+     * Assigns other halt state to this object, also resets the decay timer.
+     */
+    MafwGstRendererHaltState(const MafwGstRendererHaltState &other);
+
+    /**
+     * Assigns other halt state to this object, also resets the decay timer.
+     */
+    MafwGstRendererHaltState& operator =(const MafwGstRendererHaltState &other);
+
+
+    /**
+     * Set new renderer state for halt state, user pressed pause etc
+     * @param  newState, if newState is MafwRenderer::Paused the decay time is paused also
+     */
+    void setState(MafwRenderer::State newState);
+
+    /**
+     * Is the halt state valid? Not decayed and contains relevenat information
+     */
+    bool isSet() const;
+
+    /**
+     * Clears the halt state from any valid content, also stop the decay timer
+     */
+    void clear();
+
+    QString uri() const;
+    MafwRenderer::State state() const;
+    int position() const;
+
+Q_SIGNALS:
+    /**
+     * This signal is emitted when the MafwGstRendererHaltState::DECAY_TIME has passed
+     * from object creation or when valid parameters were assigned to it.
+     */
+    void decayed();
+
+private:
+    void initializeDecayTimer();
+
+private:
+    QString m_uri;
+    MafwRenderer::State m_state;
+    int m_position;
+    QTimer m_decayTimer;
+};
+
+#endif // MAFWGSTRENDERERHALTSTATE_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstRendererNetworkMonitor.h b/qmafw-gst-subtitles-renderer/inc/MafwGstRendererNetworkMonitor.h
new file mode 100644 (file)
index 0000000..48a345f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFWGSTRENDERERNETWORKMONITOR_H
+#define MAFWGSTRENDERERNETWORKMONITOR_H
+
+#include <QObject>
+#include <QtNetwork/QNetworkConfiguration>
+
+class QNetworkConfigurationManager;
+class MafwGstRendererNetworkMonitor : public QObject
+{
+    Q_OBJECT
+
+public:
+    MafwGstRendererNetworkMonitor();
+    virtual ~MafwGstRendererNetworkMonitor();
+
+Q_SIGNALS:
+    void prepareNetworkChange();
+    void networkChangeFinished();
+
+private Q_SLOTS:
+    void handleConfigurationChange(const QNetworkConfiguration & config);
+
+private:
+    QNetworkConfigurationManager *m_networkManager;
+    QNetworkConfiguration m_currentConfiguration;
+};
+
+#endif // MAFWGSTRENDERERNETWORKMONITOR_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstRendererPlaylistFileUtility.h b/qmafw-gst-subtitles-renderer/inc/MafwGstRendererPlaylistFileUtility.h
new file mode 100644 (file)
index 0000000..3e5bb76
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef MafwGstRendererPlaylistFileUtility_H
+#define MafwGstRendererPlaylistFileUtility_H
+
+#include <QObject>
+#include <QStringList>
+#include <totem-pl-parser/1/plparser/totem-pl-parser.h>
+#include <MafwError.h>
+
+class QUrl;
+
+/**
+ * Utility class for parsing playlist files.
+ */
+class MafwGstRendererPlaylistFileUtility : public QObject
+{
+    Q_OBJECT
+public:
+    /**
+     * Constructor
+     */
+    MafwGstRendererPlaylistFileUtility(QObject* parent);
+
+    /**
+     * Destructor
+     */
+    ~MafwGstRendererPlaylistFileUtility();
+
+    /**
+     * Returns the parsed URI list
+     * @return list of parsed URIs
+     */
+    QStringList getUriList();
+
+    /**
+     * Starts playlist file parsing, parsingReady is signalled when parsing
+     * has been done. Parsed uris can be fetched using getUri() function.
+     * @param uri The absolute uri to the playlist file.
+     */
+    void parsePlaylistFile(const QUrl& uri);
+
+    /**
+     * Removes the first unused uri parsed from playlist and returns it.
+     * @return The first unused playlist uri or empty string if each uris are
+     * used or parsing has been failed.
+     */
+    QString takeFirstUri();
+
+    /**
+     * Saves the pending error that will be fired, if no new URI's are found.
+     * This error saving feature is needed because we don't get the proper
+     * "parsing ended" signals from Totem playlist parser.
+     * @param error The error to be saved.
+     */
+    void setPendingError(MafwError& error);
+
+    /**
+     * Returns the saved error.
+     * @return The saved error.
+     */
+    MafwError takePendingError();
+
+Q_SIGNALS:
+    /** Signal telling that first uri on playlist file is parsed. */
+    void firstItemParsed();
+    /** Signal telling that parsing is ready. */
+    void parsingReady(bool succeeded);
+
+private:
+    static void readyCb(TotemPlParser* parser,
+                        GAsyncResult *async_result,
+                        MafwGstRendererPlaylistFileUtility* self);
+    static void uriParsed(TotemPlParser *parser,
+                          gchar* uri,
+                          gpointer metadata,
+                          MafwGstRendererPlaylistFileUtility* self);
+
+private:
+    /** Modifies the resulting item URI if necessary.
+     * Unfortunately there are various reasons why this is required.
+     */
+    QString manHandleURI(const QString &itemUri) const;
+
+private:
+    /** Unique id (=pointer) of currently used parser. */
+    TotemPlParser* m_parserId;
+    /** The list of parsed uris. */
+    QStringList m_uriList;
+    /** Parsing the first item */
+    bool m_firstItem;
+    /** The pending error */
+    MafwError m_pendingError;
+};
+
+#endif // MafwGstRendererPlaylistFileUtility_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstRendererPlugin.h b/qmafw-gst-subtitles-renderer/inc/MafwGstRendererPlugin.h
new file mode 100644 (file)
index 0000000..05863aa
--- /dev/null
@@ -0,0 +1,58 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFW_GST_RENDERER_PLUGIN_H
+#define MAFW_GST_RENDERER_PLUGIN_H
+
+#include <QObject>
+#include <MafwPlugin.h>
+
+class MafwGstRendererPlugin : public QObject, public MafwPlugin
+{
+    Q_OBJECT
+    Q_INTERFACES(MafwPlugin)
+
+public:
+    void initialize(MafwInternalRegistry* registry);
+    ~MafwGstRendererPlugin();
+
+    QString name() const;
+
+protected:
+    MafwInternalRegistry* m_registry;
+    
+private:
+    QList<QString> m_rendererIds;
+
+    /**
+    * Loads gst-renderers from config file.
+    * Config file contais "renderers" and "in-process-renderers" arrays.
+    * Renderer Array contains gst-renderer's id and it's "friendly" name.
+    * Syntax of the "renderers" array:
+    *    [renderers]
+    *    1\Id=mafw_gst_renderer
+    *    1\FriendlyName=MafwGstRenderer
+    *    2\Id=mafw_gst_internal_video_renderer
+    *    2\FriendlyName=MafwGstVideoRenderer
+    *    size=2
+    * If config file is deleted of empty we create default renderer with "mafw_gst_renderer" uuid.
+    **/
+    void loadRenderers(const QString& rendererArrayKey);
+
+};
+
+#endif
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstRendererVolume.h b/qmafw-gst-subtitles-renderer/inc/MafwGstRendererVolume.h
new file mode 100644 (file)
index 0000000..47d415d
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef MAFWGSTRENDERERVOLUME_H
+#define MAFWGSTRENDERERVOLUME_H
+
+#include <QObject>
+
+class DBusConnection;
+class DBusMessage;
+class DBusPendingCall;
+class DBusMessageIter;
+class DBusPendingCall;
+
+/**
+ * Provides volume setting, getting and listening functionality using
+ * PulseAudioMainVolume DBus API.
+ */
+class MafwGstRendererVolume : public QObject
+{
+    Q_OBJECT
+public:
+    /**
+     * Constructor
+     */
+    MafwGstRendererVolume();
+    ~MafwGstRendererVolume();
+
+    /**
+     * Get the volume level. Initial volume level is always got via volumeChanged signal.
+     * Before that signal returns always 0.
+     * @return The current volume level. Value is between 0 to 99.
+     */
+    uint getVolume();
+
+    /**
+     * Set the volume level to pulse audio.
+     * @note Volume setting happens asynchronously
+     *       and may wait until dbus connection to pulse audio is ready.
+     * @param The volume level to be set. Valid value range is between 0 to 99.
+     * @return true on success.
+     */
+    bool setVolume (uint value);
+
+Q_SIGNALS:
+    /**
+     * Signal telling that volume level has been changed.
+     */
+    void volumeChanged(uint newLevel);
+
+private Q_SLOTS:
+    /** Makes p2p dbus connection to pulse audio. */
+    void connectToPulseAudio();
+
+private:
+    /**
+     * Starts to listen signal from  PulseAudioMainVolume DBus API
+     */
+    void listenVolumeSignals();
+
+    /**
+     * Get the step configuration asynchronously from PulseAudioMainVolume
+     */
+    void getRestoreEntryForMediaRole();
+
+    /**
+     * Catch signals from PulseAudioMainVolume telling that volume step configuration has been changed
+     */
+    static void handleIncomingMessages( DBusConnection* conn,
+                                        DBusMessage* message,
+                                        MafwGstRendererVolume* self);
+
+    /**
+     * Catch reply callback for step configuration request from PulseAudioMainVolume.
+     */
+    static void getEntryReply(DBusPendingCall *pending, MafwGstRendererVolume *self);
+
+    static void volumeReply(DBusPendingCall *pending, MafwGstRendererVolume *self);
+
+    bool readVolumeFromStruct(DBusMessageIter *iterator);
+
+private:
+    /** The current volume step, values are between 0, used maximum volume level */
+    uint m_currentVolume;
+
+    /** The volume step which is pending to be set. */
+    uint m_pendingVolumeValue;
+
+    /** The dbus connection object */
+    DBusConnection* m_dbusConnection;
+
+    QString m_objectPath;
+
+    /** The pending call. */
+    DBusPendingCall* m_pendingCall;
+
+
+};
+
+#endif // MAFWGSTRENDERERVOLUME_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwGstScreenshot.h b/qmafw-gst-subtitles-renderer/inc/MafwGstScreenshot.h
new file mode 100644 (file)
index 0000000..a032c04
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFWGSTSCREENSHOT_H
+#define MAFWGSTSCREENSHOT_H
+
+#include <QObject>
+#include <gst/gst.h>
+
+class MafwGstScreenshot : public QObject
+{
+    Q_OBJECT
+public:
+    MafwGstScreenshot(QObject* parent);
+    ~MafwGstScreenshot();
+
+    bool savePauseFrame(GstBuffer *buffer, const char *filename);
+    void cancelPauseFrame();
+    bool reportBack(GError *error);
+
+private:
+    /* All GStreamer elements are owned by m_pipeline.
+       Elements are destroyed when m_pipeline is destroyed.*/
+    GstElement *m_src;
+    GstElement *m_sink;
+    GstElement *m_pipeline;
+    GstElement *m_filter;
+    GstElement *m_enc;
+    GstElement *m_csp;
+    GstBus *m_bus;
+    GstCaps *m_caps;
+    GstStructure *m_structure;
+
+    gulong m_handler_id;
+
+Q_SIGNALS:
+    void screenshotCancelled();
+    void screenshotTaken(char *location, GError *error);
+};
+
+#endif // MAFWGSTSCREENSHOT_H
diff --git a/qmafw-gst-subtitles-renderer/inc/MafwMmcMonitor.h b/qmafw-gst-subtitles-renderer/inc/MafwMmcMonitor.h
new file mode 100644 (file)
index 0000000..8c65055
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFW_MMC_MONITOR_H
+#define MAFW_MMC_MONITOR_H
+
+#include <gio/gio.h>
+
+#include <QObject>
+
+/**
+ * Helper class for MMC state.
+ */
+class MafwMmcMonitor : public QObject
+{
+    Q_OBJECT
+
+public:
+    static const QString MMC_URI_PREFIX;
+
+    MafwMmcMonitor(QObject* parent);
+    ~MafwMmcMonitor();
+    bool isMounted();
+
+Q_SIGNALS:
+    void preUnmount();
+
+private:
+    static void unmountEvent(GVolumeMonitor* mon,
+                                       GMount* event,
+                                       gpointer userData);
+    static void mountEvent(GVolumeMonitor* mon,
+                                       GMount* event,
+                                       gpointer userData);
+    static bool isMyDocs(GMount* mount);
+
+private Q_SLOTS:
+    void preUnmountEvent(const QString &state);
+
+private:
+    GVolumeMonitor* m_gVolMonitor;
+    bool m_mounted;
+};
+
+#endif // MAFW_MMC_MONITOR_H
diff --git a/qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-seeker.h b/qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-seeker.h
new file mode 100644 (file)
index 0000000..9010111
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFWGSTRENDERERSEEKER_H
+#define MAFWGSTRENDERERSEEKER_H
+
+#include <gst/gstelement.h>
+
+G_BEGIN_DECLS
+
+typedef struct _MafwGstRendererSeeker MafwGstRendererSeeker;
+
+
+MafwGstRendererSeeker* mafw_gst_renderer_seeker_new();
+void mafw_gst_renderer_seeker_set_pipeline(MafwGstRendererSeeker *seeker, GstElement *pipeline);
+gboolean mafw_gst_renderer_seeker_seek_to(MafwGstRendererSeeker *seeker, gint64 seek_pos);
+
+/*
+ * Processes possible seek results. Check if position has changed correctly or enough, if not
+ * executes new seek operation on the pipeline element.
+ * @return The new seek request position or -1 if no new seek request is necessary.
+ */
+gint64 mafw_gst_renderer_seeker_process(MafwGstRendererSeeker *seeker);
+void mafw_gst_renderer_seeker_cancel(MafwGstRendererSeeker *seeker);
+void mafw_gst_renderer_seeker_free(MafwGstRendererSeeker *seeker);
+
+G_END_DECLS
+
+#endif // MAFWGSTRENDERERSEEKER_H
diff --git a/qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-utils.h b/qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-utils.h
new file mode 100644 (file)
index 0000000..41e30eb
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * This file is a part of MAFW
+ *
+ * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.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; 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
+ */
+#ifndef MAFW_GST_RENDERER_UTILS_H
+#define MAFW_GST_RENDERER_UTILS_H
+
+G_BEGIN_DECLS
+#include <glib.h>
+#include <gst/gst.h>
+#include "mafw-gst-renderer-worker.h"
+
+gboolean convert_utf8(const gchar *src, gchar **dst);
+gboolean uri_is_stream(const gchar *uri);
+gint remap_gst_error_code(const GError *error);
+
+char *uri_get_subtitle_uri(const char *uri);
+
+G_END_DECLS
+#endif
diff --git a/qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-worker.h b/qmafw-gst-subtitles-renderer/inc/mafw-gst-renderer-worker.h
new file mode 100644 (file)
index 0000000..592b67f
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * This file is a part of MAFW
+ *
+ * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.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; 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
+ *
+ */
+#ifndef MAFW_GST_RENDERER_WORKER_H
+#define MAFW_GST_RENDERER_WORKER_H
+
+#include <glib.h>
+G_BEGIN_DECLS
+#include <X11/Xdefs.h>
+#include <glib-object.h>
+#include <gst/gst.h>
+
+#include "mafw-gst-renderer-seeker.h"
+
+#define MAFW_GST_RENDERER_WORKER_READY_TIMEOUT 3
+#define MAFW_GST_RENDERER_MAX_TMP_FILES 5
+
+enum {
+    WORKER_ERROR_PLAYBACK,
+    WORKER_ERROR_VIDEO_CODEC_NOT_FOUND,
+    WORKER_ERROR_AUDIO_CODEC_NOT_FOUND,
+    WORKER_ERROR_CODEC_NOT_FOUND,
+    WORKER_ERROR_UNSUPPORTED_TYPE,
+    WORKER_ERROR_UNABLE_TO_PERFORM,
+    WORKER_ERROR_CANNOT_SET_POSITION,
+    WORKER_ERROR_PLAYLIST_PARSING,
+    WORKER_ERROR_DRM_NO_LICENSE,
+    WORKER_ERROR_DRM_NOT_ALLOWED,
+    WORKER_ERROR_DRM_CLOCK_NOT_SET,
+    WORKER_ERROR_DRM_OTHER,
+    WORKER_ERROR_STREAM_DISCONNECTED,
+    WORKER_ERROR_INVALID_URI,
+    WORKER_ERROR_MEDIA_NOT_FOUND,
+    WORKER_ERROR_CORRUPTED_FILE,
+    WORKER_ERROR_TYPE_NOT_AVAILABLE,
+    WORKER_ERROR_UNKOWN,
+    WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE = 1000,
+};
+
+enum {
+    WORKER_METADATA_KEY_TITLE = 1, /* 1st must be non-zero! */
+    WORKER_METADATA_KEY_ARTIST,
+    WORKER_METADATA_KEY_AUDIO_CODEC,
+    WORKER_METADATA_KEY_VIDEO_CODEC,
+    WORKER_METADATA_KEY_BITRATE,
+    WORKER_METADATA_KEY_ENCODING,
+    WORKER_METADATA_KEY_ALBUM,
+    WORKER_METADATA_KEY_GENRE,
+    WORKER_METADATA_KEY_TRACK,
+    WORKER_METADATA_KEY_ORGANIZATION,
+    WORKER_METADATA_KEY_RENDERER_ART_URI,
+    WORKER_METADATA_KEY_RES_X,
+    WORKER_METADATA_KEY_RES_Y,
+    WORKER_METADATA_KEY_VIDEO_FRAMERATE,
+    WORKER_METADATA_KEY_DURATION,
+    WORKER_METADATA_KEY_IS_SEEKABLE,
+    WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI,
+    WORKER_METADATA_KEY_URI
+};
+
+enum {
+    WORKER_PROPERTY_VOLUME,
+    WORKER_PROPERTY_MUTE,
+    WORKER_PROPERTY_AUTOPAINT,
+    WORKER_PROPERTY_COLORKEY,
+    WORKER_PROPERTY_XID,
+    WORKER_PROPERTY_RENDER_RECTANGLE,
+    WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE,
+    WORKER_PROPERTY_PLAYBACK_SPEED,
+    WORKER_PROPERTY_FORCE_ASPECT_RATIO
+};
+
+enum {
+    WORKER_OUTPUT_NULL,
+    WORKER_OUTPUT_BUILTIN_SPEAKERS,
+    WORKER_OUTPUT_FM_RADIO,
+    WORKER_OUTPUT_BLUETOOTH_AUDIO,
+    WORKER_OUTPUT_HEADPHONE_JACK,
+    WORKER_OUTPUT_BUILTIN_DISPLAY,
+    WORKER_OUTPUT_TVOUT
+};
+
+typedef struct _MafwGstRendererWorker MafwGstRendererWorker;
+
+typedef void (*MafwGstRendererWorkerNotifySeekCb)(MafwGstRendererWorker *worker, gpointer owner);
+typedef void (*MafwGstRendererWorkerNotifyPauseCb)(MafwGstRendererWorker *worker, gpointer owner);
+typedef void (*MafwGstRendererWorkerNotifyPlayCb)(MafwGstRendererWorker *worker, gpointer owner);
+typedef void (*MafwGstRendererWorkerNotifyReadyStateCb)(MafwGstRendererWorker *worker, gpointer owner);
+typedef void (*MafwGstRendererWorkerNotifyBufferStatusCb)(MafwGstRendererWorker *worker, gpointer owner, gdouble percent);
+typedef void (*MafwGstRendererWorkerNotifyEOSCb)(MafwGstRendererWorker *worker, gpointer owner);
+typedef void (*MafwGstRendererWorkerNotifyMetadataCb)(MafwGstRendererWorker *worker, gpointer owner, gint key, GType type, gpointer value);
+typedef void (*MafwGstRendererWorkerNotifyErrorCb)(MafwGstRendererWorker *worker, gpointer owner, const GError *error);
+typedef void (*MafwGstRendererWorkerNotifyPropertyCb)(MafwGstRendererWorker *worker, gpointer owner, gint id, GValue *value);
+typedef void (*MafwGstRendererWorkerBlankingControlCb)(MafwGstRendererWorker *worker, gpointer owner, gboolean prohibit);
+typedef void (*MafwGstRendererWorkerScreenshotCb)(MafwGstRendererWorker *worker, gpointer owner, GstBuffer *buffer, const char *filename, gboolean cancel);
+
+typedef enum {
+    SEEKABILITY_UNKNOWN = -1,
+    SEEKABILITY_NO_SEEKABLE,
+    SEEKABILITY_SEEKABLE,
+} SeekabilityType;
+
+typedef enum {
+    DURATION_UNQUERIED = -2,
+    DURATION_INDEFINITE = -1
+    /* other values are actual */
+} Duration;
+
+typedef struct {
+    gint x;
+    gint y;
+    gint width;
+    gint height;
+} render_rectangle;
+
+/* This struct contains all configurable settings
+   update this and the conf file synchronously, plz
+ */
+typedef struct {
+    /* pipeline */
+    gchar *asink;
+    gchar *vsink;
+    gint flags;
+    gint64 buffer_time;
+    gint64 latency_time;
+    gboolean autoload_subtitles;
+    gchar *subtitle_encoding;
+    gchar *subtitle_font;
+
+    /* timers */
+    guint milliseconds_to_pause_frame;
+    guint seconds_to_pause_to_ready;
+
+    /* dhmmixer */
+    gboolean use_dhmmixer;
+    struct {
+        guint state;
+        gint room;
+        gint color;
+    } mobile_surround_music;
+    struct {
+        guint state;
+        gint room;
+        gint color;
+    } mobile_surround_video;
+} configuration;
+
+/*
+ * media:        Information about currently selected media.
+ *   location:           Current media location
+ *   length_nanos:       Length of the media, in nanoseconds
+ *   has_visual_content: the clip contains some visual content (video)
+ *   video_width:        If media contains video, this tells the video width
+ *   video_height:       If media contains video, this tells the video height
+ *   seekable:           Tells whether the media can be seeked
+ *   par_n:              Video pixel aspect ratio numerator
+ *   par_d:              Video pixel aspect ratio denominator
+ * owner:        Owner of the worker; usually a MafwGstRenderer (FIXME USUALLY?)
+ * pipeline:     Playback pipeline
+ * bus:          Message bus
+ * state:        Current playback pipeline state
+ * is_stream:    Is currently playing media a stream
+ * muted:        Is the audio muted
+ * eos:          Has playback reached EOS already
+ * is_error:     Has there been an error situation
+ * buffering:    Indicates the buffering state
+ * prerolling:   Indicates the prerolling state (NULL -> PAUSED)
+ * report_statechanges: Report state change bus messages
+ * current_volume:      Current audio volume [0.0 .. 1.0], see playbin:volume
+ * async_bus_id:        ID handle for GstBus
+ * buffer_probe_id:     ID of the video renderer buffer probe
+ * seek_position:       Indicates the pos where to seek, in seconds
+ * vsink:               Video sink element of the pipeline
+ * asink:               Audio sink element of the pipeline
+ * tsink:               Text sink element of the pipeline
+ * xid:                 XID for video playback
+ * current_frame_on_pause: whether to emit current frame when pausing
+ */
+struct _MafwGstRendererWorker {
+    struct {
+        gchar *location;
+        gint64 length_nanos;
+        gboolean has_visual_content;
+        gint video_width;
+        gint video_height;
+        gdouble fps;
+        SeekabilityType seekable;
+        gint par_n;
+        gint par_d;
+    } media;
+    gpointer owner;
+    GstElement *pipeline;
+
+    // Audio bin for Dolby Headphones Mobile plugin
+    GstElement *audiobin;
+
+    GstBus *bus;
+    /* GStreamer state we are considering right now */
+    GstState state;
+    gboolean is_stream;
+    gboolean muted;
+    /* we are handing eos or we did */
+    gboolean eos;
+    /* if we are handling (or handled) and error */
+    gboolean is_error;
+    /* pipeline is buffering */
+    gboolean buffering;
+    /* pipeline is prerolling */
+    gboolean prerolling;
+    /* stream is live and doesn't need prerolling */
+    gboolean is_live;
+    /* if we have to stay in paused though a do_play was
+     * requested. Usually used when pausing in transitioning */
+    gboolean stay_paused;
+    /* this variable should be FALSE while we are hiding state
+     * changed to the UI. This is that GStreamer can perform
+     * state_changes without us requiring it, for example, then
+     * seeking, buffering and so on and we have to hide those
+     * changes */
+    gboolean report_statechanges;
+    guint async_bus_id;
+    gint seek_position;
+    guint ready_timeout;
+    guint duration_seek_timeout;
+    guint duration_seek_timeout_loop_count;
+    /* TRUE when a transition to GST_STATE_READY has been
+     * requested or we are actually in GST_STATE_READY (requested
+     * by us) */
+    gboolean in_ready;
+    /* Flag indicating whether taking image from pause frame has succeed after pause. */
+    gboolean pause_frame_taken;
+    guint pause_frame_timeout;
+    GstBuffer *pause_frame_buffer;
+    GstElement *vsink;
+    GstElement *asink;
+    GstElement *tsink;
+
+    // Dolby Headphones Mobile mixer
+    GstElement *amixer;
+
+    XID xid;
+    render_rectangle x_overlay_rectangle;
+    gboolean autopaint;
+    gfloat playback_speed;
+    gboolean force_aspect_ratio;
+    gint colorkey;
+    GPtrArray *tag_list;
+    GHashTable *current_metadata;
+    gpointer context_nowplaying;
+
+    gboolean current_frame_on_pause;
+    gboolean taking_screenshot;
+    gchar *tmp_files_pool[MAFW_GST_RENDERER_MAX_TMP_FILES];
+    guint8 tmp_files_pool_index;
+
+    GSList *destinations;
+
+    GstElement *queue;
+
+    configuration *config;
+
+    MafwGstRendererSeeker *seeker;
+
+    /* Handlers for notifications */
+    MafwGstRendererWorkerNotifySeekCb notify_seek_handler;
+    MafwGstRendererWorkerNotifyPauseCb notify_pause_handler;
+    MafwGstRendererWorkerNotifyPlayCb notify_play_handler;
+    MafwGstRendererWorkerNotifyBufferStatusCb notify_buffer_status_handler;
+    MafwGstRendererWorkerNotifyEOSCb notify_eos_handler;
+    MafwGstRendererWorkerNotifyReadyStateCb notify_ready_state_handler;
+    MafwGstRendererWorkerNotifyMetadataCb notify_metadata_handler;
+    MafwGstRendererWorkerNotifyErrorCb notify_error_handler;
+    MafwGstRendererWorkerNotifyPropertyCb notify_property_handler;
+
+    MafwGstRendererWorkerBlankingControlCb blanking__control_handler;
+    MafwGstRendererWorkerScreenshotCb screenshot_handler;
+};
+
+
+MafwGstRendererWorker *mafw_gst_renderer_worker_new(gpointer owner);
+
+void mafw_gst_renderer_worker_exit(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_set_current_frame_on_pause(
+    MafwGstRendererWorker *worker,
+    gboolean current_frame_on_pause);
+
+void mafw_gst_renderer_worker_set_ready_timeout(MafwGstRendererWorker *worker,
+                                                guint seconds);
+
+gboolean mafw_gst_renderer_worker_get_current_frame_on_pause(
+    MafwGstRendererWorker *worker);
+
+configuration* mafw_gst_renderer_worker_create_default_configuration(MafwGstRendererWorker *worker);
+void mafw_gst_renderer_worker_set_configuration(MafwGstRendererWorker *worker,
+                                                configuration *config);
+
+void mafw_gst_renderer_worker_set_position(MafwGstRendererWorker *worker,
+                                           GstSeekType seek_type,
+                                           gint position,
+                                           GError **error);
+
+gint mafw_gst_renderer_worker_get_position(MafwGstRendererWorker *worker);
+
+gint64 mafw_gst_renderer_worker_get_last_known_duration(MafwGstRendererWorker *worker);
+gint64 mafw_gst_renderer_worker_get_duration(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_set_xid(MafwGstRendererWorker *worker, XID xid);
+
+XID mafw_gst_renderer_worker_get_xid(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_set_render_rectangle(MafwGstRendererWorker *worker, render_rectangle *rect);
+const render_rectangle* mafw_gst_renderer_worker_get_render_rectangle(MafwGstRendererWorker *worker);
+
+gboolean mafw_gst_renderer_worker_get_autopaint(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_set_autopaint(MafwGstRendererWorker *worker,
+                                            gboolean autopaint);
+
+gboolean mafw_gst_renderer_worker_set_playback_speed(MafwGstRendererWorker *worker, gfloat speed);
+
+gfloat mafw_gst_renderer_worker_get_playback_speed(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_set_force_aspect_ratio(MafwGstRendererWorker *worker, gboolean force);
+
+gboolean mafw_gst_renderer_worker_get_force_aspect_ratio(MafwGstRendererWorker *worker);
+
+gint mafw_gst_renderer_worker_get_colorkey(MafwGstRendererWorker *worker);
+
+gboolean mafw_gst_renderer_worker_get_seekable(MafwGstRendererWorker *worker);
+
+gboolean mafw_gst_renderer_worker_get_streaming(MafwGstRendererWorker *worker);
+
+const char* mafw_gst_renderer_worker_get_uri(MafwGstRendererWorker *worker);
+
+GHashTable *mafw_gst_renderer_worker_get_current_metadata(
+    MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_play(MafwGstRendererWorker *worker,
+                                   const gchar *uri);
+
+void mafw_gst_renderer_worker_stop(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_pause(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_resume(MafwGstRendererWorker *worker);
+
+void mafw_gst_renderer_worker_pause_at(MafwGstRendererWorker *worker, guint position);
+
+guint check_dolby_audioroute(MafwGstRendererWorker *worker, guint prop);
+
+void set_dolby_music_property(MafwGstRendererWorker *worker, guint prop);
+void set_dolby_music_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty);
+
+void set_dolby_video_property(MafwGstRendererWorker *worker, guint prop);
+void set_dolby_video_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty);
+
+void mafw_gst_renderer_worker_notify_media_destination(MafwGstRendererWorker *worker,
+                                                       GSList *destinations);
+
+G_END_DECLS
+#endif
diff --git a/qmafw-gst-subtitles-renderer/mafw-gst-renderer-plugin.conf b/qmafw-gst-subtitles-renderer/mafw-gst-renderer-plugin.conf
new file mode 100644 (file)
index 0000000..2767d34
--- /dev/null
@@ -0,0 +1,37 @@
+;Renderer instances
+[renderers]
+1\Id=mafw_gst_renderer
+1\FriendlyName=MafwGstRenderer
+2\Id=mafw_gst_internal_video_renderer
+2\FriendlyName=MafwGstVideoRenderer
+size=2
+
+[in-process-renderers]
+1\Id=mafw_in_process_gst_renderer
+1\FriendlyName=MafwInProcessGstRenderer
+size=1
+
+;Renderer's configuration
+[pipeline]
+audio-sink=pulsesink
+video-sink=omapxvsink
+flags=71
+use_dhmmixer=1
+buffer-time=600000
+latency-time=300000
+autoload_subtitles=1
+subtitle_encoding=NULL
+subtitle_font=Sans Bold 18
+
+[timers]
+pause-frame=700
+pause-to-ready=3
+
+[dhmmixer]
+;default values should be overwritten from gconf
+dhm-music-surround=0
+dhm-music-color=2
+dhm-music-room-size=2
+dhm-video-surround=0
+dhm-video-color=2
+dhm-video-room-size=2
diff --git a/qmafw-gst-subtitles-renderer/qmafw-gst-subtitles-renderer.pro b/qmafw-gst-subtitles-renderer/qmafw-gst-subtitles-renderer.pro
new file mode 100644 (file)
index 0000000..05636b4
--- /dev/null
@@ -0,0 +1,99 @@
+TEMPLATE        = lib
+TARGET          = qmafw-gst-renderer-plugin
+VERSION         = 0.0.55-1
+
+QT = core network
+
+isEmpty(PREFIX) {
+    PREFIX=/usr
+}
+
+isEmpty(MODE) {
+    CONFIG += release
+    QMAKE_CXXFLAGS += -g
+    QMAKE_CFLAGS   += -g
+}
+
+contains(MODE, release) {
+    CONFIG += release
+    DEFINES        += G_DISABLE_ASSERT
+    QMAKE_CXXFLAGS += -g
+    QMAKE_CFLAGS   += -g
+}
+
+contains(MODE, debug) {
+    CONFIG += debug
+}
+
+CONFIG          += no_keywords qt qdbus link_pkgconfig plugin
+PKGCONFIG       += qmafw glib-2.0 gobject-2.0 gq-gconf gstreamer-0.10 gstreamer-plugins-base-0.10 QtSparql
+PKGCONFIG       += contextprovider-1.0 contextsubscriber-1.0 qmsystem2 usb_moded
+
+LIBS +=  -lgstinterfaces-0.10 -lgstpbutils-0.10 -ldbus-qeventloop -ltotem-plparser
+
+DEPENDPATH      += . inc src
+INCLUDEPATH     += . inc $$system(pkg-config --variable=includedir qmafw) 
+
+#DEFINES += QT_NO_DEBUG_OUTPUT
+
+QMAKE_CXXFLAGS  += -Wall -Werror
+QMAKE_CFLAGS    += -Wall -Werror
+
+QMAKE_CLEAN     += build-stamp \
+                   configure-stamp
+
+# Version info
+DEFINES             += _VERSION_INFO
+QMAKE_EXTRA_TARGETS += revtarget
+revtarget.target     = inc/version.h
+revtarget.commands  += @echo update version info
+revtarget.commands  += $$escape_expand( \\n\\t )@echo \"namespace \{\" > $$revtarget.target
+revtarget.commands  += $$escape_expand( \\n\\t )@echo \"const char *revision = \\\"$(shell svnversion -n . || echo N/A )\\\";\" >> $$revtarget.target
+revtarget.commands  += $$escape_expand( \\n\\t )@echo \"const char *build_time = \\\"$(shell date )\\\";\" >> $$revtarget.target
+revtarget.commands  += $$escape_expand( \\n\\t )@echo \"\};\" >> $$revtarget.target
+# update revision/buildtime every time when linking is required
+QMAKE_POST_LINK     += @rm -f $$revtarget.target
+
+# Input
+HEADERS += MafwGstRenderer.h \
+    MafwGstRendererPlugin.h \
+    MafwBlankingPreventer.h \
+    mafw-gst-renderer-utils.h \
+    mafw-gst-renderer-worker.h \
+    MafwGstRendererVolume.h \
+    MafwGstRendererPlaylistFileUtility.h \
+    MafwGstRendererNetworkMonitor.h \
+    MafwGstRendererDolby.h \
+    MafwGstScreenshot.h \
+    MafwMmcMonitor.h \
+    mafw-gst-renderer-seeker.h \
+    MafwGstRendererHaltState.h
+
+SOURCES += MafwGstRenderer.cpp \
+    MafwGstRendererPlugin.cpp \
+    MafwBlankingPreventer.cpp \
+    mafw-gst-renderer-utils.c \
+    mafw-gst-renderer-worker.c \
+    MafwGstRendererVolume.cpp \
+    MafwGstRendererPlaylistFileUtility.cpp \
+    MafwGstRendererNetworkMonitor.cpp \
+    MafwGstRendererDolby.cpp \
+    MafwGstScreenshot.cpp \
+    MafwMmcMonitor.cpp \
+    mafw-gst-renderer-seeker.c \
+    MafwGstRendererHaltState.cpp
+
+DISTFILES += qmafw-gst-renderer.service
+
+# Installation
+service.files     = com.nokia.mafw.plugin.libqmafw_gst_renderer_plugin.service
+service.path      = $$PREFIX/share/dbus-1/services
+target.path       = $$PREFIX/lib/qmafw-plugin
+
+context.files     = com.nokia.mafw.context_provider.libqmafw_gst_renderer.context
+context.path      = $$PREFIX/share/contextkit/providers
+
+settings.files    = mafw-gst-renderer-plugin.conf
+settings.path     = /usr/share/qmafw
+
+INSTALLS         += target service context settings
diff --git a/qmafw-gst-subtitles-renderer/src/MafwBlankingPreventer.cpp b/qmafw-gst-subtitles-renderer/src/MafwBlankingPreventer.cpp
new file mode 100644 (file)
index 0000000..e328255
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwBlankingPreventer.h"
+#include <qmdisplaystate.h>
+#include <QDebug>
+
+/* Interval of recalling setBlankingPause in seconds */
+const int BLANKING_TIMER_INTERVAL=45;
+
+MafwBlankingPreventer::MafwBlankingPreventer(QObject* parent) : QObject(parent)
+{
+    connect( &m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
+    m_refreshTimer.setInterval( BLANKING_TIMER_INTERVAL*1000 );
+    m_display = new MeeGo::QmDisplayState(this);
+}
+
+void MafwBlankingPreventer::blankingProhibit()
+{
+    qDebug() << "MafwBlankingPreventer::blankingProhibit";
+    refresh();
+    m_refreshTimer.start();
+}
+
+void MafwBlankingPreventer::blankingAllow()
+{
+    qDebug() << "MafwBlankingPreventer::blankingAllow";
+    m_refreshTimer.stop();
+    m_display->cancelBlankingPause();
+}
+
+void MafwBlankingPreventer::refresh()
+{
+    bool success = m_display->setBlankingPause();
+    qDebug() << "MafwBlankingPreventer::refresh success" << success;
+}
+
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstRenderer.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstRenderer.cpp
new file mode 100644 (file)
index 0000000..a595711
--- /dev/null
@@ -0,0 +1,2437 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QDebug>
+#include <QMetaMethod>
+#include <QTimer>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <X11/Xdefs.h>
+
+#include <MafwCallbackHelper.h>
+#include <MafwMetadata.h>
+#include <MafwMediaInfo.h>
+
+#include "MafwGstRenderer.h"
+#include "MafwBlankingPreventer.h"
+#include "mafw-gst-renderer-worker.h"
+#include "MafwGstRendererVolume.h"
+#include "MafwGstRendererDolby.h"
+#include "MafwGstRendererNetworkMonitor.h"
+#include "MafwGstRendererHaltState.h"
+#include "MafwGstRendererPlaylistFileUtility.h"
+#include "MafwGstScreenshot.h"
+#include "MafwMmcMonitor.h"
+
+#include <QSettings>
+#include <contextsubscriber/contextproperty.h>
+#include <QDBusConnection>
+#include <QDBusMessage>
+#include <QDateTime>
+#include <QSparqlConnection>
+#include <QSparqlResult>
+#include <QSparqlQuery>
+#include <QSparqlError>
+
+// milliseconds, stamp after playing this much
+const int PLAYED_STAMP_INTERVAL = 5000;
+
+const int MAX_SUPPORTED_HEIGHT = 720;
+const int MAX_SUPPORTED_WIDTH = 1280;
+// how many time we retried to make played stamps
+const int PLAYED_STAMP_TRIES = 3;
+
+static const int ISO_DATE_BASE_LENGTH = 19; // length of "CCYY-MM-DDThh:mm:ss"
+
+// property names
+const QString PROPERTY_DOLBY_STATE_MUSIC    = "mobile-surround-state-music";
+const QString PROPERTY_DOLBY_STATE_MUSIC_ROOM    = "mobile-surround-state-music-room";
+const QString PROPERTY_DOLBY_STATE_MUSIC_COLOR    = "mobile-surround-state-music-color";
+const QString PROPERTY_DOLBY_STATE_VIDEO    = "mobile-surround-state-video";
+const QString PROPERTY_DOLBY_STATE_VIDEO_ROOM    = "mobile-surround-state-video-room";
+const QString PROPERTY_DOLBY_STATE_VIDEO_COLOR    = "mobile-surround-state-video-color";
+const QString PROPERTY_VOLUME    = "volume";
+const QString PROPERTY_AUTOPAINT = "autopaint";
+const QString PROPERTY_COLORKEY  = "colorkey";
+const QString PROPERTY_XID       = "xid";
+const QString PROPERTY_RENDER_RECT = "render-rectangle";
+const QString PROPERTY_CURRENT_FRAME_ON_PAUSE = "current-frame-on-pause";
+const QString PROPERTY_PLAYBACK_SPEED   = "playback-speed";
+const QString PROPERTY_FORCE_ASPECT_RATIO  = "force-aspect-ratio";
+
+// audio/video destinations
+const QString CONTEXT_FW_PROPERTY_AUDIO_ROUTE = "/com/nokia/policy/audio_route";
+const QString CONTEXT_FW_PROPERTY_VIDEO_ROUTE = "/com/nokia/policy/video_route";
+const QString AUDIO_ROUTE_NULL                = "null";
+const QString AUDIO_ROUTE_IHF                 = "ihf";
+const QString AUDIO_ROUTE_FMRADIO             = "fmtx";
+const QString AUDIO_ROUTE_IHF_AND_FMRADIO     = "ihfandfmtx";
+const QString AUDIO_ROUTE_EARPIECE            = "earpiece";
+const QString AUDIO_ROUTE_EARPIECE_AND_TVOUT  = "earpieceandtvout";
+const QString AUDIO_ROUTE_TV_OUT              = "tvout";
+const QString AUDIO_ROUTE_IHF_AND_TV_OUT      = "ihfandtvout";
+const QString AUDIO_ROUTE_HEADPHONE           = "headphone";
+const QString AUDIO_ROUTE_HEADSET             = "headset";
+const QString AUDIO_ROUTE_BTHSP               = "bthsp";
+const QString AUDIO_ROUTE_BTA2DP              = "bta2dp";
+const QString AUDIO_ROUTE_IHF_AND_HEADSET     = "ihfandheadset";
+const QString AUDIO_ROUTE_IHF_AND_HEADPHONE   = "ihfandheadphone";
+const QString AUDIO_ROUTE_IHF_AND_BTHSP       = "ihfandbthsp";
+const QString AUDIO_ROUTE_TV_OUT_AND_BTHSP    = "tvoutandbthsp";
+const QString AUDIO_ROUTE_TV_OUT_AND_BTA2DP   = "tvoutandbta2dp";
+const QString VIDEO_ROUTE_TV_OUT              = "tvout";
+const QString VIDEO_ROUTE_BUILT_IN            = "builtin";
+const QString VIDEO_ROUTE_BUILT_IN_AND_TV_OUT = "builtinandtvout";
+
+const QString DBUS_INTERFACE_DBUS="org.freedesktop.DBus";
+const QString DBUS_SIGNAL_NAME_OWNER_CHANGED="NameOwnerChanged";
+const QString DBUS_NAME_PCFD = "com.nokia.policy.pcfd";
+
+/********************************************************************
+ * MafwGstRenderer::MafwGstRenderer
+ ********************************************************************/
+MafwGstRenderer::MafwGstRenderer(const QString& uuid,
+                                 const QString& pluginName,
+                                 const QString& name,
+                                 QObject *parent)
+    :
+    MafwBasicRenderer(uuid, pluginName, name, parent),
+    m_initialized(false),
+    m_currentState(MafwRenderer::Invalid),
+    m_nextContent(""),
+    m_currentContent(""),
+    m_playingItem(MafwBasicRenderer::UnknownUri),
+    m_blankingPreventer(0),
+    m_screenshot(0),
+    m_networkMonitor(new MafwGstRendererNetworkMonitor()),
+    m_volume(0),
+    m_playedStamped(false),
+    m_playedStampTryCounter(0),
+    m_sparqlConnection(new QSparqlConnection("QTRACKER", QSparqlConnectionOptions(), this)),
+    m_urnQueryResult(0),
+    m_stampItResult(0),
+    m_playlistFileUtil(0),
+    m_playingPlaylistFile(false),
+    m_unsupportedTypeError(0),
+    m_playedPlaylistItem(false),
+    m_mmcMonitor(0)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_dolby = new MafwGstRendererDolby(this);
+    connect(m_dolby, SIGNAL(mafwDHMMusicPropertyChanged()),
+            this, SLOT(handleDHMMusicPropertyChanged()));
+    connect(m_dolby, SIGNAL(mafwDHMVideoPropertyChanged()),
+            this, SLOT(handleDHMVideoPropertyChanged()));
+
+    m_worker = 0;
+    m_videoRoute = 0;
+    m_audioRoute = 0;
+    gst_init(0, 0);
+
+    /* make this connection a queued connection to postpone results delivery,
+     * so that results callback is not called already in the function that
+     * initiates this procedure */
+    QObject::connect(this, SIGNAL(signalGetPosition(QObject*,
+                                                    const char*)),
+                     this, SLOT(slotGetPosition(QObject*,
+                                                const char*)),
+                     Qt::QueuedConnection);
+
+    /* make this connection a queued connection to postpone results delivery,
+     * so that results callback is not called already in the function that
+     * initiates this procedure */
+    QObject::connect(this, SIGNAL(signalMafwProperty(QString,
+                                                     QObject*,
+                                                     const char*)),
+                     this, SLOT(slotMafwProperty(QString,
+                                                 QObject*,
+                                                 const char*)),
+                     Qt::QueuedConnection);
+
+    /* make this connection a queued connection to postpone results delivery,
+     * so that results callback is not called already in the function that
+     * initiates this procedure */
+    QObject::connect(this, SIGNAL(signalGetCurrentMediaInfo(QObject*,
+                                                            const char*,
+                                                            const QString)),
+                    this, SLOT(slotGetCurrentMediaInfo(QObject*,
+                                                        const char*,
+                                                        const QString)),
+                    Qt::QueuedConnection);
+
+    m_playedStampTimer.setSingleShot(true);
+    connect(&m_playedStampTimer,SIGNAL(timeout()),this,SLOT(slotStamp()));
+
+    m_videoRoute = new ContextProperty(CONTEXT_FW_PROPERTY_VIDEO_ROUTE);
+    m_audioRoute = new ContextProperty(CONTEXT_FW_PROPERTY_AUDIO_ROUTE);
+
+    connectNameOwnerChanged();
+
+    m_playlistNextTimer.setSingleShot(true);
+    connect(&m_playlistNextTimer, SIGNAL(timeout()),
+            this, SLOT(playNextURIFromPlaylist()));
+
+    /* connection is to track when policy is on/off */
+    connect(this, SIGNAL(mafwPropertyChanged(const QString, const QVariant)),
+            this, SLOT(handlePropertyChanged(const QString&, const QVariant&)));
+
+    /* Connection to handle online status message if necessary */
+    connect(m_networkMonitor, SIGNAL(prepareNetworkChange()),
+            this, SLOT(haltStreaming()));
+    connect(m_networkMonitor, SIGNAL(networkChangeFinished()),
+            this, SLOT(continueStreaming()));
+
+    connect(&m_haltState, SIGNAL(decayed()),
+            this, SLOT(stopStreaming()));
+}
+
+/********************************************************************
+ * MafwGstRenderer::~MafwGstRenderer
+ ********************************************************************/
+MafwGstRenderer::~MafwGstRenderer()
+{
+
+    qDebug() << __PRETTY_FUNCTION__;
+    delete m_volume;
+    // this releases the resources allocated by the worker, do this before
+    // releasing anything else so any callbacks from worker won't be called
+    mafw_gst_renderer_worker_exit(m_worker);
+
+    delete m_videoRoute;
+    delete m_audioRoute;
+    delete m_networkMonitor;
+    delete m_screenshot;
+    delete m_urnQueryResult;
+    delete m_stampItResult;
+    delete m_sparqlConnection;
+
+    g_free(m_worker);
+
+    if( m_unsupportedTypeError )
+    {
+        g_error_free(m_unsupportedTypeError);
+    }
+}
+
+
+/********************************************************************
+ * MafwGstRenderer::initialize
+ ********************************************************************/
+bool MafwGstRenderer::initialize(QSettings *settings)
+{
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    //if already initialized do nothing
+    if (m_initialized)
+    {
+        return m_initialized;
+    }
+
+    m_initialized = MafwBasicRenderer::initialize();
+
+    if (m_initialized)
+    {
+        // fail to apply default policy is not considered fatal for now
+        if (MafwBasicRenderer::setDefaultRendererPolicy(MafwRendererPolicy::MediaPlayer))
+        {
+            MafwRendererPolicy *policy = rendererPolicy();
+            Q_ASSERT(policy);
+            policy->setDefaultResources(MafwRendererPolicy::Audio);
+        }
+        else
+        {
+            qWarning() << "Setting default policy failed, continuing";
+        }
+
+        m_blankingPreventer = new MafwBlankingPreventer(this);
+
+        m_screenshot = new MafwGstScreenshot(this);
+
+        connect(m_screenshot, SIGNAL(screenshotTaken(char*,GError*)),
+                this, SLOT(handleScreenshot(char*,GError*)));
+        connect(m_screenshot, SIGNAL(screenshotCancelled()),
+                this, SLOT(cancelScreenshot()));
+
+        m_worker = mafw_gst_renderer_worker_new(this);
+        m_worker->notify_play_handler = &playCallback;
+        m_worker->notify_pause_handler = &pauseCallback;
+        m_worker->notify_error_handler = &errorCallback;
+        m_worker->notify_eos_handler = &eosCallback;
+        m_worker->notify_ready_state_handler = &readyStateCallback;
+        m_worker->notify_metadata_handler = &metadataCallback;
+        m_worker->notify_property_handler = &propertyCallback;
+        m_worker->notify_buffer_status_handler = &bufferStatusCallback;
+        m_worker->blanking__control_handler = &blankingControlCallback;
+        m_worker->screenshot_handler = &screenshotCallback;
+
+        setConfiguration(settings);
+
+        // Initialize Dolby support
+        m_dolby->initialize();
+
+        m_mmcMonitor = new MafwMmcMonitor(this);
+        connect( m_mmcMonitor, SIGNAL( preUnmount() ), this, SLOT( mmcPreUnmount() ) );
+
+        // connect the audio routes AND check the current values of routes.
+        connect( m_videoRoute, SIGNAL( valueChanged() ), this, SLOT( slotRouteChanged() ) );
+        connect( m_audioRoute, SIGNAL( valueChanged() ), this, SLOT( slotRouteChanged() ) );
+        slotRouteChanged();
+    }
+    return m_initialized;
+}
+
+/********************************************************************
+ * MafwGstRenderer::playCallback
+ ********************************************************************/
+void MafwGstRenderer::playCallback(MafwGstRendererWorker *worker,
+                                   gpointer owner)
+{
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+
+    if( self->m_currentState == MafwRenderer::Paused )
+    {
+        Q_EMIT self->rendererResumed();
+    }
+    else
+    {
+        if( self->m_playingPlaylistFile )
+        {
+            if( !self->m_playedPlaylistItem )
+            {
+                qDebug() << "Emitting playing item event";
+                Q_EMIT self->rendererPlaying(static_cast<int>(self->m_playingItem));
+                self->m_playedPlaylistItem = true;
+            }
+        }
+        else
+        {
+            Q_EMIT self->rendererPlaying(static_cast<int>(self->m_playingItem));
+        }
+    }
+
+    if( mafw_gst_renderer_worker_get_position(worker)==0 )
+    {
+        self->m_playedStamped = false;
+        self->m_playedStampTryCounter = 0;
+    }
+
+    if( !self->m_playedStamped )
+    {
+        const QUrl url = self->m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
+        if (url.scheme() == "file")
+        {
+            qDebug() << __PRETTY_FUNCTION__ << "starting play stamp timer.";
+            self->m_playedStampTimer.start(PLAYED_STAMP_INTERVAL);
+        }
+    }
+
+    self->m_currentState = MafwRenderer::Playing;
+}
+
+/********************************************************************
+ * MafwGstRenderer::bufferStatusCallback
+ ********************************************************************/
+void MafwGstRenderer::bufferStatusCallback(MafwGstRendererWorker *worker,
+                                           gpointer owner,
+                                           gdouble percent)
+{
+
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+
+    Q_EMIT self->bufferingInfo(static_cast<float>(percent));
+
+}
+/********************************************************************
+ * MafwGstRenderer::constructMafwError
+ ********************************************************************/
+MafwError MafwGstRenderer::constructMafwError(const GError* error)
+{
+    MafwError mafwError;
+    guint32 code = static_cast<guint32>(error->code);
+
+    //for streams the media not found is other than the default
+    if( code == WORKER_ERROR_MEDIA_NOT_FOUND && mafw_gst_renderer_worker_get_streaming(m_worker) )
+    {
+        mafwError.setCode(MafwError::RendererError_URINotAvailable);
+    }
+    else if(code == WORKER_ERROR_UNSUPPORTED_TYPE)
+    {
+        handleResolutionError(mafwError);
+    }
+    else if (errorMap().contains(code))
+    {
+        mafwError.setCode(errorMap().value(code));
+    }
+    else
+    {
+        mafwError.setCode(MafwError::NothingButErrors);
+    }
+
+    mafwError.setMessage(error->message);
+    return mafwError;
+}
+
+/********************************************************************
+ * MafwGstRenderer::errorCallback
+ ********************************************************************/
+void MafwGstRenderer::errorCallback(MafwGstRendererWorker *worker,
+                                    gpointer owner,
+                                    const GError *error)
+{
+    Q_UNUSED(worker);
+    qWarning() << __PRETTY_FUNCTION__ << error->message;
+    MafwError mafwError;
+    guint32 code;
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+
+    code = static_cast<guint32>(error->code);
+
+    //The content might be a playlist file which was tried to play without
+    //mime type. This case can be detected by trying to play it as playlist
+    //file. If that was not the case same error will be signalled via
+    //MafwGstRenderer::handlePlaylistFileParsingErrors
+    if (!self->m_playingPlaylistFile &&
+        !self->m_unsupportedTypeError &&
+        code == WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE)
+    {
+        QMap<QString, QVariant> mime;
+        mime[MAFW_METADATA_KEY_MIME] = "audio/x-scpls";
+        self->m_currentContent.setMetaData(mime);
+        self->doPlay(self->m_currentContent);
+        self->m_unsupportedTypeError = g_error_copy(error);
+        qWarning() << __PRETTY_FUNCTION__ << "Probably we were trying to play playlist file without mime type. If that's the case use bool play(url, 'audio/x-scpls').";
+        qWarning() << __PRETTY_FUNCTION__ << "Trying to play as playlist file now...";
+        return;
+    }
+    mafwError = self->constructMafwError(error);
+
+    /* We release resources when we got error that causes stop.
+     * WORKER_ERROR_CANNOT_SET_POSITION and WORKER_ERROR_DRM_NOT_ALLOWED error don't cause stop.
+     */
+    if((code != WORKER_ERROR_CANNOT_SET_POSITION
+        && code != WORKER_ERROR_DRM_NOT_ALLOWED)
+        && !self->m_playingPlaylistFile)
+    {
+        Q_EMIT self->rendererError(mafwError);
+        MafwRendererPolicy *policy = self->rendererPolicy();
+        Q_ASSERT(policy);
+        if( policy )
+        {
+            policy->release();
+            qDebug() << __PRETTY_FUNCTION__ << "Resources released because of error" << mafwError.code();
+        }
+        else
+        {
+            qWarning() << __PRETTY_FUNCTION__ << "No policy exists!";
+        }
+
+        self->doStop();
+    }
+    else if (code != WORKER_ERROR_CANNOT_SET_POSITION && code != WORKER_ERROR_DRM_NOT_ALLOWED) //Try next uri
+    {
+        //using singleshot gives worker/gstreamer time to do
+        //cleanup before calling worker_play
+        if (self->m_playlistFileUtil->getUriList().isEmpty())
+        {
+          //delayed call to playNextURIFromPlaylist used to give the parser
+          //enough time to read new items from the playlist
+          self->m_playlistFileUtil->setPendingError(mafwError);
+
+          self->m_playlistNextTimer.start(1000);
+        }
+        else
+        {
+            self->m_playlistNextTimer.start(0);
+        }
+    }
+    else
+    {
+        Q_EMIT self->rendererError(mafwError);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::propertyCallback
+ ********************************************************************/
+void MafwGstRenderer::propertyCallback(MafwGstRendererWorker *worker,
+                                       gpointer owner,
+                                       gint id,
+                                       GValue *value)
+{
+
+    QString name;
+
+    Q_UNUSED(worker);
+
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+
+    switch (id)
+    {
+        case WORKER_PROPERTY_AUTOPAINT:
+            name = PROPERTY_AUTOPAINT;
+            break;
+        case WORKER_PROPERTY_COLORKEY:
+            name = PROPERTY_COLORKEY;
+            break;
+        case WORKER_PROPERTY_XID:
+            name = PROPERTY_XID;
+            break;
+        case WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE:
+            name = PROPERTY_CURRENT_FRAME_ON_PAUSE;
+            break;
+        case WORKER_PROPERTY_PLAYBACK_SPEED:
+            name = PROPERTY_PLAYBACK_SPEED;
+            break;
+        case WORKER_PROPERTY_FORCE_ASPECT_RATIO:
+            name = PROPERTY_FORCE_ASPECT_RATIO;
+            break;
+        case WORKER_PROPERTY_RENDER_RECTANGLE:
+            name = PROPERTY_RENDER_RECT;
+            break;
+        default:
+            qWarning() << __PRETTY_FUNCTION__ << "unknown property id:" << id;
+            return;
+            break;
+    }
+
+    qDebug() << __PRETTY_FUNCTION__ << name;
+
+    QVariant result = getValue(value);
+
+    if (result.isValid())
+    {
+        Q_EMIT self->mafwPropertyChanged(name, result);
+    }
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::blankingControlCallback
+ ********************************************************************/
+void MafwGstRenderer::blankingControlCallback(MafwGstRendererWorker *worker,
+                                   gpointer owner, gboolean prohibit)
+{
+
+    Q_UNUSED(worker);
+    qDebug() << __PRETTY_FUNCTION__ << prohibit;
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+    if(self->m_videoRoute->value() == VIDEO_ROUTE_TV_OUT ||
+       self->m_videoRoute->value() == VIDEO_ROUTE_BUILT_IN_AND_TV_OUT)
+    {
+        prohibit = false;
+    }
+
+    if( prohibit )
+    {
+        self->m_blankingPreventer->blankingProhibit();
+    }
+    else
+    {
+        self->m_blankingPreventer->blankingAllow();
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::screenshotCallback
+ ********************************************************************/
+void MafwGstRenderer::screenshotCallback(MafwGstRendererWorker *worker,
+                                         gpointer owner, GstBuffer *buffer,
+                                         const char *filename, gboolean cancel)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    MafwGstRenderer *self = static_cast<MafwGstRenderer*>(owner);
+
+    if(cancel)
+    {
+        self->m_screenshot->cancelPauseFrame();
+    }
+    else
+    {
+        if(!self->m_screenshot->savePauseFrame(buffer, filename))
+        {
+            worker->taking_screenshot = FALSE;
+            qCritical() << "Failed to create pause frame pipeline";
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::getValue
+ ********************************************************************/
+QVariant MafwGstRenderer::getValue(const GValue *v)
+{
+
+    QVariant result;
+
+    if (G_IS_VALUE(v))
+    {
+        if (G_VALUE_TYPE(v) == G_TYPE_STRING)
+        {
+            // tags from GStreamer are always expected to be UTF-8
+            result = QVariant(QString::fromUtf8(g_value_get_string(v)));
+        }
+        else if (G_VALUE_TYPE(v) == G_TYPE_UINT)
+        {
+            result = QVariant(g_value_get_uint(v));
+        }
+        else if (G_VALUE_TYPE(v) == G_TYPE_INT)
+        {
+            result = QVariant(g_value_get_int(v));
+        }
+        else if (G_VALUE_TYPE(v) == G_TYPE_BOOLEAN)
+        {
+            result = QVariant::fromValue<bool>(g_value_get_boolean(v));
+        }
+        else if (G_VALUE_TYPE(v) == G_TYPE_DOUBLE)
+        {
+            result = QVariant(g_value_get_double(v));
+        }
+        else if (G_VALUE_TYPE(v) == G_TYPE_INT64)
+        {
+            result = QVariant(g_value_get_int64(v));
+        }
+        else if (G_VALUE_TYPE(v) == G_TYPE_FLOAT)
+        {
+            result = QVariant(g_value_get_float(v));
+        }
+        else if (G_VALUE_TYPE(v) == G_TYPE_VALUE_ARRAY)
+        {
+            GValueArray *vals = static_cast<GValueArray*>(g_value_get_boxed(v));
+            if( vals->n_values == 4 )
+            {
+               result = QString("%1,%2,%3,%4")
+                       .arg(g_value_get_int(g_value_array_get_nth(vals, 0)))
+                       .arg(g_value_get_int(g_value_array_get_nth(vals, 1)))
+                       .arg(g_value_get_int(g_value_array_get_nth(vals, 2)))
+                       .arg(g_value_get_int(g_value_array_get_nth(vals, 3)));
+            }
+            else
+            {
+                qWarning() << "Invalid rect values received? Size:" << vals->n_values;
+            }
+
+        }
+        else
+        {
+            qWarning() << "unsupported value g_type";
+        }
+    }
+
+    return result;
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::metadataCallback
+ ********************************************************************/
+void MafwGstRenderer::metadataCallback(MafwGstRendererWorker *worker,
+                                       gpointer owner,
+                                       gint key,
+                                       GType type,
+                                       gpointer value)
+{
+
+    QList<QVariant> results;
+
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__ << key << metadataMap().value(key);
+
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+
+    if (metadataMap().contains(key))
+    {
+        if (type == G_TYPE_VALUE_ARRAY)
+        {
+            uint i;
+            GValueArray *vals = static_cast<GValueArray*>(value);
+            for (i = 0; i < vals->n_values; i++)
+            {
+                QVariant v = getValue(g_value_array_get_nth(vals, i));
+                if (v.isValid())
+                {
+                    results << v;
+                }
+            }
+
+            QString mafwMetadataKey = metadataMap().value(key);
+
+            self->appendRelatedMetadata(mafwMetadataKey, &results);
+
+            Q_EMIT self->metadataChanged(mafwMetadataKey, results);
+            self->m_currentMetaData.insert(mafwMetadataKey, results);
+        }
+        else
+        {
+            qWarning() << "unsupported g_type";
+        }
+    }
+    else
+    {
+        qWarning() << "unknown metadata key:" << key;
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::appendRelatedMetadata
+ ********************************************************************/
+void MafwGstRenderer::appendRelatedMetadata(const QString key, QList<QVariant>* results)
+{
+    if(key == MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI)
+    {
+        gint position = mafw_gst_renderer_worker_get_position(m_worker);
+        if(position < 0)
+        {
+            position = 0;
+        }
+
+        QUrl uri = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
+        *results << uri.toEncoded().constData();
+        *results << QVariant(position);
+    }
+}
+
+//
+// QMafw renderer interface implementation
+//
+
+/********************************************************************
+ * MafwGstRenderer::doPlay
+ ********************************************************************/
+void MafwGstRenderer::doPlay(const MafwContent& content)
+{
+    Q_ASSERT_X(false, "MafwGstRenderer", "Wrong play function called!");
+    Q_UNUSED(content);
+}
+
+/********************************************************************
+ * MafwGstRenderer::doPlay
+ ********************************************************************/
+void MafwGstRenderer::doPlay(const MafwMediaInfo& mediaInfo)
+{
+    //Preserve m_currentContent for keeping usage count up if the same item is
+    //played again.
+    if(mediaInfo.uuid().isEmpty() ||
+        mediaInfo.uuid() != m_currentContent.uuid())
+    {
+        m_currentContent = mediaInfo;
+    }
+    m_playingItem = MafwBasicRenderer::CurrentUri;
+    m_currentMetaData.clear();
+
+    const QUrl url = mediaInfo.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
+    qDebug() << __PRETTY_FUNCTION__ << url.toEncoded();
+
+    m_haltState.clear();
+
+    if( !m_mmcMonitor->isMounted() && url.toString().startsWith( MafwMmcMonitor::MMC_URI_PREFIX ) )
+    {
+        qDebug() << "MafwGstRenderer::doPlay: Can't play MMC not mounted";
+        MafwError mafwError(MafwError::RendererError_MmcNotAvailable, url.toEncoded());
+        Q_EMIT rendererError(mafwError);
+        return;
+    }
+
+    m_playedPlaylistItem = false;
+    m_playingPlaylistFile = false;
+    if (m_unsupportedTypeError)
+    {
+        g_error_free(m_unsupportedTypeError);
+        m_unsupportedTypeError = 0;
+    }
+
+    if( url.isValid() )
+    {
+        stopTimers();
+
+        // Set correct value for the Dolby Headphones Mobile effect plugin
+        set_dolby_music_property(m_worker, m_dolby->getMusicDolbyState());
+        set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyRoom(), TRUE);
+        set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyColor(), FALSE);
+        set_dolby_video_property(m_worker, m_dolby->getVideoDolbyState());
+        set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyRoom(), TRUE);
+        set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyColor(), FALSE);
+
+        const QString& mimeType = mediaInfo.firstMetaData(MAFW_METADATA_KEY_MIME).toString();
+        if (mimeType == "audio/x-scpls" )
+        {
+            if (!m_playlistFileUtil)
+            {
+                m_playlistFileUtil = new MafwGstRendererPlaylistFileUtility(this);
+                connect(m_playlistFileUtil, SIGNAL(firstItemParsed()),
+                        this, SLOT(startPlayingPlaylistFile()), Qt::QueuedConnection);
+                connect(m_playlistFileUtil, SIGNAL(parsingReady(bool)),
+                        this, SLOT(handlePlaylistFileParsingErrors(bool)), Qt::QueuedConnection);
+            }
+            m_playlistFileUtil->parsePlaylistFile(url);
+
+        }
+        else
+        {
+            playURI(url.toEncoded());
+
+            QVariant startPosition = mediaInfo.firstMetaData(MAFW_METADATA_KEY_START_POSITION);
+            if( startPosition.isValid() )
+            {
+                uint pos = startPosition.toUInt();
+                qDebug() << "Immediate seek requested to: " << pos;
+                doSeek(pos, MafwRenderer::SeekAbsolute);
+            }
+            else
+            {
+                QVariant pausePosition = mediaInfo.firstMetaData(MAFW_METADATA_KEY_PAUSED_POSITION);
+                if( pausePosition.isValid() )
+                {
+                    uint position = pausePosition.toUInt();
+                    qDebug() << "Immediate pause requested at:" << position;
+                    mafw_gst_renderer_worker_pause_at(m_worker, position);
+                }
+            }
+        }
+    }
+    else
+    {
+        MafwError mafwError(MafwError::RendererError_InvalidURI, url.toString());
+        Q_EMIT rendererError(mafwError);
+        doStop();
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::doStop
+ ********************************************************************/
+void MafwGstRenderer::doStop()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    mafw_gst_renderer_worker_stop(m_worker);
+    m_currentState = MafwRenderer::Stopped;
+    m_playingItem = MafwBasicRenderer::UnknownUri;
+
+    m_haltState.clear();
+
+    stopTimers();
+    Q_EMIT rendererStopped();
+}
+
+/********************************************************************
+ * MafwGstRenderer::doPause
+ ********************************************************************/
+void MafwGstRenderer::doPause()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if( m_haltState.isSet() && m_haltState.state() == MafwRenderer::Playing )
+    {
+        m_haltState.setState(MafwRenderer::Paused);
+        m_currentState = MafwRenderer::Paused;
+        Q_EMIT rendererPaused();
+    }
+    else
+    {
+        mafw_gst_renderer_worker_pause(m_worker);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::doResume
+ ********************************************************************/
+void MafwGstRenderer::doResume()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if( m_currentState == MafwRenderer::Paused && m_haltState.isSet() && m_haltState.state() == MafwRenderer::Paused )
+    {
+        mafw_gst_renderer_worker_play(m_worker, m_haltState.uri().toAscii().constData());
+        m_currentState = MafwRenderer::Paused;
+        if( m_haltState.position() > 0 )
+        {
+            doSeek(m_haltState.position(), MafwRenderer::SeekAbsolute);
+        }
+    }
+    else
+    {
+        mafw_gst_renderer_worker_resume(m_worker);
+    }
+
+    if( m_haltState.isSet() )
+    {
+        m_haltState.clear();
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::doSeek
+ ********************************************************************/
+void MafwGstRenderer::doSeek(int position, MafwRenderer::SeekMode seekMode)
+{
+    GError *error = 0;
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    GstSeekType seekType;
+    if( MafwRenderer::SeekAbsolute == seekMode )
+    {
+        seekType = GST_SEEK_TYPE_SET;
+    }
+    else if( MafwRenderer::SeekRelative == seekMode )
+    {
+        seekType = GST_SEEK_TYPE_CUR;
+    }
+    else
+    {
+        qCritical("MafwGstRenderer: Invalid seek operation requested!");
+        return;
+    }
+
+    mafw_gst_renderer_worker_set_position(m_worker,
+                                          seekType,
+                                          position,
+                                          &error);
+
+    if (error)
+    {
+        MafwError mafwError;
+        mafwError.setCode(MafwError::RendererError_CannotSetPosition);
+        mafwError.setMessage(error->message);
+        Q_EMIT rendererError(mafwError);
+        g_error_free(error);
+    }
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::doNextHint
+ ********************************************************************/
+bool MafwGstRenderer::doNextHint(const MafwContent& content)
+{
+    Q_ASSERT_X(false, "MafwGstRenderer", "Wrong play function called!");
+    Q_UNUSED(content);
+    return false;
+}
+
+/********************************************************************
+ * MafwGstRenderer::doNextHint
+ ********************************************************************/
+bool MafwGstRenderer::doNextHint(const MafwMediaInfo& mediaInfo)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_nextContent = mediaInfo;
+    // If we have already reached EOS trigger a new play attempt because the
+    // next content was signalled too late. However, if we have gone from playing
+    // state we can not continue, because we have released resources.
+    if (m_worker->eos && (m_currentState == MafwRenderer::Playing))
+    {
+        QTimer::singleShot(0, this, SLOT(playNext()));
+    }
+    return true;
+}
+
+/********************************************************************
+ * MafwGstRenderer::getPosition
+ ********************************************************************/
+bool MafwGstRenderer::getPosition(QObject* resultsReceiver,
+                                  const char* resultsMember)
+{
+
+    Q_EMIT signalGetPosition(resultsReceiver,
+                           resultsMember);
+
+    return true;
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::setMafwProperty
+ ********************************************************************/
+bool MafwGstRenderer::setMafwProperty(const QString& name,
+                                      const QVariant& value)
+{
+    qDebug() << __PRETTY_FUNCTION__ << name;
+
+    bool success = true;
+    if (name == PROPERTY_VOLUME)
+    {
+        if (!m_volume)
+        {
+            m_volume = new MafwGstRendererVolume();
+            connect(m_volume, SIGNAL(volumeChanged(uint)), this, SLOT(handleVolumeChange(uint)));
+        }
+        success = m_volume->setVolume(value.toUInt());
+    }
+    else if (name == PROPERTY_DOLBY_STATE_MUSIC)
+    {
+        success = m_dolby->setMusicDolbyState(value.toUInt());
+        if (success)
+        {
+            set_dolby_music_property(m_worker, m_dolby->getMusicDolbyState());
+        }
+    }
+    else if (name == PROPERTY_DOLBY_STATE_MUSIC_ROOM)
+    {
+        success = m_dolby->setMusicDolbyState(value.toInt());
+        if (success)
+        {
+            set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyRoom(), TRUE);
+        }
+    }
+    else if (name == PROPERTY_DOLBY_STATE_MUSIC_COLOR)
+    {
+        success = m_dolby->setMusicDolbyState(value.toInt());
+        if (success)
+        {
+            set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyColor(), FALSE);
+        }
+    }
+    else if (name == PROPERTY_DOLBY_STATE_VIDEO)
+    {
+        success = m_dolby->setVideoDolbyState(value.toUInt());
+        if (success)
+        {
+            set_dolby_video_property(m_worker, m_dolby->getVideoDolbyState());
+        }
+    }
+    else if (name == PROPERTY_DOLBY_STATE_VIDEO_ROOM)
+    {
+        success = m_dolby->setVideoDolbyState(value.toInt());
+        if (success)
+        {
+            set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyRoom(), TRUE);
+        }
+    }
+    else if (name == PROPERTY_DOLBY_STATE_VIDEO_COLOR)
+    {
+        success = m_dolby->setVideoDolbyState(value.toInt());
+        if (success)
+        {
+            set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyColor(), FALSE);
+        }
+    }
+    else if (name == PROPERTY_AUTOPAINT)
+    {
+        mafw_gst_renderer_worker_set_autopaint(m_worker, value.toBool());
+    }
+    else if (name == PROPERTY_XID)
+    {
+        if (rendererPolicy())
+        {
+            rendererPolicy()->setDefaultResources(MafwRendererPolicy::Audio | MafwRendererPolicy::Video);
+        }
+        else
+        {
+            qCritical() << __PRETTY_FUNCTION__ << "unable to append video to default resources";
+        }
+
+        mafw_gst_renderer_worker_set_xid(m_worker, value.toUInt());
+    }
+    else if (name == PROPERTY_CURRENT_FRAME_ON_PAUSE)
+    {
+        mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker,
+                                                            value.toBool());
+    }
+    else if (name == PROPERTY_PLAYBACK_SPEED)
+    {
+        success = mafw_gst_renderer_worker_set_playback_speed(m_worker, value.toFloat());
+    }
+    else if (name == PROPERTY_FORCE_ASPECT_RATIO)
+    {
+        mafw_gst_renderer_worker_set_force_aspect_ratio(m_worker, value.toBool());
+    }
+    else if( name == PROPERTY_RENDER_RECT )
+    {
+        if( value.type() != QVariant::String )
+        {
+            qWarning() << "MafwGstRenderer Invalid ("<<PROPERTY_RENDER_RECT<<") value received:" << value;
+        }
+        else
+        {
+            QString str = value.toString();
+            QStringList list = str.split(",");
+            bool success = true;
+            int array[4]; // x, y, width, height
+            if( list.size() != 4 )
+            {
+                success=false;
+            }
+            else
+            {
+                for( int i = 0; i < 4 && success; ++i )
+                {
+                    QString str = list.at(i);
+                    array[i] = str.toInt(&success);
+                }
+            }
+            if( !success )
+            {
+                qWarning() << "Invalid property (" << name << ") value received: " << value;
+            }
+            else
+            {
+                render_rectangle rect = {array[0], array[1], array[2], array[3]};
+                mafw_gst_renderer_worker_set_render_rectangle(m_worker, &rect);
+            }
+        }
+    }
+    else
+    {
+        success = MafwBasicRenderer::setMafwProperty(name, value);
+    }
+
+    if (!success)
+    {
+        MafwError err;
+        err.setCode(MafwError::RendererError_CannotSetProperty);
+        Q_EMIT rendererError(err);
+    }
+
+    return success;
+}
+
+/********************************************************************
+ * MafwGstRenderer::mafwProperty
+ ********************************************************************/
+bool MafwGstRenderer::mafwProperty(QString& name,
+                                   QObject* receiver,
+                                   const char* member)
+{
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    Q_EMIT signalMafwProperty(name, receiver, member);
+
+    return true;
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::mafwProperty
+ ********************************************************************/
+bool MafwGstRenderer::getCurrentMediaInfo(QObject* receiver,
+                                   const char* member,
+                                   const QString& metadataKey)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if(m_currentState == MafwRenderer::Playing || m_currentState == MafwRenderer::Paused)
+    {
+        Q_EMIT signalGetCurrentMediaInfo(receiver, member, metadataKey);
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+
+/********************************************************************
+ * MafwGstRenderer::pauseCallback
+ ********************************************************************/
+void MafwGstRenderer::pauseCallback(MafwGstRendererWorker *worker,
+                                    gpointer owner)
+{
+
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+
+    self->m_playedStampTimer.stop();
+
+    Q_EMIT self->rendererPaused();
+
+    //are we staying in paused after stopped state (pauseAt requested)
+    //we'll need to inform the MafwBasicRenderer to give the next item to play after current
+    //if so start fetching next also in this case
+    if( self->m_currentState == MafwRenderer::Stopped )
+    {
+        Q_EMIT self->rendererReadyForNext(self->m_playingItem);
+    }
+
+    self->m_currentState = MafwRenderer::Paused;
+}
+
+/********************************************************************
+ * MafwGstRenderer::eosCallback
+ * Renderer does not stop here, because there could be set next item to play.
+ ********************************************************************/
+void MafwGstRenderer::eosCallback(MafwGstRendererWorker *worker,
+                                  gpointer owner)
+{
+
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
+
+    //this is very special case to restart playing streams of undetermined duration and nonseekable
+    if( mafw_gst_renderer_worker_get_streaming(worker)
+        && mafw_gst_renderer_worker_get_last_known_duration(worker) < 0
+        && !mafw_gst_renderer_worker_get_seekable(worker) )
+    {
+        QTimer::singleShot(0, self, SLOT(restartPlay()));
+        return;
+    }
+
+    if( self->m_playedStampTimer.isActive() ) // eos before stamped, stamp now
+    {
+        self->m_playedStampTimer.stop();
+        self->slotStamp();
+    }
+
+    if (self->m_playingPlaylistFile) //Try next uri if exists
+    {
+        self->m_playlistNextTimer.start(0);
+    }
+    else
+    {
+        QTimer::singleShot(0, self, SLOT(playNext()));
+        Q_EMIT self->rendererEos();
+    }
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::restartPlay
+ * Slot to call asynchronously to restart playback (e.g. when internet radio disconnect due to network issues)
+ ********************************************************************/
+void MafwGstRenderer::restartPlay()
+{
+    //only restart if we're still playing
+    if( m_currentState == MafwRenderer::Playing )
+    {
+        doPlay(m_currentContent);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::readyStateCallback
+ * Worker informs via this when it is no longer using any resources when paused
+ ********************************************************************/
+void MafwGstRenderer::readyStateCallback(MafwGstRendererWorker *worker, gpointer owner)
+{
+    Q_UNUSED(worker);
+
+    MafwGstRenderer *self = static_cast<MafwGstRenderer*>(owner);
+
+    if( self->m_currentState != MafwRenderer::Paused )
+    {
+        qCritical("MafwGstRenderer: Ready state informed, but not in PAUSED state! Not releasing resources!");
+        return;
+    }
+
+    MafwRendererPolicy *policy = self->rendererPolicy();
+    if( policy )
+    {
+        policy->release();
+    }
+}
+
+//
+//Private implementation
+//
+
+/********************************************************************
+ * MafwGstRenderer::slotGetPosition
+ ********************************************************************/
+void MafwGstRenderer::slotGetPosition(QObject* resultsReceiver,
+                                      const char* resultsMember)
+{
+    QMetaMethod method;
+    bool methodFound;
+    gint pos;
+
+    if(m_currentState == MafwRenderer::Stopped)
+    {
+        pos = 0;
+    }
+    else if( m_haltState.isSet() )
+    {
+        pos = m_haltState.position();
+    }
+    else
+    {
+        /* this returns -1 on failure */
+        pos = mafw_gst_renderer_worker_get_position(m_worker);
+    }
+
+    if (pos < 0)
+    {
+        MafwError err;
+        err.setCode(MafwError::RendererError_CannotGetPosition);
+        Q_EMIT rendererError(err);
+    }
+    else
+    {
+        methodFound = MafwCallbackHelper::getCallbackMethod(resultsReceiver,
+                                                            resultsMember,
+                                                            method);
+
+        if (!methodFound ||
+            method.invoke(resultsReceiver, Q_ARG(uint, pos)) == false)
+        {
+            qCritical() << "Invoking the get position callback method failed!";
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::slotMafwProperty
+ ********************************************************************/
+void MafwGstRenderer::slotMafwProperty(const QString& name,
+                                       QObject* receiver,
+                                       const char* member)
+{
+
+    QVariant prop;
+    QMetaMethod method;
+    bool methodFound;
+
+    if (name == PROPERTY_VOLUME)
+    {
+        if (!m_volume)
+        {
+            m_volume = new MafwGstRendererVolume();
+            connect(m_volume, SIGNAL(volumeChanged(uint)), this, SLOT(handleVolumeChange(uint)));
+        }
+
+        uint value = m_volume->getVolume();
+        prop = QVariant(value);
+    }
+    else if (name == PROPERTY_DOLBY_STATE_MUSIC)
+    {
+        uint value = m_dolby->getMusicDolbyState();
+        prop = QVariant(value);
+    }
+    else if (name == PROPERTY_DOLBY_STATE_VIDEO)
+    {
+        uint value = m_dolby->getVideoDolbyState();
+        prop = QVariant(value);
+    }
+    else if (name == PROPERTY_AUTOPAINT)
+    {
+        gboolean value;
+        value = mafw_gst_renderer_worker_get_autopaint(m_worker);
+        prop = QVariant(value);
+    }
+    else if (name == PROPERTY_COLORKEY)
+    {
+        gint value;
+        value = mafw_gst_renderer_worker_get_colorkey(m_worker);
+        prop = QVariant(value);
+    }
+    else if (name == PROPERTY_XID)
+    {
+        XID value;
+        value = mafw_gst_renderer_worker_get_xid(m_worker);
+        prop = QVariant(static_cast<uint>(value));
+    }
+    else if (name == PROPERTY_PLAYBACK_SPEED)
+    {
+        gfloat value;
+        value = mafw_gst_renderer_worker_get_playback_speed(m_worker);
+        prop = QVariant(value);
+    }
+    else if (name == PROPERTY_FORCE_ASPECT_RATIO)
+    {
+        gboolean value;
+        value = mafw_gst_renderer_worker_get_force_aspect_ratio(m_worker);
+        prop = QVariant(value);
+    }
+    else if( name == PROPERTY_RENDER_RECT)
+    {
+        const render_rectangle *rect = mafw_gst_renderer_worker_get_render_rectangle(m_worker);
+        prop = QString("%1,%2,%3,%4")
+               .arg(rect->x).arg(rect->y).arg(rect->width).arg(rect->height);
+    }
+    else
+    {
+        qWarning() << "unknown property: " << name;
+    }
+
+    methodFound = MafwCallbackHelper::getCallbackMethod(receiver,
+                                                        member,
+                                                        method);
+
+    if (!methodFound || method.invoke(receiver,
+                                      Q_ARG(QString, name),
+                                      Q_ARG(QVariant, prop)) == false)
+    {
+        qCritical() << "Invoking the callback method failed!";
+    }
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::slotStamp
+ ********************************************************************/
+void MafwGstRenderer::slotStamp()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    QString uid=m_currentContent.uuid();
+    if( !uid.isEmpty() )
+    {
+        // create live node from MAFW object ID. Tracker case only implemented
+        // here. There definitely should be helper function for this.
+        const QString TRACKER_SOURCE_UUID = "MafwTrackerSource";
+        const QString MAFW_UUID_SEPARATOR = "::";
+
+        QString source = uid.section(MAFW_UUID_SEPARATOR, 0 , 0);
+
+        if ( source == TRACKER_SOURCE_UUID )
+        {
+            QString uniqueNodeIdentifier = uid.section(MAFW_UUID_SEPARATOR, 1, 1);
+            if (uniqueNodeIdentifier.length() > 0)
+            {
+                int counter = m_currentContent.firstMetaData(MAFW_METADATA_KEY_PLAY_COUNT).toInt();
+                counter++;
+                qDebug() << "MafwGstRenderer::slotStamp counter" << counter;
+                m_currentContent.appendMetaData(MAFW_METADATA_KEY_PLAY_COUNT, QList<QVariant>() << QVariant(counter));
+
+                int storedDuration = m_currentContent.firstMetaData(MAFW_METADATA_KEY_DURATION).toInt();
+                int currentDuration = mafw_gst_renderer_worker_get_duration(m_worker);
+                int stampDuration = -1;
+                if( currentDuration >= 0 && storedDuration != currentDuration )
+                {
+                    qDebug() << "Will store new duration:" << currentDuration;
+                    stampDuration = currentDuration;
+                    Q_EMIT(metadataChanged(MAFW_METADATA_KEY_DURATION, QList<QVariant>() << stampDuration));
+                }
+
+                stampIt(uniqueNodeIdentifier, counter, stampDuration);
+            }
+        }
+    }
+    else // UUID is unknown
+    {
+        const QUrl url = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
+
+        if( url.isValid() && url.toString().startsWith("file://") )
+        {
+            qDebug() << "MafwGstRenderer::slotStamp query from tracker" << url;
+
+            QSparqlQuery query(QString("SELECT ?urn ?usageCount ?duration WHERE { "
+                                       "?urn nie:url \"%1\". "
+                                       "OPTIONAL { "
+                                            "?urn nie:usageCounter ?usageCount. "
+                                            "?urn nfo:duration ?duration } "
+                                       "}")
+                               .arg(url.toEncoded().constData()));
+
+            delete m_urnQueryResult;
+            m_urnQueryResult = m_sparqlConnection->exec(query);
+            connect(m_urnQueryResult, SIGNAL(finished()),
+                    this, SLOT(slotStampQueryReady()));
+        }
+    }
+
+    m_playedStamped=true;
+}
+
+/********************************************************************
+ * MafwGstRenderer::slotStampQueryReady
+ ********************************************************************/
+void MafwGstRenderer::slotStampQueryReady()
+{
+    m_playedStampTryCounter++;
+    if( !m_urnQueryResult || m_urnQueryResult->hasError() || !m_urnQueryResult->first() )
+    {
+        qWarning() << "MafwGstRenderer::slotStampQueryReady: surprising result";
+        if (!m_playedStampTimer.isActive()
+            && m_currentState == MafwRenderer::Playing
+            && m_playedStampTryCounter < PLAYED_STAMP_TRIES)
+        {
+            qDebug() << __PRETTY_FUNCTION__ << "restarting timer.";
+            m_playedStampTimer.start(PLAYED_STAMP_INTERVAL);
+        }
+        else
+        {
+            qWarning() << __PRETTY_FUNCTION__ << "played stamping didn't succeeded.";
+            m_playedStamped = false;
+        }
+    }
+    else
+    {
+        QString urn = m_urnQueryResult->stringValue(0);
+        int usageCount = m_urnQueryResult->stringValue(1).toInt();
+        int storedDuration = m_urnQueryResult->stringValue(2).toInt();
+
+        int currentDuration = mafw_gst_renderer_worker_get_duration(m_worker);
+
+        int mediaDuration = -1;
+        if( storedDuration != currentDuration)
+        {
+            mediaDuration = currentDuration;
+            Q_EMIT(metadataChanged(MAFW_METADATA_KEY_DURATION, QList<QVariant>() << mediaDuration));
+        }
+
+        qDebug() << "MafwGstRenderer::slotStampQueryReady" << urn << usageCount << mediaDuration;
+
+        stampIt(urn, usageCount+1, mediaDuration);
+    }
+
+
+    delete m_urnQueryResult;
+    m_urnQueryResult = 0;
+}
+
+/********************************************************************
+ * MafwGstRenderer::stopTimers
+ ********************************************************************/
+void MafwGstRenderer::stopTimers()
+{
+    m_playlistNextTimer.stop();
+    if (m_playlistFileUtil)
+    {
+        m_playlistFileUtil->takePendingError();
+    }
+    m_playedStampTimer.stop();
+}
+
+/********************************************************************
+ * MafwGstRenderer::stampIt
+ ********************************************************************/
+void MafwGstRenderer::stampIt(const QString& urn, int usageCount, int mediaDuration)
+{
+    QString isoDate=QDateTime::currentDateTime().toUTC().toString(Qt::ISODate);
+    // Add UTC mark "Z" if it is missing (Qt behaviour has changed it seems to add it nowadays)
+    if( isoDate.length()==ISO_DATE_BASE_LENGTH )
+    {
+        isoDate.append("Z");
+    }
+
+    QSparqlQuery update;
+    if( mediaDuration > -1 )
+    {
+        update.setQuery(QString(
+                                " DELETE { <%1> nie:contentAccessed ?old } "
+                                " WHERE { <%1> nie:contentAccessed ?old } "
+                                " DELETE { <%1> nie:usageCounter ?oldu } "
+                                " WHERE { <%1> nie:usageCounter ?oldu } "
+                                " DELETE { <%1> nfo:duration ?oldd } "
+                                " WHERE { <%1> nfo:duration ?oldd } "
+                                " INSERT { <%1> nie:contentAccessed \"%2\" . "
+                                "         <%1> nie:usageCounter \"%3\" . "
+                                "         <%1> nfo:duration \"%4\" }")
+                                .arg(urn)
+                                .arg(isoDate)
+                                .arg(usageCount)
+                                .arg(mediaDuration));
+    }
+    else
+    {
+        update.setQuery(QString(
+                                "DELETE { <%1> nie:contentAccessed ?old } "
+                                " WHERE { <%1> nie:contentAccessed ?old } "
+                                "DELETE { <%1> nie:usageCounter ?oldu } "
+                                " WHERE { <%1> nie:usageCounter ?oldu } "
+                                "INSERT { <%1> nie:contentAccessed \"%2\" . "
+                                "         <%1> nie:usageCounter \"%3\"}")
+                                .arg(urn)
+                                .arg(isoDate)
+                                .arg(usageCount));
+    }
+
+    update.setType(QSparqlQuery::InsertStatement);
+
+
+    delete m_stampItResult;
+    m_stampItResult = m_sparqlConnection->exec(update);
+    connect(m_stampItResult, SIGNAL(finished()),
+            this, SLOT(slotStampItDone()));
+}
+
+/********************************************************************
+ * MafwGstRenderer::slotStampItDone()
+ ********************************************************************/
+void MafwGstRenderer::slotStampItDone()
+{
+    if( !m_stampItResult )
+    {
+        qWarning() << "Stampit cannot be done without stmapit result! Invalid slot call?";
+        return;
+    }
+
+    if( m_stampItResult->hasError() )
+    {
+        qWarning() << "Stampit failed:" << m_stampItResult->lastError().message();
+    }
+    delete m_stampItResult;
+    m_stampItResult = 0;
+}
+
+/********************************************************************
+ * MafwGstRenderer::slotRouteChanged()
+ ********************************************************************/
+void MafwGstRenderer::slotRouteChanged()
+{
+    QSet<int> set;
+    QString route;
+
+    // 1. add audio route(s) to the route set
+    route = m_audioRoute->value().toString();
+    qDebug() << "audio route is:" << route;
+    if (audioRouteMap().contains(route))
+    {
+        Q_FOREACH (int value, audioRouteMap().value(route))
+        {
+            set.insert(value);
+        }
+    }
+    else
+    {
+        // TODO: Is it ok to use NULL here?
+        qWarning() << "adding null route (audio)";
+        set.insert(WORKER_OUTPUT_NULL);
+    }
+
+    // 2. add video route(s) to the route set
+    route = m_videoRoute->value().toString();
+    qDebug() << "video route is:" << route;
+    if (videoRouteMap().contains(route))
+    {
+        Q_FOREACH (int value, videoRouteMap().value(route))
+        {
+            set.insert(value);
+        }
+    }
+    else
+    {
+        // TODO: Is it ok to use NULL here?
+        qWarning() << "adding null route (video)";
+        set.insert(WORKER_OUTPUT_NULL);
+    }
+
+    // 3. finally notify the worker about the current routes
+    GSList *destinations = NULL;
+    Q_FOREACH (int value, set)
+    {
+        destinations = g_slist_append(destinations, GINT_TO_POINTER(value));
+    }
+    mafw_gst_renderer_worker_notify_media_destination(this->m_worker,
+                                                      destinations);
+    g_slist_free(destinations);
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::playURI
+ ********************************************************************/
+void MafwGstRenderer::playURI(const QString& uri)
+{
+    m_playedStamped = false;
+    m_playedStampTryCounter = 0;
+
+    //little hack to get pause-to-play transition to be signalled
+    //correctly, in case different URI is asked to be played.
+    //So it's not resume transition
+    m_currentState = MafwRenderer::Stopped;
+    mafw_gst_renderer_worker_play(m_worker, uri.toAscii().constData());
+    m_nextContent = MafwMediaInfo();
+}
+
+/********************************************************************
+ * MafwGstRenderer::startPlayingPlaylistFile
+ ********************************************************************/
+void MafwGstRenderer::startPlayingPlaylistFile()
+{
+    m_playlistNextTimer.stop();
+    QString uri = QString();
+    if (m_playlistFileUtil)
+    {
+        uri = m_playlistFileUtil->takeFirstUri();
+        m_playlistFileUtil->takePendingError();
+    }
+    else
+    {
+        qCritical() << __PRETTY_FUNCTION__ << "playlist file util is NULL!";
+    }
+
+    if (!uri.isEmpty())
+    {
+        qDebug() << __PRETTY_FUNCTION__ << uri;
+
+        if( !m_mmcMonitor->isMounted() && uri.startsWith( MafwMmcMonitor::MMC_URI_PREFIX ) )
+        {
+            qDebug() << "MafwGstRenderer::startPlayingPlaylistFile: Can't play MMC not mounted";
+            MafwError mafwError(MafwError::RendererError_MmcNotAvailable, uri);
+            Q_EMIT rendererError(mafwError);
+            return;
+        }
+
+        m_playingPlaylistFile = true;
+        mafw_gst_renderer_worker_play(m_worker, uri.toAscii().constData());
+        QList<QVariant> metadataValue;
+        metadataValue << uri;
+        Q_EMIT metadataChanged(MAFW_METADATA_KEY_URI, metadataValue);
+    }
+    else
+    {
+        MafwError err;
+        err.setCode(MafwError::RendererError_PlaylistParsing);
+        Q_EMIT rendererError(err);
+    }
+}
+
+
+/********************************************************************
+ * MafwGstRenderer::handlePlaylistFileParsingErrors
+ ********************************************************************/
+void MafwGstRenderer::handlePlaylistFileParsingErrors(bool succeeded)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (!succeeded)
+    {
+        if (m_unsupportedTypeError)
+        {
+            errorCallback(m_worker, this, m_unsupportedTypeError);
+            g_error_free(m_unsupportedTypeError);
+            m_unsupportedTypeError = 0;
+        }
+        else
+        {
+        MafwError err;
+        err.setCode(MafwError::RendererError_PlaylistParsing);
+        Q_EMIT rendererError(err);
+        }
+    }
+    else if (!m_playingPlaylistFile)
+    {
+        qDebug() << __PRETTY_FUNCTION__ << "waiting for playlist file items...";
+        MafwError err;
+        err.setCode(MafwError::RendererError_NoPlaylist);
+        m_playlistFileUtil->setPendingError(err);
+        m_playlistNextTimer.start(1000);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::playNext
+ ********************************************************************/
+void MafwGstRenderer::playNext()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    m_playingPlaylistFile = false;
+    m_playedPlaylistItem = false;
+
+    //Preserve m_currentContent for keeping usage count up if the same item is
+    //played again.
+    if( !m_nextContent.uuid().isEmpty() && (m_nextContent.uuid() == m_currentContent.uuid()) )
+    {
+        m_nextContent = m_currentContent;
+    }
+
+    const QUrl nextURI = m_nextContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
+    if( !nextURI.isEmpty() )
+    {
+        m_playingItem = MafwBasicRenderer::NextUri;
+        m_currentContent = m_nextContent;
+        m_nextContent = MafwMediaInfo();
+
+        playURI(nextURI.toEncoded());
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::playNextURIFromPlaylist
+ ********************************************************************/
+void MafwGstRenderer::playNextURIFromPlaylist()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    QString uri = m_playlistFileUtil->takeFirstUri();
+
+    bool okToPlay=true;
+    if(uri.isEmpty())
+    {
+        okToPlay=false;
+    }
+    else if( !m_mmcMonitor->isMounted() && uri.startsWith( MafwMmcMonitor::MMC_URI_PREFIX ) )
+    {
+        qDebug() << "MafwGstRenderer::playNextURIFromPlaylist: Can't play MMC not mounted";
+        MafwError mafwError(MafwError::RendererError_MmcNotAvailable, uri);
+        m_playlistFileUtil->setPendingError( mafwError );
+        okToPlay=false;
+    }
+
+    if (okToPlay)
+    {
+        m_playlistFileUtil->takePendingError(); // clear it, we have a new candidate
+        qDebug() << "Trying next uri: " << uri;
+        mafw_gst_renderer_worker_play(m_worker, uri.toAscii().constData());
+        QList<QVariant> metadataValue;
+        metadataValue << uri;
+        Q_EMIT metadataChanged(MAFW_METADATA_KEY_URI, metadataValue);
+    }
+    else
+    {
+        m_playingPlaylistFile = false;
+
+        if (m_playedPlaylistItem)
+        {
+            Q_EMIT rendererEos();
+        }
+        m_playedPlaylistItem = false;
+
+
+        MafwError mafwError = m_playlistFileUtil->takePendingError();
+        if ( mafwError.code() != MafwError::NoError)
+        {
+            Q_EMIT rendererError(mafwError);
+            doStop();
+            MafwRendererPolicy *policy = rendererPolicy();
+            if( policy )
+            {
+                policy->release();
+            }
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::slotCurrentMediaInfo
+ ********************************************************************/
+void MafwGstRenderer::slotGetCurrentMediaInfo(QObject* receiver, const char* member, const QString& metadataKey)
+{
+    MafwMediaInfo info(m_currentContent.uuid());
+
+    //get all metadata
+    if(metadataKey.isEmpty())
+    {
+        info.setMetaData(m_currentMetaData);
+    }
+    //get one item
+    else
+    {
+        QMap<QString, QList<QVariant> >::const_iterator iter = m_currentMetaData.find(metadataKey);
+        if (iter != m_currentMetaData.end())
+        {
+            info.appendMetaData(iter.key(), iter.value());
+        }
+    }
+
+    sendMediaInfo(info, receiver, member);
+}
+
+/********************************************************************
+ * MafwGstRenderer::handleVolumeChange
+ ********************************************************************/
+void MafwGstRenderer::handleVolumeChange(uint level)
+{
+    qDebug() << "MafwGstRenderer::handleVolumeChange: " << level;
+    Q_EMIT mafwPropertyChanged(PROPERTY_VOLUME, level);
+}
+
+/********************************************************************
+ * MafwGstRenderer::stopStreaming
+ ********************************************************************/
+void MafwGstRenderer::stopStreaming()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    if( mafw_gst_renderer_worker_get_streaming(m_worker) )
+    {
+        mafw_gst_renderer_worker_stop(m_worker);
+        stopTimers();
+    }
+
+    // emit error and stop for real, only if no valid halt state is set
+    if( !m_haltState.isSet() )
+    {
+        doStop();
+        MafwError error;
+        error.setCode(MafwError::RendererError_StreamDisconnected);
+        Q_EMIT rendererError(error);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::haltStreaming
+ ********************************************************************/
+void MafwGstRenderer::haltStreaming()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    if( mafw_gst_renderer_worker_get_streaming(m_worker) )
+    {
+        QString uri;
+        if( m_playlistNextTimer.isActive() )
+        {
+            uri = m_playlistFileUtil->takeFirstUri();
+        }
+        else
+        {
+            uri = mafw_gst_renderer_worker_get_uri(m_worker);
+        }
+
+        int position = -1;
+        if( mafw_gst_renderer_worker_get_seekable(m_worker) )
+        {
+            position = mafw_gst_renderer_worker_get_position(m_worker);
+            if( position < 0 )
+            {
+                qWarning() << "Cannot resume to correct position after networkchange!";
+            }
+        }
+
+        //make sure we've uri to resume, the playlist parser may have been trying to parse something
+        if( uri.length() > 0 )
+        {
+            m_haltState = MafwGstRendererHaltState(uri, m_currentState, position);
+            //valid haltstate constructed, clear the possible pending error in playlist handling
+            if( m_playlistFileUtil )
+            {
+                m_playlistFileUtil->takePendingError();
+            }
+        }
+        else
+        {
+            //just in case
+            m_haltState.clear();
+        }
+
+        //now actually stop, and depending on the haltstate validity it will also emit error
+        stopStreaming();
+    }
+    else
+    {
+        qDebug() << "Not streaming!";
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::continueStreaming
+ ********************************************************************/
+void MafwGstRenderer::continueStreaming()
+{
+    if( mafw_gst_renderer_worker_get_streaming(m_worker) || m_haltState.isSet() )
+    {
+        //if not yet halted, do it now
+        if( !m_haltState.isSet() )
+        {
+            haltStreaming();
+        }
+
+        m_playingItem = MafwBasicRenderer::CurrentUri;
+
+        if( m_haltState.state() == MafwRenderer::Playing )
+        {
+            mafw_gst_renderer_worker_play(m_worker, m_haltState.uri().toAscii().constData());
+            int pausePos = m_haltState.position() > 0 ? m_haltState.position() : 0;
+
+            if( m_haltState.state() == MafwRenderer::Playing && pausePos > 0 )
+            {
+                qDebug() << "Resuming streaming from position: " << m_haltState.position();
+                doSeek(m_haltState.position(), MafwRenderer::SeekAbsolute);
+            }
+            m_haltState.clear();
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::handlePropertyChanged
+ ********************************************************************/
+void MafwGstRenderer::handlePropertyChanged(const QString& name,
+                                            const QVariant& value)
+{
+    // This is a way to check if the policy is on. We need to set the
+    // PAUSED-to-READY timeout to zero, since we need to be sure that the
+    // resources really get released by the GStreamer.  It is unfortunate that
+    // a doPause() and PAUSED state is not enough, e.g. in case of XVideo.
+    if (name == MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE)
+    {
+        guint timeout;
+        if (value.toBool() == true)
+        {
+            timeout = 0;
+        }
+        else
+        {
+            timeout = MAFW_GST_RENDERER_WORKER_READY_TIMEOUT;
+        }
+        mafw_gst_renderer_worker_set_ready_timeout(m_worker, timeout);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::handleDHMMusicPropertyChanged
+ ********************************************************************/
+void MafwGstRenderer::handleDHMMusicPropertyChanged()
+{
+    if (m_worker)
+    {
+        qDebug() << "MafwGstRenderer::handleDHMMusicPropertyChanged set_dolby_music_property" << m_dolby->getMusicDolbyState();
+        set_dolby_music_property(m_worker, m_dolby->getMusicDolbyState());
+        set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyRoom(), TRUE);
+        set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyColor(), FALSE);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::handleDHMVideoPropertyChanged
+ ********************************************************************/
+void MafwGstRenderer::handleDHMVideoPropertyChanged()
+{
+    if (m_worker)
+    {
+        qDebug() << "MafwGstRenderer::handleDHMVideoPropertyChanged set_dolby_video_property" << m_dolby->getVideoDolbyState();
+        set_dolby_video_property(m_worker, m_dolby->getVideoDolbyState());
+        set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyRoom(), TRUE);
+        set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyColor(), FALSE);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::handleScreenshot
+ ********************************************************************/
+void MafwGstRenderer::handleScreenshot(char *location, GError *error)
+{
+    if(!error)
+    {
+        QList<QVariant> results;
+        results << location;
+
+        QString mafwMetadataKey = MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI;
+
+        appendRelatedMetadata(mafwMetadataKey, &results);
+        Q_EMIT metadataChanged(mafwMetadataKey, results);
+        m_currentMetaData.insert(mafwMetadataKey, results);
+    }
+    else
+    {
+        qCritical() << error->message;
+    }
+
+    m_worker->taking_screenshot = FALSE;
+}
+
+/********************************************************************
+ * MafwGstRenderer::cancelScreenshot
+ ********************************************************************/
+void MafwGstRenderer::cancelScreenshot()
+{
+    if(m_worker)
+    {
+        m_worker->taking_screenshot = FALSE;
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::sendMediaInfo
+ ********************************************************************/
+void MafwGstRenderer::sendMediaInfo(const MafwMediaInfo& info, QObject* receiver, const char* member)
+{
+    QMetaMethod method;
+    bool methodFound;
+
+    methodFound = MafwCallbackHelper::getCallbackMethod(receiver, member, method);
+
+    if (!methodFound)
+    {
+        MafwError err;
+        err.setCode(MafwError::CallbackSlotNotFound);
+        Q_EMIT error(err);
+    }
+    //actual result callback call is inside this if()
+    else if( !method.invoke(receiver, Q_ARG(MafwMediaInfo, info)) )
+    {
+        MafwError err;
+        err.setCode(MafwError::CallbackCouldNotInvoke);
+        Q_EMIT error(err);
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::mmcPreUnmount
+ ********************************************************************/
+void MafwGstRenderer::mmcPreUnmount()
+{
+    qDebug() << "MafwGstRenderer::mmcPreUnmount" << m_currentState;
+
+    if( m_currentState!=MafwRenderer::Stopped )
+    {
+        const QUrl url = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
+        if( url.toString().startsWith(MafwMmcMonitor::MMC_URI_PREFIX) )
+        {
+            qDebug() << "MafwGstRenderer::mmcPreUnmount: playing from MMC, going to stop";
+            doStop();
+            MafwError mafwError(MafwError::RendererError_MmcNotAvailable, url.toEncoded());
+            Q_EMIT rendererError(mafwError);
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::connectNameOwnerChanged
+ ********************************************************************/
+bool MafwGstRenderer::connectNameOwnerChanged()
+{
+    QStringList argumentMatch;
+    argumentMatch << DBUS_NAME_PCFD;
+
+    QDBusConnection connection = QDBusConnection::systemBus();
+    return connection.connect( QString(),
+                                 QString(),
+                                 DBUS_INTERFACE_DBUS,
+                                 DBUS_SIGNAL_NAME_OWNER_CHANGED,
+                                 argumentMatch,
+                                 QString(),
+                                 this,
+                                 SLOT(handleContextProviderRemoval(QDBusMessage) ) );
+}
+
+/********************************************************************
+ * MafwGstRenderer::handleContextProviderRemoval
+ ********************************************************************/
+void MafwGstRenderer::handleContextProviderRemoval( const QDBusMessage& message )
+{
+    QList<QVariant> arguments;
+    QString name;
+    QString oldName;
+    QString newName;
+
+    arguments= message.arguments();
+
+    if ( message.type() == QDBusMessage::SignalMessage && arguments.size()==3 )
+    {
+
+        name = arguments.at(0).toString();
+        oldName = arguments.at(1).toString();
+        newName = arguments.at(2).toString();
+
+        if ( oldName.length() && newName.length()==0 )
+        {
+            qDebug() << "MafwGstRenderer::handleContextProviderRemoval context provider died";
+
+            // add null output
+            GSList *destinations = NULL;
+            destinations = g_slist_append(destinations,
+                                          GINT_TO_POINTER(WORKER_OUTPUT_NULL));
+            mafw_gst_renderer_worker_notify_media_destination(this->m_worker,
+                                                              destinations);
+            g_slist_free(destinations);
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRenderer::handleResolutionError
+ ********************************************************************/
+void MafwGstRenderer::handleResolutionError(MafwError &error)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    const QUrl url = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
+    MafwError::Code errorCode = MafwError::RendererError_UnsuppertedType;
+
+    if( url.isValid() && url.toString().startsWith("file://") )
+    {
+        qDebug() << __PRETTY_FUNCTION__ << url;
+
+        QSparqlQuery query(QString("SELECT ?height ?width WHERE { "
+                                   "?_u nie:url \"%1\" ."
+                                   "?_u nfo:height ?height . "
+                                   "?_u nfo:width ?width }")
+                           .arg(QString(url.toEncoded())));
+
+        QSparqlResult *result = m_sparqlConnection->syncExec(query);
+
+        if( result->hasError() )
+        {
+            qWarning() << __PRETTY_FUNCTION__ << " surprising result";
+            qWarning() << result->lastError().message();
+        }
+        else if( result->first() )
+        {
+            int height = result->stringValue(0).toInt();
+            int width = result->stringValue(1).toInt();
+
+            if (height > MAX_SUPPORTED_HEIGHT || width > MAX_SUPPORTED_WIDTH)
+            {
+                errorCode = MafwError::RendererError_UnsupportedResolution;
+            }
+        }
+        delete result;
+    }
+    error.setCode(errorCode);
+}
+
+/********************************************************************
+ * MafwGstRenderer::setConfiguration
+ ********************************************************************/
+void MafwGstRenderer::setConfiguration(QSettings *settings)
+{
+    //if no settings use "factory" configuration
+    if( !settings )
+    {
+        return;
+    }
+
+    configuration *defaultconfig = mafw_gst_renderer_worker_create_default_configuration(m_worker);
+
+    //pipeline settings
+    settings->beginGroup("pipeline");
+    QVariant value = readSettingsValue(settings, "audio-sink", defaultconfig->asink);
+    qFree(defaultconfig->asink);
+    defaultconfig->asink = g_strdup(value.toString().toAscii());
+
+    value = readSettingsValue(settings, "video-sink", defaultconfig->vsink);
+    qFree(defaultconfig->vsink);
+    defaultconfig->vsink = g_strdup(value.toString().toAscii());
+
+    value = readSettingsValue(settings, "flags", defaultconfig->flags);
+    defaultconfig->flags = value.toInt();
+
+    value = readSettingsValue(settings, "use_dhmmixer", defaultconfig->use_dhmmixer);
+    defaultconfig->use_dhmmixer = value.toBool();
+
+    value = readSettingsValue(settings, "buffer-time", defaultconfig->buffer_time);
+    defaultconfig->buffer_time = value.toULongLong();
+
+    value = readSettingsValue(settings, "latency-time", defaultconfig->latency_time);
+    defaultconfig->latency_time = value.toULongLong();
+
+    value = readSettingsValue(settings, "autoload_subtitles", defaultconfig->autoload_subtitles);
+    defaultconfig->autoload_subtitles = value.toBool();
+
+    value = readSettingsValue(settings, "subtitle_encoding", defaultconfig->subtitle_encoding);
+    qFree(defaultconfig->subtitle_encoding);
+    defaultconfig->subtitle_encoding = g_strdup(value.toString().toAscii());
+
+    value = readSettingsValue(settings, "subtitle_font", defaultconfig->subtitle_font);
+    qFree(defaultconfig->subtitle_font);
+    defaultconfig->subtitle_font = g_strdup(value.toString().toAscii());
+    settings->endGroup();
+
+    //timers
+    settings->beginGroup("timers");
+    value = readSettingsValue(settings, "pause-frame", defaultconfig->milliseconds_to_pause_frame);
+    defaultconfig->milliseconds_to_pause_frame = value.toUInt();
+
+    value = readSettingsValue(settings, "pause-to-ready", defaultconfig->seconds_to_pause_to_ready);
+    defaultconfig->seconds_to_pause_to_ready = value.toUInt();
+    settings->endGroup();
+
+    //dhmmixer
+    settings->beginGroup("dhmmixer");
+    value = readSettingsValue(settings, "dhm-music-surround", defaultconfig->mobile_surround_music.state);
+    defaultconfig->mobile_surround_music.state = value.toUInt();
+
+    value = readSettingsValue(settings, "dhm-music-color", defaultconfig->mobile_surround_music.color);
+    defaultconfig->mobile_surround_music.color = value.toInt();
+
+    value = readSettingsValue(settings, "dhm-music-room-size", defaultconfig->mobile_surround_music.room);
+    defaultconfig->mobile_surround_music.room = value.toInt();
+
+    value = readSettingsValue(settings, "dhm-video-surround", defaultconfig->mobile_surround_video.state);
+    defaultconfig->mobile_surround_video.state = value.toUInt();
+
+    value = readSettingsValue(settings, "dhm-video-color", defaultconfig->mobile_surround_video.color);
+    defaultconfig->mobile_surround_video.color = value.toInt();
+
+    value = readSettingsValue(settings, "dhm-video-room-size", defaultconfig->mobile_surround_video.room);
+    defaultconfig->mobile_surround_video.room = value.toInt();
+    settings->endGroup();
+
+    mafw_gst_renderer_worker_set_configuration(m_worker, defaultconfig);
+}
+
+/********************************************************************
+ * MafwGstRenderer::readSettingsValue
+ ********************************************************************/
+QVariant MafwGstRenderer::readSettingsValue(QSettings *settings,
+                                            const QString &valueName,
+                                            const QVariant &defaultValue) const
+{
+    QVariant value = settings->value(valueName, defaultValue);
+    if( !settings->contains(valueName) )
+    {
+        qWarning() << "No value for: (" << valueName << ") in configuration file! Using factory default";
+    }
+    return value;
+}
+
+/********************************************************************
+ * MafwGstRenderer::errorMap
+ ********************************************************************/
+const QHash<int, MafwError::Code>& MafwGstRenderer::errorMap()
+{
+
+    static QHash<int, MafwError::Code> map;
+
+    if (map.isEmpty())
+    {
+        /* initialize error map */
+        map[WORKER_ERROR_PLAYBACK] =
+            MafwError::RendererError_Playback;
+        map[WORKER_ERROR_VIDEO_CODEC_NOT_FOUND] =
+            MafwError::RendererError_VideoCodeNotFound;
+        map[WORKER_ERROR_AUDIO_CODEC_NOT_FOUND] =
+            MafwError::RendererError_AudioCodecNotFound;
+        map[WORKER_ERROR_CODEC_NOT_FOUND] =
+            MafwError::RendererError_CodecNotFound;
+        map[WORKER_ERROR_UNSUPPORTED_TYPE] =
+            MafwError::RendererError_UnsuppertedType;
+        map[WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE] =
+            MafwError::RendererError_UnsuppertedType;
+        map[WORKER_ERROR_UNABLE_TO_PERFORM] =
+            MafwError::RendererError_UnableToPerform;
+        map[WORKER_ERROR_CANNOT_SET_POSITION] =
+            MafwError::RendererError_CannotSetPosition;
+        map[WORKER_ERROR_PLAYLIST_PARSING] =
+            MafwError::RendererError_PlaylistParsing;
+        map[WORKER_ERROR_DRM_NO_LICENSE] =
+            MafwError::RendererError_DRMNoLicense;
+        map[WORKER_ERROR_DRM_NOT_ALLOWED] =
+            MafwError::RendererError_DRMNotAllowed;
+        map[WORKER_ERROR_DRM_OTHER] =
+            MafwError::RendererError_DRMOther;
+        map[WORKER_ERROR_STREAM_DISCONNECTED] =
+            MafwError::RendererError_StreamDisconnected;
+        map[WORKER_ERROR_INVALID_URI] =
+            MafwError::RendererError_InvalidURI;
+        map[WORKER_ERROR_MEDIA_NOT_FOUND] =
+            MafwError::RendererError_MediaNotFound;
+        map[WORKER_ERROR_CORRUPTED_FILE] =
+            MafwError::RendererError_CorruptedFile;
+        map[WORKER_ERROR_TYPE_NOT_AVAILABLE] =
+            MafwError::RendererError_TypeNotAvailable;
+    }
+
+    return map;
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::metadataMap
+ ********************************************************************/
+const QHash<int, QString>& MafwGstRenderer::metadataMap()
+{
+
+    static QHash<int, QString> map;
+
+    if (map.isEmpty())
+    {
+        /* initialize metadata key map */
+        map[WORKER_METADATA_KEY_TITLE] =
+            MAFW_METADATA_KEY_TITLE;
+        map[WORKER_METADATA_KEY_ARTIST] =
+            MAFW_METADATA_KEY_ARTIST;
+        map[WORKER_METADATA_KEY_AUDIO_CODEC] =
+            MAFW_METADATA_KEY_AUDIO_CODEC;
+        map[WORKER_METADATA_KEY_VIDEO_CODEC] =
+            MAFW_METADATA_KEY_VIDEO_CODEC;
+        map[WORKER_METADATA_KEY_BITRATE] =
+            MAFW_METADATA_KEY_BITRATE;
+        map[WORKER_METADATA_KEY_ENCODING] =
+            MAFW_METADATA_KEY_ENCODING;
+        map[WORKER_METADATA_KEY_ALBUM] =
+            MAFW_METADATA_KEY_ALBUM;
+        map[WORKER_METADATA_KEY_GENRE] =
+            MAFW_METADATA_KEY_GENRE;
+        map[WORKER_METADATA_KEY_TRACK] =
+            MAFW_METADATA_KEY_TRACK;
+        map[WORKER_METADATA_KEY_ORGANIZATION] =
+            MAFW_METADATA_KEY_ORGANIZATION;
+        map[WORKER_METADATA_KEY_RENDERER_ART_URI] =
+            MAFW_METADATA_KEY_RENDERER_ART_URI;
+        map[WORKER_METADATA_KEY_RES_X] =
+            MAFW_METADATA_KEY_RES_X;
+        map[WORKER_METADATA_KEY_RES_Y] =
+            MAFW_METADATA_KEY_RES_Y;
+        map[WORKER_METADATA_KEY_VIDEO_FRAMERATE] =
+            MAFW_METADATA_KEY_VIDEO_FRAMERATE;
+        map[WORKER_METADATA_KEY_DURATION] =
+            MAFW_METADATA_KEY_DURATION;
+        map[WORKER_METADATA_KEY_IS_SEEKABLE] =
+            MAFW_METADATA_KEY_IS_SEEKABLE;
+        map[WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI] =
+            MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI;
+        map[WORKER_METADATA_KEY_URI] =
+            MAFW_METADATA_KEY_URI;
+    }
+
+    return map;
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::audioRouteMap
+ ********************************************************************/
+const QHash<QString, QList<int> >& MafwGstRenderer::audioRouteMap()
+{
+
+    static QHash<QString, QList<int> > map;
+
+    if (map.isEmpty())
+    {
+        map[AUDIO_ROUTE_NULL]               = QList<int>() << WORKER_OUTPUT_NULL;
+        map[AUDIO_ROUTE_IHF]                = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS;
+        map[AUDIO_ROUTE_FMRADIO]            = QList<int>() << WORKER_OUTPUT_FM_RADIO;
+        map[AUDIO_ROUTE_IHF_AND_FMRADIO]    = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_FM_RADIO;
+
+        // earpiece is intentionally handled as builtdin speaker, well it kinda is
+        map[AUDIO_ROUTE_EARPIECE]           = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS;
+        map[AUDIO_ROUTE_EARPIECE_AND_TVOUT] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_TVOUT;
+
+        map[AUDIO_ROUTE_TV_OUT]             = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK;
+        map[AUDIO_ROUTE_IHF_AND_TV_OUT]     = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_TVOUT;
+        map[AUDIO_ROUTE_HEADPHONE]          = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK;
+        map[AUDIO_ROUTE_HEADSET]            = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK;
+        map[AUDIO_ROUTE_BTHSP]              = QList<int>() << WORKER_OUTPUT_BLUETOOTH_AUDIO;
+        map[AUDIO_ROUTE_BTA2DP]             = QList<int>() << WORKER_OUTPUT_BLUETOOTH_AUDIO;
+        map[AUDIO_ROUTE_IHF_AND_HEADSET]    = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_HEADPHONE_JACK;
+        map[AUDIO_ROUTE_IHF_AND_HEADPHONE]  = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_HEADPHONE_JACK;
+        map[AUDIO_ROUTE_IHF_AND_BTHSP]      = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_BLUETOOTH_AUDIO;
+        map[AUDIO_ROUTE_TV_OUT_AND_BTHSP]   = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK << WORKER_OUTPUT_BLUETOOTH_AUDIO;
+        map[AUDIO_ROUTE_TV_OUT_AND_BTA2DP]  = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK << WORKER_OUTPUT_BLUETOOTH_AUDIO;
+    }
+
+    return map;
+
+}
+
+/********************************************************************
+ * MafwGstRenderer::videoRouteMap
+ ********************************************************************/
+const QHash<QString, QList<int> >& MafwGstRenderer::videoRouteMap()
+{
+
+    static QHash<QString, QList<int> > map;
+
+    if (map.isEmpty())
+    {
+        map[VIDEO_ROUTE_TV_OUT]              = QList<int>() << WORKER_OUTPUT_TVOUT;
+        map[VIDEO_ROUTE_BUILT_IN]            = QList<int>() << WORKER_OUTPUT_BUILTIN_DISPLAY;
+        map[VIDEO_ROUTE_BUILT_IN_AND_TV_OUT] = QList<int>() << WORKER_OUTPUT_BUILTIN_DISPLAY << WORKER_OUTPUT_TVOUT;
+    }
+
+    return map;
+
+}
+
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstRendererDolby.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstRendererDolby.cpp
new file mode 100644 (file)
index 0000000..91a6fa0
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwGstRendererDolby.h"
+
+#include <QDebug>
+
+const int DEFAULT_COLOR = 2;
+const int DEFAULT_ROOM_SIZE = 2;
+const int MAX_VALUE = 4;
+
+enum MafwDolbyStates
+{
+    MafwDolbyOff,
+    MafwDolbyOn,
+    MafwDolbyAuto
+};
+
+MafwGstRendererDolby::MafwGstRendererDolby( QObject* parent ):
+        QObject(parent),
+        m_dolbyConfMusic(0),
+        m_dolbyConfMusicRoom(0),
+        m_dolbyConfMusicColor(0),
+        m_dolbyConfVideo(0),
+        m_dolbyConfVideoRoom(0),
+        m_dolbyConfVideoColor(0)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    m_currentMusicDolbyState = MafwDolbyOff;
+    m_currentMusicDolbyRoom = DEFAULT_ROOM_SIZE;
+    m_currentMusicDolbyColor = DEFAULT_COLOR;
+    m_currentVideoDolbyState = MafwDolbyOff;
+    m_currentVideoDolbyRoom = DEFAULT_ROOM_SIZE;
+    m_currentVideoDolbyColor = DEFAULT_COLOR;
+}
+
+void MafwGstRendererDolby::initialize()
+{
+    if (!m_dolbyConfMusic)
+    {
+        m_dolbyConfMusic = new GConfItem("/apps/Multimedia/music/dolbyConf", this);
+    }
+    if (!m_dolbyConfMusicRoom)
+    {
+        m_dolbyConfMusicRoom = new GConfItem("/apps/Multimedia/music/dolbyConfRoom", this);
+    }
+    if (!m_dolbyConfMusicColor)
+    {
+        m_dolbyConfMusicColor = new GConfItem("/apps/Multimedia/music/dolbyConfColor", this);
+    }
+    if (!m_dolbyConfVideo)
+    {
+        m_dolbyConfVideo = new GConfItem("/apps/Multimedia/video/dolbyConf", this);
+    }
+    if (!m_dolbyConfVideoRoom)
+    {
+        m_dolbyConfVideoRoom = new GConfItem("/apps/Multimedia/video/dolbyConfRoom", this);
+    }
+    if (!m_dolbyConfVideoColor)
+    {
+        m_dolbyConfVideoColor = new GConfItem("/apps/Multimedia/video/dolbyConfColor", this);
+    }
+    if (!m_dolbyConfMusic->value().toString().isEmpty())
+    {
+        valueMusicChanged();
+        connect(m_dolbyConfMusic, SIGNAL(valueChanged()), this, SLOT(valueMusicChanged()));
+        connect(m_dolbyConfMusicRoom, SIGNAL(valueChanged()), this, SLOT(valueMusicChanged()));
+        connect(m_dolbyConfMusicColor, SIGNAL(valueChanged()), this, SLOT(valueMusicChanged()));
+    }
+    if (!m_dolbyConfVideo->value().toString().isEmpty())
+    {
+        valueVideoChanged();
+        connect(m_dolbyConfVideo, SIGNAL(valueChanged()), this, SLOT(valueVideoChanged()));
+        connect(m_dolbyConfVideoRoom, SIGNAL(valueChanged()), this, SLOT(valueVideoChanged()));
+        connect(m_dolbyConfVideoColor, SIGNAL(valueChanged()), this, SLOT(valueVideoChanged()));
+    }
+}
+
+MafwGstRendererDolby::~MafwGstRendererDolby()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+}
+
+bool MafwGstRendererDolby::setMusicDolbyState (uint value)
+{
+    qDebug() << __PRETTY_FUNCTION__ << value;
+    if ( value <= MafwDolbyAuto)
+    {
+        m_currentMusicDolbyState = value;
+        m_dolbyConfMusic->set(m_currentMusicDolbyState);
+        return true;
+    }
+    else
+    {
+        m_currentMusicDolbyState = MafwDolbyOff;
+        m_dolbyConfMusic->set(m_currentMusicDolbyState);
+        return false;
+    }
+}
+
+bool MafwGstRendererDolby::setMusicDolbyRoom (int value)
+{
+    qDebug() << __PRETTY_FUNCTION__ << value;
+    if ( value < 0)
+    {
+        m_currentMusicDolbyRoom = 0;
+        m_dolbyConfMusicRoom->set(m_currentMusicDolbyRoom);
+    }
+    else if ( value > MAX_VALUE)
+    {
+        m_currentMusicDolbyRoom = MAX_VALUE;
+        m_dolbyConfMusicRoom->set(m_currentMusicDolbyRoom);
+    }
+    else
+    {
+        m_currentMusicDolbyRoom = value;
+        m_dolbyConfMusicRoom->set(m_currentMusicDolbyRoom);
+    }
+    return true;
+}
+
+bool MafwGstRendererDolby::setMusicDolbyColor (int value)
+{
+    qDebug() << __PRETTY_FUNCTION__ << value;
+    if ( value < 0)
+    {
+        m_currentMusicDolbyColor = 0;
+        m_dolbyConfMusicColor->set(m_currentMusicDolbyColor);
+    }
+    else if ( value > MAX_VALUE)
+    {
+        m_currentMusicDolbyColor = MAX_VALUE;
+        m_dolbyConfMusicColor->set(m_currentMusicDolbyColor);
+    }
+    else
+    {
+        m_currentMusicDolbyColor = value;
+        m_dolbyConfMusicColor->set(m_currentMusicDolbyColor);
+    }
+    return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyState (uint value)
+{
+    qDebug() << __PRETTY_FUNCTION__ << value;
+    if ( value <= MafwDolbyAuto)
+    {
+        m_currentVideoDolbyState = value;
+        m_dolbyConfVideo->set(int(m_currentVideoDolbyState));
+        return true;
+    }
+    else
+    {
+        m_currentVideoDolbyState = MafwDolbyOff;
+        m_dolbyConfVideo->set(int(m_currentVideoDolbyState));
+        return false;
+    }
+}
+
+bool MafwGstRendererDolby::setVideoDolbyRoom (int value)
+{
+    qDebug() << __PRETTY_FUNCTION__ << value;
+    if ( value < 0)
+    {
+        m_currentVideoDolbyRoom = 0;
+        m_dolbyConfVideoRoom->set(m_currentVideoDolbyRoom);
+    }
+    else if ( value > MAX_VALUE)
+    {
+        m_currentVideoDolbyRoom = MAX_VALUE;
+        m_dolbyConfVideoRoom->set(m_currentVideoDolbyRoom);
+    }
+    else
+    {
+        m_currentVideoDolbyRoom = value;
+        m_dolbyConfVideoRoom->set(m_currentVideoDolbyRoom);
+    }
+    return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyColor (int value)
+{
+    qDebug() << __PRETTY_FUNCTION__ << value;
+    if ( value < 0)
+    {
+        m_currentVideoDolbyColor = 0;
+        m_dolbyConfVideoColor->set(m_currentVideoDolbyColor);
+    }
+    else if ( value > MAX_VALUE)
+    {
+        m_currentVideoDolbyColor = MAX_VALUE;
+        m_dolbyConfVideoColor->set(m_currentVideoDolbyColor);
+    }
+    else
+    {
+        m_currentVideoDolbyColor = value;
+        m_dolbyConfVideoColor->set(m_currentVideoDolbyColor);
+    }
+    return true;
+}
+
+void MafwGstRendererDolby::valueMusicChanged()
+{
+    m_currentMusicDolbyState = m_dolbyConfMusic->value().toUInt();
+    if (!(m_currentMusicDolbyState <= MafwDolbyAuto))
+    {
+        m_currentMusicDolbyState = MafwDolbyOff;
+        m_currentMusicDolbyRoom = m_dolbyConfMusicRoom->value().toInt();
+        if (m_currentMusicDolbyRoom < 0)
+        {
+            m_currentMusicDolbyRoom = 0;
+        }
+        if (m_currentMusicDolbyRoom > MAX_VALUE)
+        {
+            m_currentMusicDolbyRoom = MAX_VALUE;
+        }
+        m_currentMusicDolbyColor = m_dolbyConfMusicColor->value().toInt();
+        if (m_currentMusicDolbyColor < 0)
+        {
+            m_currentMusicDolbyColor = 0;
+        }
+        if (m_currentMusicDolbyColor > MAX_VALUE)
+        {
+            m_currentMusicDolbyColor = MAX_VALUE;
+        }
+    }
+    qDebug() << __PRETTY_FUNCTION__ << "state" << m_currentMusicDolbyState;
+    qDebug() << __PRETTY_FUNCTION__ << "room" << m_currentMusicDolbyRoom;
+    qDebug() << __PRETTY_FUNCTION__ << "color" << m_currentMusicDolbyColor;
+   Q_EMIT mafwDHMMusicPropertyChanged();
+}
+
+void MafwGstRendererDolby::valueVideoChanged()
+{
+    m_currentVideoDolbyState = m_dolbyConfVideo->value().toUInt();
+    if (!(m_currentVideoDolbyState <= MafwDolbyAuto))
+    {
+        m_currentVideoDolbyState = MafwDolbyOff;
+        m_currentVideoDolbyRoom = m_dolbyConfVideoRoom->value().toInt();
+        if (m_currentVideoDolbyRoom < 0)
+        {
+            m_currentVideoDolbyRoom = 0;
+        }
+        if (m_currentVideoDolbyRoom > MAX_VALUE)
+        {
+            m_currentVideoDolbyRoom = MAX_VALUE;
+        }
+        m_currentVideoDolbyColor = m_dolbyConfVideoColor->value().toInt();
+        if (m_currentVideoDolbyColor < 0)
+        {
+            m_currentVideoDolbyColor = 0;
+        }
+        if (m_currentVideoDolbyColor > MAX_VALUE)
+        {
+            m_currentVideoDolbyColor = MAX_VALUE;
+        }
+    }
+    qDebug() << __PRETTY_FUNCTION__ << "state" << m_currentVideoDolbyState;
+    qDebug() << __PRETTY_FUNCTION__ << "room" << m_currentVideoDolbyRoom;
+    qDebug() << __PRETTY_FUNCTION__ << "color" << m_currentVideoDolbyColor;
+   Q_EMIT mafwDHMVideoPropertyChanged();
+}
+
+uint MafwGstRendererDolby::getMusicDolbyState ()
+{
+    qDebug() << __PRETTY_FUNCTION__ << m_currentMusicDolbyState;
+    return m_currentMusicDolbyState;
+}
+
+int MafwGstRendererDolby::getMusicDolbyRoom ()
+{
+    qDebug() << __PRETTY_FUNCTION__ << m_currentMusicDolbyRoom;
+    return m_currentMusicDolbyRoom;
+}
+
+int MafwGstRendererDolby::getMusicDolbyColor ()
+{
+    qDebug() << __PRETTY_FUNCTION__ << m_currentMusicDolbyColor;
+    return m_currentMusicDolbyColor;
+}
+
+uint MafwGstRendererDolby::getVideoDolbyState ()
+{
+    qDebug() << __PRETTY_FUNCTION__ << m_currentVideoDolbyState;
+    return m_currentVideoDolbyState;
+}
+
+int MafwGstRendererDolby::getVideoDolbyRoom ()
+{
+    qDebug() << __PRETTY_FUNCTION__ << m_currentVideoDolbyRoom;
+    return m_currentVideoDolbyRoom;
+}
+
+int MafwGstRendererDolby::getVideoDolbyColor ()
+{
+    qDebug() << __PRETTY_FUNCTION__ << m_currentVideoDolbyColor;
+    return m_currentVideoDolbyColor;
+}
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstRendererHaltState.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstRendererHaltState.cpp
new file mode 100644 (file)
index 0000000..8fbe2ef
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwGstRendererHaltState.h"
+
+int MafwGstRendererHaltState::DECAY_TIME = 20;
+
+/********************************************************************
+ * MafwGstRendererHaltState::MafwGstRendererHaltState
+ ********************************************************************/
+MafwGstRendererHaltState::MafwGstRendererHaltState()
+    :
+    QObject(),
+    m_state(MafwRenderer::Invalid),
+    m_position(-1)
+{
+    connect(&m_decayTimer, SIGNAL(timeout()),
+            this, SIGNAL(decayed()));
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::MafwGstRendererHaltState
+ ********************************************************************/
+MafwGstRendererHaltState::MafwGstRendererHaltState(const QString &uri,
+                                                   MafwRenderer::State state,
+                                                   int position)
+    :
+    QObject(),
+    m_uri(uri),
+    m_state(state),
+    m_position(position)
+{
+    connect(&m_decayTimer, SIGNAL(timeout()),
+            this, SIGNAL(decayed()));
+    initializeDecayTimer();
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::MafwGstRendererHaltState
+ ********************************************************************/
+MafwGstRendererHaltState::MafwGstRendererHaltState(const MafwGstRendererHaltState &other)
+    :
+    QObject()
+{
+    *this = other;
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::operator =
+ ********************************************************************/
+MafwGstRendererHaltState& MafwGstRendererHaltState::operator =(const MafwGstRendererHaltState &other)
+{
+    if( this == &other )
+    {
+        return *this;
+    }
+
+    this->m_uri = other.m_uri;
+    this->m_position = other.m_position;
+    this->m_state = other.m_state;
+
+    initializeDecayTimer();
+
+    return *this;
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::~MafwGstRendererHaltState
+ ********************************************************************/
+MafwGstRendererHaltState::~MafwGstRendererHaltState()
+{
+
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::isSet
+ ********************************************************************/
+bool MafwGstRendererHaltState::isSet() const
+{
+    return ((m_uri.length() > 0)
+            && (m_state != MafwRenderer::Invalid)
+            && (m_decayTimer.isActive() || m_state == MafwRenderer::Paused));
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::setState
+ ********************************************************************/
+void MafwGstRendererHaltState::clear()
+{
+    m_uri.clear();
+    m_position = -1;
+    m_state = MafwRenderer::Invalid;
+    m_decayTimer.stop();
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::setState
+ ********************************************************************/
+void MafwGstRendererHaltState::setState(MafwRenderer::State newState)
+{
+    m_state = newState;
+    if( newState == MafwRenderer::Paused )
+    {
+        m_decayTimer.stop();
+    }
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::uri
+ ********************************************************************/
+QString MafwGstRendererHaltState::uri() const
+{
+    return m_uri;
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::state
+ ********************************************************************/
+MafwRenderer::State MafwGstRendererHaltState::state() const
+{
+    return m_state;
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::position
+ ********************************************************************/
+int MafwGstRendererHaltState::position() const
+{
+    return m_position;
+}
+
+/********************************************************************
+ * MafwGstRendererHaltState::initializeDecayTimer
+ ********************************************************************/
+void MafwGstRendererHaltState::initializeDecayTimer()
+{
+    if( m_uri.length() > 0 && m_state != MafwRenderer::Invalid )
+    {
+        m_decayTimer.setSingleShot(true);
+        m_decayTimer.setInterval(DECAY_TIME * 1000);
+        m_decayTimer.start();
+    }
+    else
+    {
+        m_decayTimer.stop();
+    }
+}
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstRendererNetworkMonitor.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstRendererNetworkMonitor.cpp
new file mode 100644 (file)
index 0000000..504676d
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwGstRendererNetworkMonitor.h"
+#include "MafwGstRendererHaltState.h"
+
+#include <QDebug>
+#include <QtNetwork/QNetworkConfigurationManager>
+
+/********************************************************************
+ * MafwGstRendererNetworkMonitor::MafwGstRendererNetworkMonitor
+ ********************************************************************/
+MafwGstRendererNetworkMonitor::MafwGstRendererNetworkMonitor()
+    :
+    m_networkManager(new QNetworkConfigurationManager(this))
+{
+    connect(m_networkManager, SIGNAL(configurationChanged(QNetworkConfiguration)),
+            this, SLOT(handleConfigurationChange(QNetworkConfiguration)));
+}
+
+/********************************************************************
+ * MafwGstRendererNetworkMonitor::MafwGstRendererNetworkMonitor
+ ********************************************************************/
+MafwGstRendererNetworkMonitor::~MafwGstRendererNetworkMonitor()
+{
+
+}
+
+/********************************************************************
+ * MafwGstRendererNetworkMonitor::handleConfigurationChange
+ ********************************************************************/
+void MafwGstRendererNetworkMonitor::handleConfigurationChange(const QNetworkConfiguration &config)
+{
+    qDebug() << __PRETTY_FUNCTION__ << "Configs status: " << config.name() << config.state();
+
+    QNetworkConfiguration::StateFlags flags = config.state();
+    if( flags.testFlag(QNetworkConfiguration::Active) )
+    {
+        Q_EMIT networkChangeFinished();
+        m_currentConfiguration = config;
+    }
+    else if( !m_currentConfiguration.isValid() || config == m_currentConfiguration )
+    {
+        Q_EMIT prepareNetworkChange();
+    }
+}
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstRendererPlaylistFileUtility.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstRendererPlaylistFileUtility.cpp
new file mode 100644 (file)
index 0000000..eb70f10
--- /dev/null
@@ -0,0 +1,165 @@
+#include "MafwGstRendererPlaylistFileUtility.h"
+#include <glib-object.h>
+#include <QUrl>
+#include <QDebug>
+#include <MafwError.h>
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::MafwGstRendererPlaylistFileUtility
+ ********************************************************************/
+MafwGstRendererPlaylistFileUtility::MafwGstRendererPlaylistFileUtility(QObject* parent):
+        QObject(parent), m_parserId(0), m_firstItem(false)
+{    
+    g_type_init();
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::MafwGstRendererPlaylistFileUtility
+ ********************************************************************/
+MafwGstRendererPlaylistFileUtility::~MafwGstRendererPlaylistFileUtility()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::getUriList
+ ********************************************************************/
+QStringList MafwGstRendererPlaylistFileUtility::getUriList()
+{
+    return m_uriList;
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::playPlaylistFile
+ ********************************************************************/
+void MafwGstRendererPlaylistFileUtility::parsePlaylistFile(const QUrl& url)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (url.isValid() && !url.scheme().isEmpty())
+    {
+        m_uriList.clear();
+        m_parserId = totem_pl_parser_new ();
+        g_object_set(m_parserId, "recurse", false, "disable-unsafe",
+                     true, NULL);
+        g_signal_connect(G_OBJECT(m_parserId), "entry-parsed", G_CALLBACK(uriParsed), this);
+        totem_pl_parser_parse_async(m_parserId,
+                                    url.toString().toAscii().constData(),
+                                    false,
+                                    0,
+                                    GAsyncReadyCallback(readyCb),
+                                    (void *)this);
+        g_object_unref(m_parserId);
+        m_firstItem = true;
+    }
+    else
+    {
+        Q_EMIT parsingReady(false);
+    }
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::takeFirstUri
+ ********************************************************************/
+QString MafwGstRendererPlaylistFileUtility::takeFirstUri()
+{
+    if (m_uriList.isEmpty())
+    {
+        qDebug() << __PRETTY_FUNCTION__ << ": there are no more items parsed";
+        return QString();
+    }
+    else
+    {
+        return m_uriList.takeFirst();
+    }
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::setPendingError
+ ********************************************************************/
+void MafwGstRendererPlaylistFileUtility::setPendingError(MafwError& error)
+{
+    m_pendingError = error;
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::takePendingError
+ ********************************************************************/
+MafwError MafwGstRendererPlaylistFileUtility::takePendingError()
+{
+    MafwError retMe = m_pendingError;
+    m_pendingError = MafwError();
+    return retMe;
+}
+
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::uriParsed
+ ********************************************************************/
+void MafwGstRendererPlaylistFileUtility::uriParsed(TotemPlParser* parser,
+                      gchar* uri,
+                      gpointer /*metadata*/,
+                      MafwGstRendererPlaylistFileUtility* self)
+{
+    qDebug() << __PRETTY_FUNCTION__ << parser << uri;
+
+    if (uri && (parser == self->m_parserId))
+    {
+        QString modifiedURI = self->manHandleURI(uri);
+        self->m_uriList.append(modifiedURI);
+        if (self->m_firstItem)
+        {
+            Q_EMIT self->firstItemParsed();
+            self->m_firstItem = false;
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::readyCb
+ ********************************************************************/
+void MafwGstRendererPlaylistFileUtility::readyCb(TotemPlParser* parser,
+                                            GAsyncResult* async_result,
+                                            MafwGstRendererPlaylistFileUtility* self)
+{
+    qDebug() << __PRETTY_FUNCTION__ << parser;
+    if (parser == self->m_parserId)
+    {
+        GError *error = 0;
+        bool success = true;
+
+        TotemPlParserResult  result = totem_pl_parser_parse_finish(parser,
+                                                                   async_result,
+                                                                   &error);
+        qDebug() << __PRETTY_FUNCTION__ << result;
+        if (result != TOTEM_PL_PARSER_RESULT_SUCCESS)
+        {
+            success = false;
+            qWarning() << __PRETTY_FUNCTION__ << ": Playlist file parsing failed";
+            if (error)
+            {
+                qWarning() << error->message;
+                g_error_free (error);
+            }
+        }
+        //Actually parsing is not ready yet, we might have no results yet.
+        Q_EMIT self->parsingReady(success);
+    }
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::manHandleURI
+ ********************************************************************/
+QString MafwGstRendererPlaylistFileUtility::manHandleURI(const QString &itemUri) const
+{
+    qDebug() << __FUNCTION__ << "Orig: " << itemUri;
+    QString modifiedUri = itemUri;
+
+    if( itemUri.endsWith(".asf", Qt::CaseInsensitive)
+        && itemUri.startsWith("http://", Qt::CaseInsensitive) )
+    {
+        modifiedUri.replace(0,4, "mmsh");
+    }
+    qDebug() << __FUNCTION__ << "Handled: " << modifiedUri;
+    return modifiedUri;
+}
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstRendererPlugin.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstRendererPlugin.cpp
new file mode 100644 (file)
index 0000000..734ddd9
--- /dev/null
@@ -0,0 +1,145 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QObject>
+#include <QtPlugin>
+#include <QDebug>
+#include <QSettings>
+#include <QCoreApplication>
+
+#include <MafwInternalRegistry.h>
+
+#include "MafwGstRendererPlugin.h"
+#include "MafwGstRenderer.h"
+
+#ifdef _VERSION_INFO
+#include "version.h"
+#endif
+
+const QString PLUGIN_NAME = "MafwGstRendererPlugin";
+const QString RENDERER_UUID = "mafw_gst_renderer";
+const QString DBUS_WRAPPER_NAME = "qmafw-dbus-wrapper";
+const QString RENDERER_PLUGIN_CONFIG_FILE = "/usr/share/qmafw/mafw-gst-renderer-plugin.conf";
+
+
+MafwGstRendererPlugin::~MafwGstRendererPlugin()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    for(int i = 0; i < m_rendererIds.count(); i++)
+    {
+        m_registry->removeExtension(m_rendererIds.at(i));
+    }
+}
+
+void MafwGstRendererPlugin::initialize(MafwInternalRegistry* registry)
+{
+#ifdef _VERSION_INFO
+    qDebug() << "mafw-gst-renderer revision:" << revision;
+    qDebug() << "mafw-gst-renderer library builtime:" << build_time;
+#endif
+
+    Q_ASSERT(registry);
+
+    m_registry = registry;
+
+    QString rendererArrayKey;
+    QString appname = QCoreApplication::applicationName();
+    // appname can contain full path to config file
+    if(appname.endsWith(DBUS_WRAPPER_NAME))
+    {
+        // We are loading out-process renderers from config file
+        rendererArrayKey = "renderers";
+        loadRenderers(rendererArrayKey);
+    }
+    else
+    {
+        // We are loading in-process renderers from config file
+        rendererArrayKey = "in-process-renderers";
+        loadRenderers(rendererArrayKey);
+    }
+
+    // if there are no gst-renderers in config file, we create a "basic" gst-renderer
+    if(m_rendererIds.isEmpty())
+    {
+        MafwGstRenderer *rnd = new MafwGstRenderer(RENDERER_UUID,
+                                                   PLUGIN_NAME,
+                                                   "QMAFW GStreamer Renderer",
+                                                   registry);
+
+        QSettings settings(RENDERER_PLUGIN_CONFIG_FILE, QSettings::NativeFormat);
+
+        if(rnd->initialize(&settings))
+        {
+            m_registry->addRenderer(rnd);
+            m_rendererIds.append(RENDERER_UUID);
+        }
+        else
+        {
+            qCritical() << "Failed to initialize QMAFW GStreamer Renderer";
+            delete rnd;
+        }
+    }
+}
+
+void MafwGstRendererPlugin::loadRenderers(const QString& rendererArrayKey)
+{
+    QSettings settings(RENDERER_PLUGIN_CONFIG_FILE, QSettings::NativeFormat);
+    QString id;
+    QString friendlyname;
+
+    QList<MafwGstRenderer*> rnds;
+
+    // Configuration file contains the array of renderer names and uuids as string.
+    // beginReadArray returns size of the array.
+    int size = settings.beginReadArray(rendererArrayKey);
+    for(int i = 0; i < size; i++)
+    {
+        settings.setArrayIndex(i);
+        id = settings.value("Id").toString();
+        friendlyname = settings.value("FriendlyName").toString();
+        MafwGstRenderer *rnd = new MafwGstRenderer(id,
+                                                   PLUGIN_NAME,
+                                                   friendlyname,
+                                                   m_registry);
+        rnds.append(rnd);
+    }
+    settings.endArray();
+
+    Q_FOREACH( MafwGstRenderer *rnd, rnds )
+    {
+        if(rnd->initialize(&settings))
+        {
+            m_registry->addRenderer(rnd);
+            m_rendererIds.append(rnd->uuid());
+        }
+        else
+        {
+            qCritical() << "Failed to initialize" << rnd->name();
+            delete rnd;
+        }
+    }
+}
+
+QString MafwGstRendererPlugin::name() const
+{
+    return PLUGIN_NAME;
+}
+
+/*****************************************************************************
+ * Plugin export
+ ****************************************************************************/
+Q_EXPORT_PLUGIN2(qmafw-gst-renderer-plugin, MafwGstRendererPlugin)
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstRendererVolume.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstRendererVolume.cpp
new file mode 100644 (file)
index 0000000..daf3b95
--- /dev/null
@@ -0,0 +1,476 @@
+#include "MafwGstRendererVolume.h"
+
+#include <dbus/dbus.h>
+#include <dbusconnectioneventloop.h>
+
+#include <QDebug>
+#include <QTimer>
+
+// The default PulseAudioMainVolume DBus API socket
+#define DEFAULT_ADDRESS "unix:path=/var/run/pulse/dbus-socket"
+#define ROLE = "x-maemo";
+
+#define PULSE_CORE_PATH "/org/pulseaudio/core1"
+#define STREAM_RESTORE_PATH "/org/pulseaudio/stream_restore1"
+#define STREAM_RESTORE_IF "org.PulseAudio.Ext.StreamRestore1"
+#define GET_ENTRY_METHOD "GetEntryByName"
+#define STREAM_RESTORE_IF_ENTRY STREAM_RESTORE_IF ".RestoreEntry"
+#define STREAM_RESTORE_VOLUME_SIGNAL STREAM_RESTORE_IF_ENTRY ".VolumeUpdated"
+
+#define ENTRY_NAME "sink-input-by-media-role:x-maemo"
+//# 100% volume in Pulseaudio's native volume units.
+const uint VOLUME_NORM = 0x10000;
+//Place of mono channel at pulse audio's channel position enumeration
+const uint VOLUME_CHANNEL_MONO = 0;
+//Delay for attempting to reconnect to pulseaudio
+const uint PULSE_RESTART_DELAY = 2000;
+
+/********************************************************************
+ * MafwGstRendererVolume::MafwGstRendererVolume
+ ********************************************************************/
+MafwGstRendererVolume::MafwGstRendererVolume(): m_currentVolume(0), m_pendingVolumeValue(0),
+                            m_dbusConnection(0), m_objectPath(QString()), m_pendingCall(0)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    connectToPulseAudio();
+}
+
+/********************************************************************
+ * MafwGstRendererVolume::connectToPulseAudio
+ ********************************************************************/
+void MafwGstRendererVolume::connectToPulseAudio()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    DBusError error;
+    QByteArray address = qgetenv("PULSE_DBUS_SERVER");
+
+    if (address.isEmpty())
+    {
+        address = QByteArray(DEFAULT_ADDRESS);
+    }
+
+    dbus_error_init (&error);
+
+    if (m_dbusConnection)
+    {
+        DBUSConnectionEventLoop::removeConnection(m_dbusConnection);
+        dbus_connection_unref(m_dbusConnection);
+        m_dbusConnection = 0;
+    }
+
+    m_dbusConnection = dbus_connection_open (address.constData(), &error);
+
+    if (dbus_error_is_set(&error))
+    {
+        qCritical() << "Unable to open dbus connection to pulse audio:" << error.message;
+        dbus_error_free (&error);        
+        QTimer::singleShot(PULSE_RESTART_DELAY, this, SLOT(connectToPulseAudio()));
+    }
+    else
+    {
+        if (DBUSConnectionEventLoop::addConnection(m_dbusConnection))
+        {
+        dbus_connection_add_filter (
+            m_dbusConnection,
+            (DBusHandleMessageFunction) handleIncomingMessages,
+            (void *) this, NULL);
+
+        getRestoreEntryForMediaRole();
+        }
+        else
+        {
+            qCritical() << "DBUSConnectionEventLoop failure";
+            dbus_connection_unref(m_dbusConnection);
+            m_dbusConnection = 0;
+        }
+    }
+}
+
+/********************************************************************
+ * MafwGstRendererVolume::~MafwGstRendererVolume()
+ ********************************************************************/
+MafwGstRendererVolume::~MafwGstRendererVolume()
+{
+    if(m_pendingCall)
+    {
+        dbus_pending_call_cancel(m_pendingCall);
+    }
+    DBUSConnectionEventLoop::removeConnection(m_dbusConnection);
+    dbus_connection_unref(m_dbusConnection);
+}
+/********************************************************************
+ * We need the object path for the RestoreEntry of the "x-maemo" role.
+ * GetEntryByName with parameter "sink-input-by-media-role:x-maemo" is used
+ * for that.
+ ********************************************************************/
+void MafwGstRendererVolume::getRestoreEntryForMediaRole()
+{    
+    qDebug() << __PRETTY_FUNCTION__;
+    DBusMessage *msg;
+    DBusError    error;
+
+    dbus_error_init (&error);
+
+    msg = dbus_message_new_method_call(0,
+                                       STREAM_RESTORE_PATH,
+                                       STREAM_RESTORE_IF,
+                                       GET_ENTRY_METHOD);
+    const char *name = ENTRY_NAME;
+    dbus_message_append_args (msg,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_INVALID);
+
+
+    DBusPendingCall *pending = 0;
+    //Return value taken for satisfying coverity tool
+    bool outOfMemory = dbus_connection_send_with_reply( m_dbusConnection, msg, &pending, -1 );
+    Q_UNUSED(outOfMemory);
+    m_pendingCall = pending;
+
+    if (pending)
+    {        
+        qDebug() << __PRETTY_FUNCTION__ << "pending call sent!";
+        dbus_pending_call_set_notify( pending,
+                                      (DBusPendingCallNotifyFunction) getEntryReply,
+                                      (void *)this,
+                                      NULL );
+        dbus_message_unref(msg);
+    }
+    qDebug() << __PRETTY_FUNCTION__ << "exit";
+}
+
+/********************************************************************
+ * Now we have the RestoreEntry object path for "x-maemo". Next we just
+ * need to start listening for the VolumeUpdated signals from that object,
+ * and use the Volume property for controlling the role volume.
+ ********************************************************************/
+void MafwGstRendererVolume::getEntryReply(DBusPendingCall *pending, MafwGstRendererVolume *self)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    self->m_pendingCall = 0;
+    DBusMessage *reply;
+    DBusError error;
+
+    dbus_error_init(&error);
+
+    reply = dbus_pending_call_steal_reply(pending);
+
+    if (dbus_set_error_from_message(&error, reply))
+    {
+        qWarning() << "Unable to get volume from pulse audio:" << error.message;
+        dbus_error_free (&error);
+        //Try to reconnect
+        QTimer::singleShot(0, self, SLOT(connectToPulseAudio()));
+    }
+    else if (reply && (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN))
+    {
+        const char *object_path;
+        bool argError = dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID);
+        if (!argError)
+        {
+            qWarning() << "Unable to get volume from pulse audio:" << error.message;
+            dbus_error_free (&error);
+            //Try to reconnect
+            QTimer::singleShot(0, self, SLOT(connectToPulseAudio()));
+        }
+
+        qDebug() << __PRETTY_FUNCTION__ << "Object path: " << object_path;
+        self->m_objectPath = object_path;
+
+        if (self->m_pendingVolumeValue > 0)
+        {
+            qDebug() << __PRETTY_FUNCTION__ << "setting volume to level " << self->m_pendingVolumeValue;
+            self->listenVolumeSignals();
+            self->setVolume(self->m_pendingVolumeValue);
+            self->m_pendingVolumeValue = 0;
+        }
+        else
+        {
+            qDebug() << __PRETTY_FUNCTION__ << "getting initial volume level.";
+            DBusMessage *msg;
+            DBusError    error2;
+            dbus_error_init (&error2);
+
+            msg = dbus_message_new_method_call(0,
+                                               object_path,
+                                               DBUS_INTERFACE_PROPERTIES,
+                                               "Get");
+            const char* interface = STREAM_RESTORE_IF_ENTRY;
+            const char* property = "Volume";
+
+            dbus_message_append_args (msg,
+                                      DBUS_TYPE_STRING, &interface,
+                                      DBUS_TYPE_STRING, &property,
+                                      DBUS_TYPE_INVALID);
+
+            DBusPendingCall *pending = 0;
+            //Return value taken for satisfying coverity tool
+            bool outOfMemory = dbus_connection_send_with_reply( self->m_dbusConnection, msg, &pending, -1 );
+            Q_UNUSED(outOfMemory);
+            self->m_pendingCall = pending;
+            if (pending)
+            {
+                qDebug() << __PRETTY_FUNCTION__ << "pending call sent!";
+                dbus_pending_call_set_notify( pending,
+                                              (DBusPendingCallNotifyFunction) volumeReply,
+                                              (void *)self,
+                                              NULL );
+                dbus_message_unref(msg);
+            }
+        }
+    }
+    dbus_message_unref (reply);
+}
+
+/********************************************************************
+ * MafwGstRendererVolume::volumeReply
+ ********************************************************************/
+void MafwGstRendererVolume::volumeReply(DBusPendingCall *pending, MafwGstRendererVolume *self)
+{
+    self->m_pendingCall = 0;
+    Q_UNUSED (self);
+    qDebug() << __PRETTY_FUNCTION__;
+
+    DBusMessage *reply;
+    reply = dbus_pending_call_steal_reply(pending);
+
+    DBusError error;
+    dbus_error_init(&error);
+
+    if (dbus_set_error_from_message(&error, reply))
+    {
+        qWarning() << "MafwGstRendererVolume: Unable to get volume from pulse audio:" << error.message;
+        dbus_error_free (&error);
+    }
+    else
+    {
+        DBusMessageIter iter, array_iterator;
+        dbus_message_iter_init (reply, &iter);
+        if(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT)
+        {
+            dbus_message_iter_recurse (&iter, &array_iterator);
+        }
+
+        if (dbus_message_iter_get_arg_type (&array_iterator) == DBUS_TYPE_ARRAY)
+        {
+            self->readVolumeFromStruct(&array_iterator);
+            Q_EMIT self->volumeChanged(self->m_currentVolume);
+        }
+        else
+        {
+            qCritical("Unable to get initial volume from Pulse Audio!!");
+        }
+    }
+    dbus_message_unref (reply);
+    self->listenVolumeSignals();
+}
+
+/********************************************************************
+ * MafwGstRendererVolume::listenVolumeSignals
+ ********************************************************************/
+void MafwGstRendererVolume::listenVolumeSignals()
+{    
+    qDebug() << __PRETTY_FUNCTION__;
+
+    DBusMessage *message = 0;
+    char *signal = (char *) STREAM_RESTORE_VOLUME_SIGNAL;
+    char           **emptyarray = { 0 };
+
+    message = dbus_message_new_method_call (0,
+                                            PULSE_CORE_PATH,
+                                            0,
+                                            "ListenForSignal");
+
+    dbus_message_append_args (message,
+                              DBUS_TYPE_STRING, &signal,
+                              DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &emptyarray, 0,
+                              DBUS_TYPE_INVALID);
+
+    dbus_connection_send (m_dbusConnection, message, NULL);
+    dbus_connection_flush (m_dbusConnection);
+    dbus_message_unref (message);
+}
+
+/********************************************************************
+ * MafwGstRendererVolume::handleIncomingMessages
+ ********************************************************************/
+void MafwGstRendererVolume::handleIncomingMessages (DBusConnection* conn,
+                    DBusMessage* message,
+                    MafwGstRendererVolume* self)
+{    
+    qDebug(__PRETTY_FUNCTION__);
+    Q_UNUSED (conn);
+
+    if (message &&
+        dbus_message_has_member (message, "VolumeUpdated") &&
+        dbus_message_has_interface(message, STREAM_RESTORE_IF_ENTRY) &&
+        dbus_message_has_path(message, self->m_objectPath.toAscii()))
+    {
+        qDebug() << "MafwGstRendererVolume: VolumeUpdated signal received.";
+        DBusError error;
+        dbus_error_init(&error);
+
+        if (dbus_set_error_from_message(&error, message))
+        {
+            qWarning() << "Got volume error from pulse audio:" << error.message;
+            dbus_error_free (&error);
+        }
+
+        DBusMessageIter iter;
+        dbus_message_iter_init (message, &iter);
+
+        if (self->readVolumeFromStruct(&iter))
+        {
+            Q_EMIT self->volumeChanged(self->m_currentVolume);
+        }
+    }
+    //When a connection is disconnected, you are guaranteed to get a signal "Disconnected" from the interface DBUS_INTERFACE_LOCAL, path DBUS_PATH_LOCAL.
+    else if (message &&
+             dbus_message_has_member (message, "Disconnected") &&
+             dbus_message_get_interface(message) == QString(DBUS_INTERFACE_LOCAL) &&
+             dbus_message_get_path(message) == QString(DBUS_PATH_LOCAL))
+    {
+        qWarning("MafwGstRendererVolume: Connection with pulse audio is disconnected!");
+        QTimer::singleShot(PULSE_RESTART_DELAY, self, SLOT(connectToPulseAudio()));
+        qDebug("MafwGstRendererVolume: Trying to reconnect.");
+    }
+
+}
+
+/********************************************************************
+ * There is a dbus variant containing array of structures. Each structure
+ * contains channels postion and the volume level of this position
+ ********************************************************************/
+bool MafwGstRendererVolume::readVolumeFromStruct(DBusMessageIter *iterator)
+{    
+    qDebug(__PRETTY_FUNCTION__);
+    bool volumeChanged = false;
+    DBusMessageIter struct_iterator;
+    dbus_message_iter_recurse (iterator, &struct_iterator);
+    int volume = -1;
+
+    while (dbus_message_iter_get_arg_type(&struct_iterator) == DBUS_TYPE_STRUCT)
+    {
+        DBusMessageIter variant;
+        dbus_message_iter_recurse (&struct_iterator, &variant);
+        int channel, value = 0;
+
+        if (dbus_message_iter_get_arg_type (&variant) == DBUS_TYPE_UINT32)
+        {
+            dbus_message_iter_get_basic (&variant, &channel);
+            qDebug("Channel %d", channel);
+            dbus_message_iter_next (&variant);
+            dbus_message_iter_get_basic (&variant, &value);
+
+            value = qRound((float)value / (float)VOLUME_NORM * 100);
+
+            //We're interested in all the channels that stream-restore happens to give you.
+            //We have to somehow map between a single volume value and per-channel volume.
+            //The usual way to do the mapping is just to use the loudest channel as
+            //the overall volume
+            if (value > volume)
+            {
+                uint newVolume = value;
+                if (newVolume != m_currentVolume)
+                {
+                    m_currentVolume = newVolume;
+                    volumeChanged = true;
+                    qDebug("MafwGstRendererVolume: current volume level has changed: %d", m_currentVolume);
+                }
+            }
+
+            if (m_currentVolume > 100) //MAFW volume has range 0-100
+            {
+                qWarning("MafwGstRendererVolume: Pulse audio signals volume level which is out-of range!");
+                m_currentVolume = 100;
+                break;
+            }
+        }
+        else
+        {
+            qWarning("MafwGstRendererVolume: Invalid volume value from pulse audio!");
+        }
+        dbus_message_iter_next (&struct_iterator);
+    }
+    return volumeChanged;
+}
+
+/********************************************************************
+ * MafwGstRendererVolume::getVolume
+ ********************************************************************/
+uint MafwGstRendererVolume::getVolume()
+{
+    qDebug(__PRETTY_FUNCTION__);
+    return m_currentVolume;
+}
+
+/********************************************************************
+ * Incoming value has range 0-99 pulseaudio uses values 0-VOLUME_NORM
+ ********************************************************************/
+bool MafwGstRendererVolume::setVolume (uint value)
+{
+    bool success = true;
+    qDebug("MafwGstRendererVolume::setVolume (uint %d)", value);
+    if (m_objectPath.isEmpty())
+    {
+        qDebug() << "MafwGstRendererVolume: Can not set volume yet. Waiting for RestoreEntry object path";
+        m_pendingVolumeValue = value;
+        return success;
+    }
+
+    const char* interface = STREAM_RESTORE_IF_ENTRY;
+    const char* property = "Volume";
+    if (value > 100) //MAFW volume has range 0-100
+    {
+        qWarning("MafwGstRendererVolume: Trying to set volume level which is out-of range!");
+        value = (uint)100;
+    }
+    uint nativeValue = (((float)value / (float)100) * VOLUME_NORM);
+    DBusMessage* message;
+    message = dbus_message_new_method_call(0,
+                                           m_objectPath.toAscii(),
+                                           DBUS_INTERFACE_PROPERTIES,
+                                           "Set");
+
+    if ( dbus_message_append_args(message,
+                                 DBUS_TYPE_STRING, &interface,
+                                 DBUS_TYPE_STRING, &property,
+                                 DBUS_TYPE_INVALID))
+    {
+        //Compose the dbus variant containing an array of struct of pair
+        //of unsigned integers va(uu)
+        DBusMessageIter argument_iterator, variant_iterator, array_iterator, struct_iterator;
+        dbus_message_iter_init_append (message, &argument_iterator);
+        dbus_message_iter_open_container (&argument_iterator,
+                                          DBUS_TYPE_VARIANT,
+                                          "a(uu)",
+                                          &variant_iterator);
+        dbus_message_iter_open_container (&variant_iterator,
+                                          DBUS_TYPE_ARRAY,
+                                          "(uu)",
+                                          &array_iterator);
+        dbus_message_iter_open_container (&array_iterator,
+                                          DBUS_TYPE_STRUCT,
+                                          NULL,
+                                          &struct_iterator);
+
+        dbus_message_iter_append_basic (&struct_iterator, DBUS_TYPE_UINT32, &VOLUME_CHANNEL_MONO);
+        dbus_message_iter_append_basic (&struct_iterator, DBUS_TYPE_UINT32, &nativeValue);
+
+        dbus_message_iter_close_container (&array_iterator, &struct_iterator);
+        dbus_message_iter_close_container (&variant_iterator, &array_iterator);
+        dbus_message_iter_close_container (&argument_iterator, &variant_iterator);
+
+        dbus_connection_send (m_dbusConnection, message, NULL);
+        dbus_connection_flush (m_dbusConnection);
+    }
+    else
+    {
+        qWarning("Cannot set volume!");
+        success = false;
+    }
+    dbus_message_unref (message);
+
+    return success;
+}
diff --git a/qmafw-gst-subtitles-renderer/src/MafwGstScreenshot.cpp b/qmafw-gst-subtitles-renderer/src/MafwGstScreenshot.cpp
new file mode 100644 (file)
index 0000000..610ab1d
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwGstScreenshot.h"
+#include <QDebug>
+
+MafwGstScreenshot::MafwGstScreenshot(QObject *parent) : QObject(parent)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_src = NULL;
+    m_sink = NULL;
+    m_pipeline = NULL;
+    m_filter = NULL;
+    m_csp = NULL;
+    m_enc = NULL;
+    m_bus = NULL;
+    m_caps = NULL;
+    m_structure = NULL;
+    m_handler_id = 0;
+}
+
+MafwGstScreenshot::~MafwGstScreenshot()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    if(m_pipeline)
+    {
+        gst_element_set_state(m_pipeline, GST_STATE_NULL);
+        gst_object_unref(m_pipeline);
+    }
+}
+
+static void copyBufferToSource(GstElement *src, GstBuffer *buffer, GstPad *pad,
+                         gpointer data)
+{
+
+    Q_UNUSED(src);
+    Q_UNUSED(pad);
+
+    GstBuffer *in_buf = GST_BUFFER(data);
+
+    memcpy(GST_BUFFER_DATA(buffer), GST_BUFFER_DATA(in_buf),
+           GST_BUFFER_SIZE(in_buf));
+    GST_BUFFER_SIZE(buffer) = GST_BUFFER_SIZE(in_buf);
+}
+
+static void freeSourceBuffer(gpointer data)
+{
+    GstBuffer *in_buf = GST_BUFFER(data);
+    gst_buffer_unref(in_buf);
+}
+
+static gboolean asyncBusHandler(GstBus *bus, GstMessage *msg, gpointer data)
+{
+    Q_UNUSED(bus);
+
+    gboolean ret = TRUE;
+
+    MafwGstScreenshot *self = static_cast<MafwGstScreenshot*>(data);
+
+    switch(GST_MESSAGE_TYPE(msg))
+    {
+        case GST_MESSAGE_EOS:
+        {
+            ret = self->reportBack(NULL);
+            break;
+        }
+        case GST_MESSAGE_ERROR:
+        {
+            GError *error = NULL;
+
+            gst_message_parse_error(msg, &error, NULL);
+
+            ret = self->reportBack(error);
+            g_error_free(error);
+            break;
+        }
+        default:
+            break;
+    }
+    return ret;
+}
+
+/********************************************************************
+ * MafwGstScreenshot::savePauseFrame
+ ********************************************************************/
+bool MafwGstScreenshot::savePauseFrame(GstBuffer *buffer, const char *filename)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    gint width = 0;
+    gint height = 0;
+
+    if(!m_pipeline)
+    {
+        m_pipeline = gst_pipeline_new("screenshot-pipeline");
+        if(!m_pipeline)
+        {
+            goto err_out;
+        }
+        m_src = gst_element_factory_make("fakesrc", NULL);
+        m_sink = gst_element_factory_make("filesink", NULL);
+        m_filter = gst_element_factory_make("capsfilter", NULL);
+        m_csp = gst_element_factory_make("ffmpegcolorspace", NULL);
+        m_enc = gst_element_factory_make("pngenc", NULL);
+
+        if(!m_src || !m_sink || !m_filter || !m_csp || !m_enc)
+        {
+            goto err_out;
+        }
+
+        gst_bin_add_many(GST_BIN(m_pipeline), m_src, m_filter, m_csp, m_enc, m_sink, NULL);
+
+        if(!gst_element_link_many(m_src, m_filter, m_csp, m_enc, m_sink, NULL))
+        {
+            goto err_out;
+        }
+
+        m_bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
+        gst_bus_add_watch(m_bus, asyncBusHandler, this);
+        gst_object_unref(m_bus);
+
+        g_object_set(m_sink, "preroll-queue-len", 1, NULL);
+        g_object_set(m_src,
+                "sizetype", 2,
+                "num-buffers", 1,
+                "signal-handoffs", TRUE,
+                NULL);
+        g_object_set(m_enc, "compression-level", 1, NULL);
+    }
+
+    m_caps = gst_caps_copy(GST_BUFFER_CAPS(buffer));
+    if(!m_caps)
+    {
+        goto err_out;
+    }
+    m_structure = gst_caps_get_structure(m_caps, 0);
+    gst_structure_remove_field(m_structure, "pixel-aspect-ratio");
+    /* limit image size in case it exceeds the pre-determined size */
+    if(gst_structure_get_int(m_structure, "width", &width) &&
+       gst_structure_get_int(m_structure, "height", &height))
+    {
+        gst_caps_set_simple(m_caps,
+                            "width", G_TYPE_INT, width,
+                            "height", G_TYPE_INT, height,
+                            NULL);
+    }
+    g_object_set(m_filter, "caps", m_caps, NULL);
+    gst_caps_unref(m_caps);
+
+    g_object_set(m_sink, "location", filename, NULL);
+    g_object_set(m_src, "sizemax", GST_BUFFER_SIZE(buffer), NULL);
+
+    m_handler_id = g_signal_connect_data(m_src, "handoff", G_CALLBACK(copyBufferToSource), buffer, (GClosureNotify) freeSourceBuffer, G_CONNECT_AFTER);
+
+    gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
+
+    return true;
+
+err_out:
+    if( m_pipeline )
+    {
+        gst_object_unref(m_pipeline);
+        m_pipeline = NULL;
+    }
+    if( buffer )
+    {
+        gst_buffer_unref(buffer);
+    }
+
+    return false;
+}
+
+/********************************************************************
+ * MafwGstScreenshot::cancelPauseFrame
+ ********************************************************************/
+void MafwGstScreenshot::cancelPauseFrame()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    gst_element_set_state(m_pipeline, GST_STATE_NULL);
+    g_signal_handler_disconnect(m_src, m_handler_id);
+
+    Q_EMIT screenshotCancelled();
+}
+
+/********************************************************************
+ * MafwGstScreenshot::reportBack
+ ********************************************************************/
+bool MafwGstScreenshot::reportBack(GError *error)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    if(!error)
+    {
+        char *location;
+        g_object_get(m_sink, "location", &location, NULL);
+        Q_EMIT screenshotTaken(location, NULL);
+        g_free(location);
+    }
+    else
+    {
+        Q_EMIT screenshotTaken(NULL, error);
+    }
+
+    gst_element_set_state(m_pipeline, GST_STATE_NULL);
+    g_signal_handler_disconnect(m_src, m_handler_id);
+
+    return true;
+}
diff --git a/qmafw-gst-subtitles-renderer/src/MafwMmcMonitor.cpp b/qmafw-gst-subtitles-renderer/src/MafwMmcMonitor.cpp
new file mode 100644 (file)
index 0000000..94fd5b5
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwMmcMonitor.h"
+#include <QDebug>
+#include <glib.h>
+
+#include <usb_moded-dbus.h>
+#include <QDBusConnection>
+
+const QString MafwMmcMonitor::MMC_URI_PREFIX="file:///home/user/MyDocs";
+
+MafwMmcMonitor::MafwMmcMonitor(QObject* parent) : QObject(parent), m_mounted(false)
+{
+    m_gVolMonitor=g_volume_monitor_get();
+
+    g_signal_connect(m_gVolMonitor, "mount-removed",
+                     G_CALLBACK(unmountEvent), this);
+    g_signal_connect(m_gVolMonitor, "mount-added",
+                     G_CALLBACK(mountEvent), this);
+
+    GList* mounts=g_volume_monitor_get_mounts(m_gVolMonitor);
+    if( mounts )
+    {
+        for( guint i=0; i<g_list_length(mounts); i++ )
+        {
+            GMount* m=(GMount*)g_list_nth_data(mounts, i);
+            if(m && isMyDocs(m))
+            {
+                m_mounted = true;
+            }
+            g_object_unref(m);
+        }
+        g_list_free(mounts);
+    }
+
+    QDBusConnection conn = QDBusConnection::systemBus();
+    if( !conn.connect(USB_MODE_SERVICE,
+                      USB_MODE_OBJECT,
+                      USB_MODE_INTERFACE,
+                      USB_MODE_SIGNAL_NAME,
+                      this,
+                      SLOT(preUnmountEvent(QString))) )
+    {
+        qCritical() << "MafwGstRenderer could not connect to USB pre unmount signal!";
+    }
+}
+
+MafwMmcMonitor::~MafwMmcMonitor()
+{
+    g_object_unref(m_gVolMonitor);
+
+    QDBusConnection conn = QDBusConnection::systemBus();
+    conn.disconnect(USB_MODE_SERVICE,
+                    USB_MODE_OBJECT,
+                    USB_MODE_INTERFACE,
+                    USB_MODE_SIGNAL_NAME,
+                    this,
+                    SLOT(preUnmountEvent(QString)));
+}
+
+bool MafwMmcMonitor::isMounted()
+{
+    return m_mounted;
+}
+
+void MafwMmcMonitor::preUnmountEvent(const QString &state)
+{
+    //this slot will receive other information from usb_moded besides pre-unmount
+    if( state == USB_PRE_UNMOUNT )
+    {
+        qDebug() << "preUnmountEvent";
+        // This assumes that preunmount always affects MyDocs
+        Q_EMIT preUnmount();
+    }
+}
+
+void MafwMmcMonitor::unmountEvent(GVolumeMonitor * mon,
+                                       GMount  * mount,
+                                       gpointer userData)
+{
+    Q_UNUSED(mon);
+
+    qDebug() << "unmountEvent";
+
+    if( isMyDocs(mount) )
+    {
+        MafwMmcMonitor* self=static_cast<MafwMmcMonitor*>(userData);
+        self->m_mounted = false;
+    }
+}
+
+void MafwMmcMonitor::mountEvent(GVolumeMonitor * mon,
+                                       GMount  * mount,
+                                       gpointer userData)
+{
+    Q_UNUSED(mon);
+
+    qDebug() << "mountEvent";
+
+    if( isMyDocs(mount) )
+    {
+        MafwMmcMonitor* self=static_cast<MafwMmcMonitor*>(userData);
+        self->m_mounted = true;
+    }
+}
+
+bool MafwMmcMonitor::isMyDocs(GMount* mount)
+{
+    bool isIt=false;
+    GFile *root=0;
+    root = g_mount_get_root(mount);
+    if( root )
+    {
+        char* uri=g_file_get_uri(root);
+        if( uri && MMC_URI_PREFIX.compare(uri)==0 )
+        {
+            isIt=true;
+        }
+        qDebug() << "MafwMmcMonitor::isMyDocs" << uri << isIt;
+        g_free(uri);
+        g_object_unref(root);
+    }
+    return isIt;
+}
diff --git a/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-seeker.c b/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-seeker.c
new file mode 100644 (file)
index 0000000..07d7fc6
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "mafw-gst-renderer-seeker.h"
+
+#include <gst/gst.h>
+
+#define CLOSE_LIMIT 2
+#define MOVE_FORWARD 10
+
+typedef struct {
+    gint64 required_pos;
+    gint64 starting_pos;
+    gint64 current_pos;
+} seek_request;
+
+struct _MafwGstRendererSeeker {
+    GstElement *pipeline;
+    seek_request last_request;
+};
+
+gint64 _get_current_pos(GstElement* pipeline)
+{
+    GstFormat format = GST_FORMAT_TIME;
+    gint64 time = 0;
+
+    if(pipeline &&
+       gst_element_query_position(pipeline, &format, &time))
+    {
+        return (time + (GST_SECOND/2)) / GST_SECOND;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+gint64 _get_duration(GstElement *pipeline)
+{
+    gint64 value = -1;
+    GstFormat format = GST_FORMAT_TIME;
+
+    gboolean success = gst_element_query_duration(pipeline, &format, &value);
+    if( success )
+    {
+        return (value + (GST_SECOND/2)) / GST_SECOND;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+gboolean _try_seek_required_pos(MafwGstRendererSeeker *seeker)
+{
+    gboolean ret;
+    gint64 spos;
+    GstSeekFlags flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT;
+
+
+    spos = (seeker->last_request.required_pos) * GST_SECOND;
+    g_debug("seek target: %lld", spos);
+
+    ret = gst_element_seek(seeker->pipeline,
+                           1.0,
+                           GST_FORMAT_TIME,
+                           flags,
+                           GST_SEEK_TYPE_SET,
+                           spos,
+                           GST_SEEK_TYPE_NONE,
+                           GST_CLOCK_TIME_NONE);
+
+    return ret;
+}
+
+gboolean _is_position_close_enough(gint64 pos, gint64 required_pos)
+{
+    return ABS((pos - required_pos)) < CLOSE_LIMIT;
+}
+
+gboolean _has_position_changed_enough(gint64 pos, gint64 required_pos)
+{
+    return !_is_position_close_enough(pos, required_pos);
+}
+
+MafwGstRendererSeeker* mafw_gst_renderer_seeker_new()
+{
+    return g_new0(MafwGstRendererSeeker, 1);
+}
+
+void mafw_gst_renderer_seeker_free(MafwGstRendererSeeker *seeker)
+{
+    g_free(seeker);
+}
+
+void mafw_gst_renderer_seeker_set_pipeline(MafwGstRendererSeeker *seeker, GstElement *pipeline)
+{
+    seeker->pipeline = pipeline;
+    mafw_gst_renderer_seeker_cancel(seeker);
+}
+
+gboolean mafw_gst_renderer_seeker_seek_to(MafwGstRendererSeeker *seeker, gint64 seek_pos)
+{
+    if( seeker == NULL )
+    {
+        g_critical("Seeker is NULL!");
+        return FALSE;
+    }
+
+    seek_request *request = &(seeker->last_request);
+    request->required_pos = seek_pos;
+    request->starting_pos = _get_current_pos(seeker->pipeline);
+    request->current_pos = request->starting_pos;
+
+    return _try_seek_required_pos(seeker);
+
+}
+
+void mafw_gst_renderer_seeker_cancel(MafwGstRendererSeeker *seeker)
+{
+    seek_request *request = &(seeker->last_request);
+    request->current_pos = -1;
+    request->required_pos = -1;
+    request->starting_pos = -1;
+}
+
+gint64 mafw_gst_renderer_seeker_process(MafwGstRendererSeeker *seeker)
+{
+    if( seeker == NULL )
+    {
+        g_critical("Seeker is NULL!");
+        return -1;
+    }
+
+    seek_request *request = &(seeker->last_request);
+
+    if(request->required_pos < 0)
+    {
+        g_debug("[Seeker] No valid request set! Doing nothing,");
+        return request->required_pos;
+    }
+
+    request->current_pos = _get_current_pos(seeker->pipeline);
+    if( request->current_pos < 0 )
+    {
+        mafw_gst_renderer_seeker_cancel(seeker);
+        g_warning("[Seeker] Could not get position! Cannot refine seek!");
+        return seeker->last_request.current_pos;
+    }
+
+    gboolean forward_seek = ( request->required_pos >= request->starting_pos );
+
+    if( _is_position_close_enough(request->current_pos, request->required_pos)
+        ||
+        ((_has_position_changed_enough(request->current_pos, request->starting_pos)
+          && forward_seek
+          && request->current_pos > request->starting_pos)) )
+    {
+        g_debug("Got good enough seek result: Current pos: %lld, Required pos: %lld", request->current_pos, request->required_pos);
+        mafw_gst_renderer_seeker_cancel(seeker);
+    }
+    else
+    {
+        if( forward_seek )
+        {
+            request->required_pos += MOVE_FORWARD;
+            gint64 duration = _get_duration(seeker->pipeline);
+            if( request->required_pos > duration )
+            {
+                g_debug("[Seeker] Cancelling increased seek target beyond media length!");
+                mafw_gst_renderer_seeker_cancel(seeker);
+            }
+        }
+        else
+        {
+            g_debug("Backward seek done, cannot do better...");
+            mafw_gst_renderer_seeker_cancel(seeker);
+        }
+    }
+
+    if( request->required_pos >= 0 )
+    {
+        _try_seek_required_pos(seeker);
+    }
+
+    return request->required_pos;
+}
diff --git a/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-utils.c b/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-utils.c
new file mode 100644 (file)
index 0000000..49364fd
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * This file is a part of MAFW
+ *
+ * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.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; 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <string.h>
+#include <gio/gio.h>
+
+#include <gst/gst.h>
+
+#include "mafw-gst-renderer-utils.h"
+
+#undef  G_LOG_DOMAIN
+#define G_LOG_DOMAIN "mafw-gst-renderer-utils"
+
+/**
+ * convert_utf8:
+ * @src: string.
+ * @dst: location for utf8 version of @src.
+ *
+ * Tries to convert @src into UTF-8, placing it into @dst.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean convert_utf8(const gchar *src, gchar **dst)
+{
+    GError *error;
+
+    if (!src || !dst)
+        return FALSE;
+    if (g_utf8_validate(src, -1, NULL)) {
+        *dst = g_strdup(src);
+        return TRUE;
+    }
+    error = NULL;
+    *dst = g_locale_to_utf8(src, -1, NULL, NULL, &error);
+    if (error) {
+        g_warning("utf8 conversion failed '%s' (%d: %s)",
+              src, error->code, error->message);
+        g_error_free(error);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/**
+ * uri_is_stream:
+ * @uri: the URI to be checked.
+ *
+ * Check if given URI is a stream (not a local resource).  To not depend on
+ * gnomevfs for this, we assume everything that doesn't start with "file://" is
+ * a stream.
+ *
+ * Returns: TRUE if the URI is not local.
+ */
+gboolean uri_is_stream(const gchar *uri)
+{
+    if (uri == NULL) {
+        return FALSE;
+    } else {
+        return !g_str_has_prefix(uri, "file://");
+    }
+}
+
+/** remap_gst_error_code:
+ *
+ * @error: pointer to error
+ * 
+ * Maps a Gst error to worker errror code,
+ * mapping follows roughly the one from FMAFW gst-renderer.
+ *
+ * Returns: possibly remapped ecode if the domain was certain Gst domain.
+*/
+gint remap_gst_error_code(const GError *error)
+{
+
+    gint new_err_code;
+
+    if (error->domain == GST_RESOURCE_ERROR)
+    {
+        /* handle RESOURCE errors */
+        switch (error->code)
+        {
+            case GST_RESOURCE_ERROR_READ:
+                new_err_code = WORKER_ERROR_STREAM_DISCONNECTED;
+                break;
+            case GST_RESOURCE_ERROR_NOT_FOUND:
+            case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
+            case GST_RESOURCE_ERROR_OPEN_READ:
+                new_err_code = WORKER_ERROR_MEDIA_NOT_FOUND;
+                break;
+            case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
+                new_err_code = WORKER_ERROR_UNABLE_TO_PERFORM;
+                break;
+            case GST_RESOURCE_ERROR_WRITE:
+                /* DSP renderers send ERROR_WRITE when they find
+                   corrupted data */
+                new_err_code = WORKER_ERROR_CORRUPTED_FILE;
+                break;
+            case GST_RESOURCE_ERROR_SEEK:
+                new_err_code = WORKER_ERROR_CANNOT_SET_POSITION;
+                break;
+            default:
+                /* Unknown RESOURCE error */
+                new_err_code = WORKER_ERROR_UNABLE_TO_PERFORM;
+                break;
+        }
+    }
+    else if (error->domain == GST_STREAM_ERROR)
+    {
+        /* handle STREAM errors */
+        switch (error->code) {
+            case GST_STREAM_ERROR_TYPE_NOT_FOUND:
+                new_err_code = WORKER_ERROR_TYPE_NOT_AVAILABLE;
+                break;
+            case GST_STREAM_ERROR_FORMAT:
+            case GST_STREAM_ERROR_WRONG_TYPE:
+            case GST_STREAM_ERROR_FAILED:
+                new_err_code = WORKER_ERROR_UNSUPPORTED_TYPE;
+                break;
+            case GST_STREAM_ERROR_DECODE:
+            case GST_STREAM_ERROR_DEMUX:
+                new_err_code = WORKER_ERROR_CORRUPTED_FILE;
+                break;
+            case GST_STREAM_ERROR_CODEC_NOT_FOUND:
+                new_err_code = WORKER_ERROR_CODEC_NOT_FOUND;
+                break;
+            case GST_STREAM_ERROR_DECRYPT:
+            case GST_STREAM_ERROR_DECRYPT_NOKEY:
+                new_err_code = WORKER_ERROR_DRM_NOT_ALLOWED;
+                break;
+            case WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE:
+                new_err_code = WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE;
+                break;
+            default:
+                /* Unknown STREAM error */
+                new_err_code = WORKER_ERROR_UNABLE_TO_PERFORM;
+                break;
+        }
+    }
+    else if( error->domain == GST_CORE_ERROR )
+    {
+        switch( error->code ) {
+            case GST_CORE_ERROR_MISSING_PLUGIN:
+                new_err_code = WORKER_ERROR_UNSUPPORTED_TYPE;
+                break;
+            default:
+                new_err_code = error->code;
+        }
+    }
+    else
+    {
+        /* by default return the original code */
+        new_err_code = error->code;
+    }
+
+    return new_err_code;
+
+}
+
+/*
+ * Imported from totem-uri.c
+ * Copyright (C) 2004 Bastien Nocera
+ */
+
+/* List from xine-lib's demux_sputext.c */
+static const char subtitle_ext[][4] = {
+    "sub",
+    "srt",
+    "smi",
+    "ssa",
+    "ass",
+    "asc"
+};
+
+static inline gboolean
+uri_exists (const char *uri)
+{
+    GFile *file = g_file_new_for_uri (uri);
+    if (file != NULL) {
+        if (g_file_query_exists (file, NULL)) {
+            g_object_unref (file);
+                return TRUE;
+        }
+        g_object_unref (file);
+    }
+    return FALSE;
+}
+
+static char *
+uri_get_subtitle_for_uri (const char *uri)
+{
+    char *subtitle;
+    guint len, i;
+    gint suffix;
+
+    /* Find the filename suffix delimiter */
+    len = strlen (uri);
+    for (suffix = len - 1; suffix > 0; suffix--) {
+        if (uri[suffix] == G_DIR_SEPARATOR ||
+            (uri[suffix] == '/')) {
+                /* This filename has no extension; we'll need to 
+                 * add one */
+                suffix = len;
+                break;
+        }
+        if (uri[suffix] == '.') {
+            /* Found our extension marker */
+            break;
+        }
+    }
+    if (suffix < 0)
+        return NULL;
+
+    /* Generate a subtitle string with room at the end to store the
+     * 3 character extensions for which we want to search */
+    subtitle = g_malloc0 (suffix + 4 + 1);
+    g_return_val_if_fail (subtitle != NULL, NULL);
+    g_strlcpy (subtitle, uri, suffix + 4 + 1);
+    g_strlcpy (subtitle + suffix, ".???", 5);
+
+    /* Search for any files with one of our known subtitle extensions */
+    for (i = 0; i < G_N_ELEMENTS (subtitle_ext) ; i++) {
+        char *subtitle_ext_upper;
+        memcpy (subtitle + suffix + 1, subtitle_ext[i], 3);
+
+        if (uri_exists (subtitle))
+            return subtitle;
+
+        /* Check with upper-cased extension */
+        subtitle_ext_upper = g_ascii_strup (subtitle_ext[i], -1);
+        memcpy (subtitle + suffix + 1, subtitle_ext_upper, 3);
+        g_free (subtitle_ext_upper);
+
+        if (uri_exists (subtitle))
+            return subtitle;
+    }
+    g_free (subtitle);
+    return NULL;
+}
+
+static char *
+uri_get_subtitle_in_subdir (GFile *file, const char *subdir)
+{
+    char *filename, *subtitle, *full_path_str;
+    GFile *parent, *full_path, *directory;
+
+    /* Get the sibling directory @subdir of the file @file */
+    parent = g_file_get_parent (file);
+    directory = g_file_get_child (parent, subdir);
+    g_object_unref (parent);
+
+    /* Get the file of the same name as @file in the @subdir directory */
+    filename = g_file_get_basename (file);
+    full_path = g_file_get_child (directory, filename);
+    g_object_unref (directory);
+    g_free (filename);
+
+    /* Get the subtitles from that URI */
+    full_path_str = g_file_get_uri (full_path);
+    g_object_unref (full_path);
+    subtitle = uri_get_subtitle_for_uri (full_path_str);
+    g_free (full_path_str);
+
+    return subtitle;
+}
+
+char *
+uri_get_subtitle_uri (const char *uri)
+{
+    GFile *file;
+    char *subtitle;
+
+    if (g_str_has_prefix (uri, "http") != FALSE)
+        return NULL;
+
+    /* Has the user specified a subtitle file manually? */
+    if (strstr (uri, "#subtitle:") != NULL)
+        return NULL;
+
+    /* Does the file exist? */
+    file = g_file_new_for_uri (uri);
+    if (g_file_query_exists (file, NULL) != TRUE) {
+        g_object_unref (file);
+        return NULL;
+    }
+
+    /* Try in the current directory */
+    subtitle = uri_get_subtitle_for_uri (uri);
+    if (subtitle != NULL) {
+        g_object_unref (file);
+        return subtitle;
+    }
+
+    subtitle = uri_get_subtitle_in_subdir (file, "subtitles");
+    g_object_unref (file);
+
+    return subtitle;
+}
diff --git a/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-worker.c b/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-worker.c
new file mode 100644 (file)
index 0000000..eeceb39
--- /dev/null
@@ -0,0 +1,3105 @@
+/*
+ * This file is a part of MAFW
+ *
+ * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.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; 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
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/pbutils/missing-plugins.h>
+#include <gst/base/gstbasesink.h>
+#include <context_provider.h>
+
+#include "mafw-gst-renderer-worker.h"
+#include "mafw-gst-renderer-utils.h"
+
+#define UNUSED(x) (void)(x)
+
+/* context provider DBus name must be the same as the .context file name without
+ * the .context suffix, service name in the .context file must be the same too */
+#define CONTEXT_PROVIDER_BUS_NAME       "com.nokia.mafw.context_provider.libqmafw_gst_renderer"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING "Media.NowPlaying"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_TITLE    "title"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_ALBUM    "album"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_ARTIST   "artist"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_GENRE    "genre"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_RESOURCE "resource"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_DURATION "duration"
+
+#define WORKER_ERROR g_quark_from_static_string("com.nokia.mafw.error.renderer")
+
+#define MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LAZY_TIMEOUT 4000
+#define MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_FAST_TIMEOUT 200
+#define MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LOOP_LIMIT 10
+#define MAFW_GST_MISSING_TYPE_DECODER "decoder"
+#define MAFW_GST_MISSING_TYPE_ENCODER "encoder"
+
+#define MAFW_TMP_URI_LEN 2048
+
+#define STREAM_TYPE_MMS "mms://"
+#define STREAM_TYPE_MMSH "mmsh://"
+#define MAFW_GST_MMSH_CONNECTION_SPEED "2000"       /* kbit/s */
+#define MAFW_GST_MMSH_TCP_TIMEOUT "30000000"        /* microseconds */
+
+/* struct needed when emitting renderer art/frames as image files */
+typedef struct {
+    MafwGstRendererWorker *worker;
+    gint metadata_key;
+    const gchar *filename;
+} SaveGraphicData;
+
+/* Forward declarations. */
+static void _do_play(MafwGstRendererWorker *worker);
+
+static void _do_seek(MafwGstRendererWorker *worker,
+                     GstSeekType seek_type,
+                     gint position,
+                     gboolean key_frame_seek,
+                     GError **error);
+
+static gboolean _set_value(GValue *v, GType type, gconstpointer value);
+
+static void _emit_metadatas(MafwGstRendererWorker *worker);
+
+static gboolean _current_metadata_add(MafwGstRendererWorker *worker,
+                                      const gint key,
+                                      GType type,
+                                      const gpointer value);
+
+static gpointer _set_context_map_value(gpointer map,
+                                       const gchar *tag,
+                                       const gchar *value);
+
+/*
+ * Is used to prevent a critical log from context fw in case of multiple initialisations.
+ * Common to all renderers in the process.
+ */
+static gboolean _context_fw_initialised = FALSE;
+
+/*
+ * Sends @error to MafwGstRenderer.  Only call this from the glib main thread,
+ * or face the consequences.  @err is free'd.
+ */
+static void _send_error(MafwGstRendererWorker *worker, GError *err)
+{
+    worker->is_error = TRUE;
+    if (worker->notify_error_handler)
+    {
+        /* remap a possible gst ecode to worker ecode */
+        err->code = remap_gst_error_code(err);
+        worker->notify_error_handler(worker, worker->owner, err);
+    }
+    g_error_free(err);
+}
+
+configuration* _create_default_configuration()
+{
+    configuration *config = g_malloc0(sizeof(configuration));
+    config->asink = g_strdup("pulsesink");
+    config->vsink = g_strdup("omapxvsink");
+    config->flags = 71;
+    config->buffer_time = 600000; /* microseconds */
+    config->latency_time = 100000; /* microseconds */
+    config->autoload_subtitles = TRUE;
+    config->subtitle_encoding = NULL;
+    config->subtitle_font = g_strdup("Sans Bold 18");
+
+    /* timers */
+    config->milliseconds_to_pause_frame = 700; /* milliseconds */
+    config->seconds_to_pause_to_ready = 3; /* seconds */
+
+    /* dhmmixer */
+    config->use_dhmmixer = TRUE;
+
+    config->mobile_surround_music.state = 0;
+    config->mobile_surround_music.room = 2;
+    config->mobile_surround_music.color = 2;
+    config->mobile_surround_video.state = 0;
+    config->mobile_surround_video.room = 2;
+    config->mobile_surround_video.color = 2;
+
+    return config;
+}
+
+void _free_configuration(configuration* config)
+{
+    g_free(config->asink);
+    g_free(config->vsink);
+
+    g_free(config);
+}
+
+/*
+ * Posts an @error on the gst bus.  _async_bus_handler will then pick it up and
+ * forward to MafwGstRenderer.  @err is free'd.
+ */
+static void _post_error(MafwGstRendererWorker *worker, GError *err)
+{
+    gst_bus_post(worker->bus,
+                 gst_message_new_error(GST_OBJECT(worker->pipeline),
+                                       err,
+                                       NULL));
+    g_error_free(err);
+}
+
+static gboolean _set_value(GValue *v, GType type, gconstpointer value)
+{
+
+    gboolean ret = TRUE;
+
+    if (v && value)
+    {
+        memset(v, 0, sizeof(GValue));
+        g_value_init(v, type);
+
+        if (type == G_TYPE_STRING) {
+            g_value_set_string(v, (const gchar*)value);
+        }
+        else if (type == G_TYPE_INT) {
+            g_value_set_int(v, *(gint*)value);
+        }
+        else if (type == G_TYPE_UINT) {
+            g_value_set_uint(v, *(uint*)value);
+        }
+        else if (type == G_TYPE_DOUBLE) {
+            g_value_set_double(v, *(gdouble*)value);
+        }
+        else if (type == G_TYPE_BOOLEAN) {
+            g_value_set_boolean(v, *(gboolean*)value);
+        }
+        else if (type == G_TYPE_INT64) {
+            g_value_set_int64(v, *(gint64*)value);
+        }
+        else if (type == G_TYPE_FLOAT) {
+            g_value_set_float(v, *(gfloat*)value);
+        }
+        else if (type == G_TYPE_VALUE_ARRAY) {
+            g_value_copy((GValue*)value,v);
+        }
+        else {
+            g_warning("%s: unknown g_type", G_STRFUNC);
+            ret = FALSE;
+        }
+    }
+    else
+    {
+        ret = FALSE;
+    }
+
+    return ret;
+
+}
+
+static void _emit_metadata(MafwGstRendererWorker *worker,
+                           gint metadata_key,
+                           GType type,
+                           gconstpointer value)
+{
+
+    GValue v;
+
+    if (worker && worker->notify_metadata_handler &&
+        _set_value(&v, type, value))
+    {
+        GValueArray *array = g_value_array_new(0);
+        g_value_array_append(array, &v);
+        worker->notify_metadata_handler(worker,
+                                        worker->owner,
+                                        metadata_key,
+                                        G_TYPE_VALUE_ARRAY,
+                                        array);
+        g_value_array_free(array);
+        g_value_unset(&v);
+    }
+
+}
+
+static void _emit_property(MafwGstRendererWorker *worker,
+                           gint property,
+                           GType type,
+                           gconstpointer value)
+{
+
+    GValue v;
+
+    if (worker && worker->notify_property_handler &&
+        _set_value(&v, type, value))
+    {
+        worker->notify_property_handler(worker, worker->owner, property, &v);
+        g_value_unset(&v);
+    }
+
+}
+
+static gchar *_init_tmp_file(void)
+{
+    gint fd;
+    gchar *path = NULL;
+
+    fd = g_file_open_tmp("mafw-gst-renderer-XXXXXX.picture", &path, NULL);
+    if (fd >= 0 )
+    {
+        close(fd);
+    }
+
+    return path;
+}
+
+static void _destroy_tmp_file(MafwGstRendererWorker *worker, guint index)
+{
+    g_unlink(worker->tmp_files_pool[index]);
+    g_free(worker->tmp_files_pool[index]);
+    worker->tmp_files_pool[index] = NULL;
+}
+
+static void _init_tmp_files_pool(MafwGstRendererWorker *worker)
+{
+    guint8 i;
+
+    worker->tmp_files_pool_index = 0;
+
+    for (i = 0; i < MAFW_GST_RENDERER_MAX_TMP_FILES; i++) {
+        worker->tmp_files_pool[i] = NULL;
+    }
+}
+
+static void _destroy_tmp_files_pool(MafwGstRendererWorker *worker)
+{
+    guint8 i;
+
+    for (i = 0; (i < MAFW_GST_RENDERER_MAX_TMP_FILES) &&
+         (worker->tmp_files_pool[i] != NULL); i++) {
+        g_unlink(worker->tmp_files_pool[i]);
+        g_free(worker->tmp_files_pool[i]);
+    }
+}
+
+static const gchar *_get_tmp_file_from_pool(MafwGstRendererWorker *worker)
+{
+    gchar *path = worker->tmp_files_pool[worker->tmp_files_pool_index];
+
+    if (path == NULL) {
+        path = _init_tmp_file();
+        worker->tmp_files_pool[worker->tmp_files_pool_index] = path;
+    }
+    else
+    {
+        _destroy_tmp_file(worker, worker->tmp_files_pool_index);
+        path = _init_tmp_file();
+        worker->tmp_files_pool[worker->tmp_files_pool_index] = path;
+    }
+
+    if (++(worker->tmp_files_pool_index) >= MAFW_GST_RENDERER_MAX_TMP_FILES) {
+        worker->tmp_files_pool_index = 0;
+    }
+
+    return path;
+}
+
+static void _emit_gst_buffer_as_graphic_file_cb(GError *error,
+                                                gpointer user_data)
+{
+    SaveGraphicData *sgd = user_data;
+
+    if (error == NULL) {
+        /* Add the info to the current metadata. */
+        _current_metadata_add(sgd->worker,
+                              sgd->metadata_key,
+                              G_TYPE_STRING,
+                              (const gpointer)sgd->filename);
+
+        /* Emit the metadata. */
+        _emit_metadata(sgd->worker,
+                       sgd->metadata_key,
+                       G_TYPE_STRING,
+                       sgd->filename);
+    }
+    else
+    {
+        g_warning("could not emit graphic file: %s", error->message);
+    }
+
+    g_free(sgd);
+}
+
+static void _emit_gst_buffer_as_graphic_file(MafwGstRendererWorker *worker,
+                                             GstBuffer *buffer,
+                                             const gint metadata_key)
+{
+    GstStructure *structure;
+    const gchar *mime = NULL;
+    GError *error = NULL;
+    SaveGraphicData *sgd;
+
+    g_return_if_fail((buffer != NULL) && GST_IS_BUFFER(buffer));
+
+    structure = gst_caps_get_structure(GST_BUFFER_CAPS(buffer), 0);
+    mime = gst_structure_get_name(structure);
+
+    /* video pause frame related branch */
+    if (g_str_has_prefix(mime, "video/x-raw")) {
+        const gchar *filename = _get_tmp_file_from_pool(worker);
+
+        if(worker->taking_screenshot)
+        {
+            worker->screenshot_handler(worker, worker->owner, NULL, NULL, TRUE);
+        }
+        worker->taking_screenshot = TRUE;
+        worker->screenshot_handler(worker, worker->owner, buffer, filename, FALSE);
+
+    /* gst image tag related branch */
+    } else if (g_str_has_prefix(mime, "image/")) {
+
+        sgd = g_new0(SaveGraphicData, 1);
+        sgd->worker = worker;
+        sgd->metadata_key = metadata_key;
+        sgd->filename = _get_tmp_file_from_pool(worker);
+
+        g_debug("dumping gst image %s directly to a file", mime);
+        g_file_set_contents(sgd->filename,
+                            (const gchar*)GST_BUFFER_DATA(buffer),
+                            GST_BUFFER_SIZE(buffer),
+                            &error);
+        _emit_gst_buffer_as_graphic_file_cb(error, sgd);
+        if (error) {
+            g_error_free(error);
+        }
+    } else {
+        g_warning("Mime type not supported, will not create a thumbnail");
+        gst_buffer_unref(buffer);
+    }
+}
+
+static gboolean _go_to_gst_ready(gpointer user_data)
+{
+    g_debug("_go_to_gst_ready");
+    MafwGstRendererWorker *worker = user_data;
+
+    g_return_val_if_fail(worker->state == GST_STATE_PAUSED ||
+                         worker->prerolling, FALSE);
+
+    worker->seek_position = mafw_gst_renderer_worker_get_position(worker);
+
+    g_debug("going to GST_STATE_READY");
+    gst_element_set_state(worker->pipeline, GST_STATE_READY);
+    worker->in_ready = TRUE;
+    return FALSE;
+}
+
+static void _add_ready_timeout(MafwGstRendererWorker *worker)
+{
+    if( worker->ready_timeout == 0 )
+    {
+        g_debug("Adding timeout to go to GST_STATE_READY");
+        worker->ready_timeout =
+                g_timeout_add_seconds(
+                    worker->config->seconds_to_pause_to_ready,
+                    _go_to_gst_ready,
+                    worker);
+    }
+}
+
+static void _remove_ready_timeout(MafwGstRendererWorker *worker)
+{
+    if( worker->ready_timeout != 0 )
+    {
+        g_debug("removing timeout for READY");
+        g_source_remove(worker->ready_timeout);
+        worker->ready_timeout = 0;
+    }
+}
+
+static gboolean _take_pause_frame(gpointer user_data)
+{
+    MafwGstRendererWorker *worker = user_data;
+
+    if( worker->pause_frame_taken && worker->pause_frame_buffer )
+    {
+        gst_buffer_unref(worker->pause_frame_buffer);
+        worker->pause_frame_buffer = NULL;
+        return FALSE;
+    }
+
+    if (worker->pause_frame_buffer != NULL) {
+        worker->pause_frame_taken = TRUE;
+        _emit_gst_buffer_as_graphic_file(
+            worker,
+            worker->pause_frame_buffer,
+            WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI);
+        worker->pause_frame_buffer = NULL;
+    }
+    return FALSE;
+}
+
+static void _add_pause_frame_timeout(MafwGstRendererWorker *worker)
+{
+    if (worker->media.has_visual_content && worker->current_frame_on_pause && worker->seek_position == -1)
+    {            
+        if (!worker->pause_frame_timeout)
+        {
+            GstBuffer *buffer = NULL;
+            g_object_get(worker->pipeline, "frame", &buffer, NULL);
+            if( buffer )
+            {
+                GstBuffer *copy = gst_buffer_copy(buffer);
+                gst_buffer_copy_metadata(copy, buffer, GST_BUFFER_COPY_ALL);
+                worker->pause_frame_buffer = copy;
+                gst_buffer_unref(buffer);
+
+                g_debug("Adding timeout to go to current frame capture");
+                worker->pause_frame_timeout =
+                        g_timeout_add_full(
+                                G_PRIORITY_DEFAULT,
+                                worker->config->milliseconds_to_pause_frame,
+                                _take_pause_frame,
+                                worker, NULL);
+            }
+            else
+            {
+                g_warning("MafwGstRenderer Worker: Could not get buffer from pipeline! Maybe at EOS?");
+            }
+        }
+    } else {
+        g_debug("Not adding timeout to take pause frame.");
+        worker->pause_frame_timeout = 0;
+    }
+}
+
+static void _remove_pause_frame_timeout(MafwGstRendererWorker *worker)
+{
+    if (worker->pause_frame_timeout != 0) {
+        g_debug("removing timeout for pause frame!");
+        g_source_remove(worker->pause_frame_timeout);
+        worker->pause_frame_timeout = 0;
+    }
+
+    if(worker->taking_screenshot)
+    {
+        worker->screenshot_handler(worker, worker->owner, NULL, NULL, TRUE);
+        worker->taking_screenshot = FALSE;
+    }
+    else
+    {
+        /* in this case the buffer has not been given to the
+         * screenshot component to be processed */
+        if(worker->pause_frame_buffer)
+        {
+            gst_buffer_unref(worker->pause_frame_buffer);
+            worker->pause_frame_buffer = NULL;
+        }
+    }
+}
+
+static gboolean _emit_video_info(MafwGstRendererWorker *worker)
+{
+
+    _emit_metadata(worker,
+                   WORKER_METADATA_KEY_RES_X,
+                   G_TYPE_INT,
+                   &worker->media.video_width);
+
+    _emit_metadata(worker,
+                   WORKER_METADATA_KEY_RES_Y,
+                   G_TYPE_INT,
+                   &worker->media.video_height);
+
+    _emit_metadata(worker,
+                   WORKER_METADATA_KEY_VIDEO_FRAMERATE,
+                   G_TYPE_DOUBLE,
+                   &worker->media.fps);
+
+    return FALSE;
+
+}
+
+/*
+ * Checks if the video details are supported.  It also extracts other useful
+ * information (such as PAR and framerate) from the caps, if available.  NOTE:
+ * this will be called from a different thread than glib's mainloop (when
+ * invoked via _stream_info_cb);  don't call MafwGstRenderer directly.
+ *
+ * Returns: TRUE if video details are acceptable.
+ */
+static gboolean _handle_video_info(MafwGstRendererWorker *worker,
+                                   const GstStructure *structure)
+{
+    gint width, height;
+    gdouble fps;
+
+    width = height = 0;
+    gst_structure_get_int(structure, "width", &width);
+    gst_structure_get_int(structure, "height", &height);
+    g_debug("video size: %d x %d", width, height);
+    if (gst_structure_has_field(structure, "pixel-aspect-ratio"))
+    {
+        gst_structure_get_fraction(structure,
+                                   "pixel-aspect-ratio",
+                                   &worker->media.par_n,
+                                   &worker->media.par_d);
+        g_debug("video PAR: %d:%d", worker->media.par_n, worker->media.par_d);
+        width = width * worker->media.par_n / worker->media.par_d;
+    }
+
+    fps = 1.0;
+    if (gst_structure_has_field(structure, "framerate"))
+    {
+        gint fps_n, fps_d;
+
+        gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d);
+        if (fps_d > 0) {
+            fps = (gdouble)fps_n / (gdouble)fps_d;
+        }
+        g_debug("video fps: %f", fps);
+    }
+
+    worker->media.video_width = width;
+    worker->media.video_height = height;
+    worker->media.fps = fps;
+
+    _current_metadata_add(worker, WORKER_METADATA_KEY_RES_X, G_TYPE_INT,
+                          (const gpointer)&width);
+    _current_metadata_add(worker, WORKER_METADATA_KEY_RES_Y, G_TYPE_INT,
+                          (const gpointer)&height);
+    _current_metadata_add(worker, WORKER_METADATA_KEY_VIDEO_FRAMERATE,
+                          G_TYPE_DOUBLE, (const gpointer)&fps);
+
+    /* Emit the metadata.*/
+    g_idle_add((GSourceFunc)_emit_video_info, worker);
+    return TRUE;
+}
+
+static void _parse_stream_info_item(MafwGstRendererWorker *worker, GObject *obj)
+{
+    GParamSpec *pspec;
+    GEnumValue *val;
+    gint type;
+
+    g_object_get(obj, "type", &type, NULL);
+    pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), "type");
+    if(!pspec)
+        return;
+    val = g_enum_get_value(G_PARAM_SPEC_ENUM(pspec)->enum_class, type);
+    if (!val)
+        return;
+    if (!g_ascii_strcasecmp(val->value_nick, "video") ||
+        !g_ascii_strcasecmp(val->value_name, "video"))
+    {
+        GstCaps *vcaps;
+        GstObject *object;
+
+        object = NULL;
+        g_object_get(obj, "object", &object, NULL);
+        vcaps = NULL;
+        if (object) {
+            vcaps = gst_pad_get_caps(GST_PAD_CAST(object));
+        } else {
+            g_object_get(obj, "caps", &vcaps, NULL);
+            gst_caps_ref(vcaps);
+        }
+        if (vcaps) {
+            if (gst_caps_is_fixed(vcaps))
+            {
+                _handle_video_info(worker, gst_caps_get_structure(vcaps, 0));
+            }
+            gst_caps_unref(vcaps);
+        }
+    }
+}
+
+/* It always returns FALSE, because it is used as an idle callback as well. */
+static gboolean _parse_stream_info(MafwGstRendererWorker *worker)
+{
+    GList *stream_info, *s;
+
+    stream_info = NULL;
+    if (g_object_class_find_property(G_OBJECT_GET_CLASS(worker->pipeline),
+                                     "stream-info"))
+    {
+        g_object_get(worker->pipeline, "stream-info", &stream_info, NULL);
+    }
+    for (s = stream_info; s; s = g_list_next(s))
+        _parse_stream_info_item(worker, G_OBJECT(s->data));
+    return FALSE;
+}
+
+static void mafw_gst_renderer_worker_apply_xid(MafwGstRendererWorker *worker)
+{
+    /* Set sink to render on the provided XID if we have do have
+       a XID a valid video sink and we are rendering video content */
+    if (worker->xid &&
+        worker->vsink &&
+        worker->media.has_visual_content)
+    {
+        g_debug ("Setting overlay, window id: %x", (gint) worker->xid);
+        gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(worker->vsink), worker->xid);
+
+
+        /* Ask the gst to redraw the frame if we are paused */
+        /* TODO: in MTG this works only in non-fs -> fs way. */
+        if (worker->state == GST_STATE_PAUSED)
+        {
+            gst_x_overlay_expose(GST_X_OVERLAY(worker->vsink));
+        }
+    } else {
+        g_debug("Not setting overlay for window id: %x", (gint) worker->xid);
+    }
+}
+
+static void mafw_gst_renderer_worker_apply_render_rectangle(MafwGstRendererWorker *worker)
+{
+    /* Set sink to render on the provided XID if we have do have
+       a XID a valid video sink and we are rendering video content */
+    if (worker->xid &&
+        worker->vsink &&
+        worker->media.has_visual_content
+        &&
+        (worker->x_overlay_rectangle.x >= 0 &&
+         worker->x_overlay_rectangle.y >= 0 &&
+         worker->x_overlay_rectangle.width >= 0 &&
+         worker->x_overlay_rectangle.height >= 0) )
+    {
+        g_debug("Applying render rectangle: X:%d,Y:%d  Width:%d, Height:%d",
+                worker->x_overlay_rectangle.x,
+                worker->x_overlay_rectangle.y,
+                worker->x_overlay_rectangle.width,
+                worker->x_overlay_rectangle.height);
+
+        gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(worker->vsink),
+                                           worker->x_overlay_rectangle.x,
+                                           worker->x_overlay_rectangle.y,
+                                           worker->x_overlay_rectangle.width,
+                                           worker->x_overlay_rectangle.height);
+        /* Ask the gst to redraw the frame if we are paused */
+        /* TODO: in MTG this works only in non-fs -> fs way. */
+        if (worker->state == GST_STATE_PAUSED)
+        {
+            gst_x_overlay_expose(GST_X_OVERLAY(worker->vsink));
+        }
+
+    } else {
+        g_debug("Not setting render rectangle for window id: %x", (gint) worker->xid);
+    }
+}
+
+/*
+ * GstBus synchronous message handler.  NOTE that this handler is NOT invoked
+ * from the glib thread, so be careful what you do here.
+ */
+static GstBusSyncReply _sync_bus_handler(GstBus *bus,
+                                         GstMessage *msg,
+                                         MafwGstRendererWorker *worker)
+{
+
+    UNUSED(bus);
+
+    if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ELEMENT &&
+        gst_structure_has_name(msg->structure, "prepare-xwindow-id"))
+    {
+        g_debug("got prepare-xwindow-id");
+        worker->media.has_visual_content = TRUE;
+        set_dolby_video_property(worker, worker->config->mobile_surround_video.state);
+        set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.room, TRUE);
+        set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.color, FALSE);
+        /* The user has to preset the XID, we don't create windows by
+         * ourselves. */
+        if (!worker->xid || !worker->vsink) {
+            /* We must post an error message to the bus that will be picked up
+             * by _async_bus_handler.  Calling the notification function
+             * directly from here (different thread) is not healthy. */
+            g_warning("No video window or video-sink set!");
+            _post_error(worker,
+                        g_error_new_literal(WORKER_ERROR,
+                                            WORKER_ERROR_PLAYBACK,
+                                            "No video window XID or video-sink set"));
+            gst_message_unref (msg);
+            return GST_BUS_DROP;
+        } else {
+            g_debug ("Video window to use is: %x", (gint)worker->xid);
+        }
+
+        /* Instruct vsink to use the client-provided window */
+        mafw_gst_renderer_worker_apply_xid(worker);
+        /* Instruct vsink to use the required render rectangle */
+        mafw_gst_renderer_worker_apply_render_rectangle(worker);
+
+        /* Handle colorkey and autopaint */
+        mafw_gst_renderer_worker_set_autopaint(worker, worker->autopaint);
+        g_object_get(worker->vsink, "colorkey", &worker->colorkey, NULL);
+        /* Defer the signal emission to the thread running the mainloop. */
+        if (worker->colorkey != -1) {
+            gst_bus_post(worker->bus,
+                         gst_message_new_application(
+                             GST_OBJECT(worker->vsink),
+                             gst_structure_empty_new("ckey")));
+        }
+        gst_message_unref (msg);
+        return GST_BUS_DROP;
+    }
+    /* do not unref message when returning PASS */
+    return GST_BUS_PASS;
+}
+
+static void _free_taglist_item(GstMessage *msg, gpointer data)
+{
+    UNUSED(data);
+
+    gst_message_unref(msg);
+}
+
+static void _free_taglist(MafwGstRendererWorker *worker)
+{
+    if (worker->tag_list != NULL)
+    {
+        g_ptr_array_foreach(worker->tag_list, (GFunc)_free_taglist_item, NULL);
+        g_ptr_array_free(worker->tag_list, TRUE);
+        worker->tag_list = NULL;
+    }
+}
+
+static gboolean _seconds_duration_equal(gint64 duration1, gint64 duration2)
+{
+    gint64 duration1_seconds, duration2_seconds;
+
+    duration1_seconds = duration1 / GST_SECOND;
+    duration2_seconds = duration2 / GST_SECOND;
+
+    return duration1_seconds == duration2_seconds;
+}
+
+static void _check_duration(MafwGstRendererWorker *worker, gint64 value)
+{
+    gboolean right_query = TRUE;
+
+    if (value == -1) {
+        GstFormat format = GST_FORMAT_TIME;
+        right_query =
+            gst_element_query_duration(worker->pipeline, &format, &value);
+    }
+
+    if (right_query && value > 0
+            && !_seconds_duration_equal(worker->media.length_nanos, value))
+    {
+        gint64 duration = (value + (GST_SECOND/2)) / GST_SECOND;
+
+        /* Add the duration to the current metadata. */
+        if( _current_metadata_add(worker,
+                                  WORKER_METADATA_KEY_DURATION,
+                                  G_TYPE_INT64,
+                                  (const gpointer)&duration) )
+        {
+            _emit_metadata(worker,
+                           WORKER_METADATA_KEY_DURATION,
+                           G_TYPE_INT64,
+                           &duration);
+        }
+
+         /* Publish to context FW */
+        if( worker->context_nowplaying == NULL )
+        {
+            worker->context_nowplaying = context_provider_map_new();
+        }
+        context_provider_map_set_integer(worker->context_nowplaying,
+                                         CONTEXT_PROVIDER_KEY_NOWPLAYING_DURATION,
+                                         duration);
+        context_provider_set_map(CONTEXT_PROVIDER_KEY_NOWPLAYING,
+                                 worker->context_nowplaying, FALSE);
+         /* end of publishing to context FW */
+    }
+
+    if( right_query )
+    {
+        worker->media.length_nanos = value;
+    }
+
+    g_debug("media duration: %lld", worker->media.length_nanos);
+}
+
+static void _check_seekability(MafwGstRendererWorker *worker)
+{
+    SeekabilityType seekable = SEEKABILITY_UNKNOWN;
+    if (worker->media.length_nanos >= 0 )
+    {
+        g_debug("Quering GStreamer for seekability");
+        GstQuery *seek_query;
+        GstFormat format = GST_FORMAT_TIME;
+        /* Query the seekability of the stream */
+        seek_query = gst_query_new_seeking(format);
+        if (gst_element_query(worker->pipeline, seek_query)) {
+            gboolean renderer_seekable = FALSE;
+            gst_query_parse_seeking(seek_query,
+                                    NULL,
+                                    &renderer_seekable,
+                                    NULL, NULL);
+            g_debug("GStreamer seekability %d", renderer_seekable);
+            seekable = renderer_seekable ? SEEKABILITY_SEEKABLE : SEEKABILITY_NO_SEEKABLE;
+        }
+        else
+        {
+            g_debug("Could not query pipeline for seekability! Using old value!");
+            seekable = worker->media.seekable;
+        }
+        gst_query_unref(seek_query);
+    }
+    else if( worker->media.length_nanos == DURATION_INDEFINITE )
+    {
+        /* duration indefinite, "clearly" not seekable */
+        seekable = SEEKABILITY_NO_SEEKABLE;
+    }
+    else
+    {
+        /* otherwise we'll use last known/guessed value */
+        seekable = worker->media.seekable;
+    }
+
+    g_debug("media seekable: %d", seekable);
+
+    /* If the seekability is unknown it is set as false and sent. After that it is
+       sent only if it changes to true
+       */
+    if( (seekable == SEEKABILITY_UNKNOWN && worker->media.seekable == SEEKABILITY_UNKNOWN)
+        || seekable != worker->media.seekable )
+    {
+        if( seekable != SEEKABILITY_NO_SEEKABLE )
+        {
+            worker->media.seekable = SEEKABILITY_SEEKABLE;
+        }
+        else
+        {
+            worker->media.seekable =  SEEKABILITY_NO_SEEKABLE;
+        }
+
+        gboolean is_seekable = (worker->media.seekable == SEEKABILITY_SEEKABLE);
+        _current_metadata_add(worker,
+                              WORKER_METADATA_KEY_IS_SEEKABLE,
+                              G_TYPE_BOOLEAN,
+                              (const gpointer)&is_seekable);
+        _emit_metadata(worker,
+                       WORKER_METADATA_KEY_IS_SEEKABLE,
+                       G_TYPE_BOOLEAN,
+                       &is_seekable);
+    }
+}
+
+static gboolean _query_duration_and_seekability_timeout(gpointer data)
+{
+    MafwGstRendererWorker *worker = data;
+
+    if (!worker->in_ready)
+    {
+        _check_duration(worker, -1);
+        worker->duration_seek_timeout_loop_count += 1;
+
+        /* for worker's internal logic let's put the indefinite duration if loop limit has been reached */
+        /* this affects the seekability resolution */
+        if( worker->duration_seek_timeout_loop_count >= MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LOOP_LIMIT
+            && worker->media.length_nanos == DURATION_UNQUERIED )
+        {
+            worker->media.length_nanos = DURATION_INDEFINITE;
+        }
+
+        _check_seekability(worker);
+
+        if( worker->media.length_nanos >= DURATION_INDEFINITE )
+        {
+            worker->duration_seek_timeout = 0;
+            /* we've got a valid duration value no need to ask for more */
+            return FALSE;
+        }
+        else
+        {
+            return TRUE;
+        }
+    }
+    else
+    {
+        g_warning("_query_duration_and_seekability_timeout: We are in ready state, duration and seekability not checked.");
+        return FALSE;
+    }
+}
+
+/*
+ * Resets the media information.
+ */
+static void _reset_media_info(MafwGstRendererWorker *worker)
+{
+    if (worker->media.location) {
+        g_free(worker->media.location);
+        worker->media.location = NULL;
+    }
+    worker->media.length_nanos = DURATION_UNQUERIED;
+    worker->media.has_visual_content = FALSE;
+    worker->media.seekable = SEEKABILITY_UNKNOWN;
+    worker->media.video_width = 0;
+    worker->media.video_height = 0;
+    worker->media.fps = 0.0;
+}
+
+static void _reset_pipeline_and_worker(MafwGstRendererWorker *worker)
+{
+
+    if (worker->pipeline) {
+        g_debug("destroying pipeline");
+        if (worker->async_bus_id) {
+            g_source_remove(worker->async_bus_id);
+            worker->async_bus_id = 0;
+        }
+        gst_element_set_state(worker->pipeline, GST_STATE_NULL);
+        if (worker->bus) {
+            gst_bus_set_sync_handler(worker->bus, NULL, NULL);
+            gst_object_unref(GST_OBJECT_CAST(worker->bus));
+            worker->bus = NULL;
+        }
+        gst_object_unref(worker->pipeline);
+        worker->pipeline = NULL;
+    }
+
+    worker->report_statechanges = TRUE;
+    worker->state = GST_STATE_NULL;
+    worker->prerolling = FALSE;
+    worker->is_live = FALSE;
+    worker->buffering = FALSE;
+    worker->is_stream = FALSE;
+    worker->is_error = FALSE;
+    worker->eos = FALSE;
+    worker->seek_position = -1;
+    worker->stay_paused = FALSE;
+    worker->playback_speed = 1;
+    worker->in_ready = FALSE;
+    _remove_ready_timeout(worker);
+    _remove_pause_frame_timeout(worker);
+    _free_taglist(worker);
+    if (worker->current_metadata) {
+        g_hash_table_destroy(worker->current_metadata);
+        worker->current_metadata = NULL;
+    }
+
+    if (worker->duration_seek_timeout != 0) {
+        g_source_remove(worker->duration_seek_timeout);
+        worker->duration_seek_timeout = 0;
+    }
+    worker->duration_seek_timeout_loop_count = 0;
+
+    _reset_media_info(worker);
+
+    /* removes all idle timeouts with this worker as data */
+    while(g_idle_remove_by_data(worker));
+}
+
+
+/*
+ * Called when the pipeline transitions into PAUSED state.  It extracts more
+ * information from Gst.
+ */
+static void _finalize_startup(MafwGstRendererWorker *worker)
+{
+    /* Check video caps */
+    if (worker->media.has_visual_content && worker->vsink) {
+        GstPad *pad = GST_BASE_SINK_PAD(worker->vsink);
+        GstCaps *caps = GST_PAD_CAPS(pad);
+        if (caps && gst_caps_is_fixed(caps)) {
+            GstStructure *structure;
+            structure = gst_caps_get_structure(caps, 0);
+            if (!_handle_video_info(worker, structure))
+                return;
+        }
+    }
+
+    /* Something might have gone wrong at this point already. */
+    if (worker->is_error) {
+        g_debug("Error occured during preroll");
+        return;
+    }
+
+    /* Streaminfo might reveal the media to be unsupported.  Therefore we
+     * need to check the error again. */
+    _parse_stream_info(worker);
+    if (worker->is_error) {
+        g_debug("Error occured. Leaving");
+        return;
+    }
+
+    /* Check duration and seekability */
+    if (worker->duration_seek_timeout != 0) {
+        g_source_remove(worker->duration_seek_timeout);
+        worker->duration_seek_timeout = 0;
+    }
+
+    _check_duration(worker, -1);
+    _check_seekability(worker);
+}
+
+static void _add_duration_seek_query_timeout(MafwGstRendererWorker *worker)
+{
+    if(worker->duration_seek_timeout == 0)
+    {
+        gint timeout = 0;
+        if( worker->duration_seek_timeout_loop_count >= MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LOOP_LIMIT
+            || worker->media.length_nanos >= DURATION_INDEFINITE )
+        {
+            /* this is just for verifying the duration later on if it was received in PAUSED state early on */
+            timeout = MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LAZY_TIMEOUT;
+        }
+        else
+        {
+            timeout = MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_FAST_TIMEOUT;
+        }
+
+        worker->duration_seek_timeout = g_timeout_add(
+                timeout,
+                _query_duration_and_seekability_timeout,
+                worker);
+    }
+}
+
+static void _do_pause_postprocessing(MafwGstRendererWorker *worker)
+{
+    if (worker->notify_pause_handler) {
+        worker->notify_pause_handler(worker, worker->owner);
+    }
+
+    _add_pause_frame_timeout(worker);
+    _add_ready_timeout(worker);
+}
+
+static void _report_playing_state(MafwGstRendererWorker * worker)
+{
+    if (worker->report_statechanges && worker->notify_play_handler)
+    {
+        worker->notify_play_handler( worker,
+                                     worker->owner);
+    }
+}
+
+static void _handle_state_changed(GstMessage *msg,
+                                  MafwGstRendererWorker *worker)
+{
+    GstState newstate, oldstate;
+    GstStateChange statetrans;
+
+    gst_message_parse_state_changed(msg, &oldstate, &newstate, NULL);
+    statetrans = GST_STATE_TRANSITION(oldstate, newstate);
+    g_debug("State changed: %d: %d -> %d", worker->state, oldstate, newstate);
+
+    /* If the state is the same we do nothing, otherwise, we keep it */
+    if (worker->state == newstate)
+    {
+        /* This is used for saving correct pause frame after pauseAt.
+         * If we doing normal seek we dont want to save pause frame.
+         * We use gst_element_get_state to check if the state change is completed.
+         * If gst_element_get_state returns GST_STATE_CHANGE_SUCCESS we know that
+         * it's save to do pause_postprocessing */
+        if (newstate == GST_STATE_PAUSED && worker->stay_paused &&
+            gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS)
+        {
+            worker->seek_position = mafw_gst_renderer_seeker_process(worker->seeker);
+
+            /* has seeking ended successfully? */
+            if( worker->seek_position < 0 )
+            {
+                /* we do pause_postprocessing for pauseAt */
+                _do_pause_postprocessing(worker);
+            }
+        }
+
+        /* the EOS flag should only be cleared if it has been set and seeking has been done
+         * paused -> paused transition should only happen when seeking
+         */
+        if( newstate == GST_STATE_PAUSED && worker->eos )
+        {
+            worker->eos = FALSE;
+        }
+        return;
+    }
+
+    worker->state = newstate;
+
+    switch (statetrans) {
+        case GST_STATE_CHANGE_READY_TO_PAUSED:
+            if (worker->in_ready) {
+                /* Woken up from READY, resume stream position and playback */
+
+                /*live sources can be sought only in PLAYING state*/
+                if( !worker->is_live ) {
+                    _do_seek(worker,
+                             GST_SEEK_TYPE_SET,
+                             worker->seek_position,
+                             FALSE,
+                             NULL);
+                }
+
+                /* While buffering, we have to wait in PAUSED until we reach 100% before
+                 * doing anything */
+                if (worker->buffering) {
+                    return;
+                } else {
+                    _do_play(worker);
+                }
+            } else if (worker->prerolling && worker->report_statechanges && !worker->buffering) {
+                /* PAUSED after pipeline has been constructed. We check caps,
+                 * seek and duration and if staying in pause is needed, we
+                 * perform operations for pausing, such as current frame on
+                 * pause and signalling state change and adding the timeout to
+                 * go to ready */
+                g_debug ("Prerolling done, finalizaing startup");
+                _finalize_startup(worker);
+
+                if (worker->stay_paused) {
+                    /* then we can tell we're paused */
+                    _do_pause_postprocessing(worker);
+                }
+
+                if( worker->seek_position > 0 )
+                {
+                    g_debug("Immediate seek from READY state to: %d", worker->seek_position);
+                    _do_seek(worker, GST_SEEK_TYPE_SET,
+                             worker->seek_position, FALSE, NULL);
+
+                    if(worker->vsink)
+                    {
+                        g_object_set(worker->vsink, "show-preroll-frame",
+                                     TRUE, NULL);
+                    }
+
+                    /* do_seek will set this to false, but we'll want to report state changes
+                       when doing immediate seek from start */
+                    worker->report_statechanges = TRUE;
+                }
+                worker->prerolling = FALSE;
+                _do_play(worker);
+            }
+            break;
+        case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+            /* When pausing we do the stuff, like signalling state, current
+             * frame on pause and timeout to go to ready */
+            if (worker->report_statechanges) {
+                _do_pause_postprocessing(worker);
+            }
+            break;
+        case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+
+            /*live sources can be sought only in PLAYING state
+              This seek should happen only after READY to PAUSED to PLAYING
+              transitions
+            */
+            if( worker->report_statechanges
+                    && worker->seek_position > -1
+                    && worker->is_live )
+            {
+                g_debug("Seeking live source in PLAYING state!");
+                _do_seek(worker,
+                         GST_SEEK_TYPE_SET,
+                         worker->seek_position,
+                         FALSE,
+                         NULL);
+                /* this has to be set as do_seek sets statechanges to FALSE
+                  but we still want to inform that we're in PLAYING state */
+                worker->report_statechanges = TRUE;
+                /* seek position needs to be reset here for a live stream */
+                worker->seek_position = -1;
+            }
+
+            /* Because live streams are sought in PLAYING state, we reset
+               seek_position after all state transitions are completed. Normal
+               streams resetting seek_position here is OK.  */
+            if(worker->report_statechanges == FALSE || !worker->is_live)
+            {
+                /* if seek was called, at this point it is really ended */
+                worker->seek_position = mafw_gst_renderer_seeker_process(worker->seeker);
+            }
+
+            /* Signal state change if needed */
+            _report_playing_state(worker);
+
+            /* Prevent blanking if we are playing video */
+            if (worker->media.has_visual_content &&
+                worker->blanking__control_handler)
+            {
+                worker->blanking__control_handler(worker, worker->owner, TRUE);
+            }
+
+            /* Back to playing no longer in_ready (if ever was) */
+            worker->in_ready = FALSE;
+
+            /* context framework adaptation starts */
+            worker->context_nowplaying =
+                _set_context_map_value(worker->context_nowplaying,
+                                       GST_TAG_LOCATION,
+                                       worker->media.location);
+            context_provider_set_map(CONTEXT_PROVIDER_KEY_NOWPLAYING,
+                                     worker->context_nowplaying, FALSE);
+            /* context framework adaptation ends */
+
+            /* Emit metadata. We wait until we reach the playing state because
+             * this speeds up playback start time */
+            _emit_metadatas(worker);
+
+            /* in any case the duration is verified, it may change with VBR media */
+            _add_duration_seek_query_timeout(worker);
+
+            /* We've reached playing state, state changes are not reported
+             * unless explicitly requested (e.g. by PAUSE request) seeking
+             * in PLAYING does not cause state change reports
+             */
+            worker->report_statechanges = FALSE;
+
+            /* Delayed pause e.g. because of seek */
+            if (worker->stay_paused) {
+                mafw_gst_renderer_worker_pause(worker);
+            }
+
+            break;
+        case GST_STATE_CHANGE_PAUSED_TO_READY:
+            /* If we went to READY, we free the taglist and * deassign the
+             * timout it */
+            if (worker->in_ready) {
+                g_debug("changed to GST_STATE_READY");
+                worker->ready_timeout = 0;
+                _free_taglist(worker);
+
+                if( worker->notify_ready_state_handler )
+                {
+                    worker->notify_ready_state_handler(worker, worker->owner);
+                }
+            }
+            break;
+        case GST_STATE_CHANGE_NULL_TO_READY:
+            if(g_str_has_prefix(worker->media.location, STREAM_TYPE_MMSH) ||
+               g_str_has_prefix(worker->media.location, STREAM_TYPE_MMS))
+            {
+                GstElement *source = NULL;
+                g_object_get(worker->pipeline, "source", &source, NULL);
+                if(source)
+                {
+                    gst_util_set_object_arg(G_OBJECT(source), "tcp-timeout", MAFW_GST_MMSH_TCP_TIMEOUT);
+                    gst_object_unref(source);
+                }
+                else
+                    g_warning("Failed to get source element from pipeline");
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+static void _handle_duration(MafwGstRendererWorker *worker)
+{
+    /* if we've got ongoing query timeout ignore this and in any case do it only in PAUSE/PLAYING */
+    if( worker->duration_seek_timeout == 0
+        && ( worker->state == GST_STATE_PAUSED || worker->state == GST_STATE_PLAYING) )
+    {
+        /* We want to check this quickly but not immediately */
+        g_timeout_add_full(G_PRIORITY_DEFAULT,
+                           MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_FAST_TIMEOUT,
+                           _query_duration_and_seekability_timeout,
+                           worker,
+                           NULL);
+    }
+}
+
+static void _emit_renderer_art(MafwGstRendererWorker *worker,
+                               const GstTagList *list)
+{
+    GstBuffer *buffer = NULL;
+    const GValue *value = NULL;
+
+    g_return_if_fail(gst_tag_list_get_tag_size(list, GST_TAG_IMAGE) > 0);
+
+    value = gst_tag_list_get_value_index(list, GST_TAG_IMAGE, 0);
+
+    g_return_if_fail((value != NULL) && G_VALUE_HOLDS(value, GST_TYPE_BUFFER));
+
+    buffer = g_value_peek_pointer(value);
+
+    g_return_if_fail((buffer != NULL) && GST_IS_BUFFER(buffer));
+
+    _emit_gst_buffer_as_graphic_file(worker,
+                                     buffer,
+                                     WORKER_METADATA_KEY_RENDERER_ART_URI);
+}
+
+static void value_dtor(gpointer value)
+{
+
+    if (G_IS_VALUE(value)) {
+        g_value_unset(value);
+        g_free(value);
+    } else {
+        g_value_array_free(value);
+    }
+
+}
+
+static gboolean _current_metadata_add(MafwGstRendererWorker *worker,
+                                      const gint key,
+                                      GType type,
+                                      const gpointer value)
+{
+    GValue *new_gval;
+    gboolean was_updated = FALSE;
+
+    if( value == NULL )
+    {
+        g_warning("Null value for metadata was tried to be set!");
+        return was_updated;
+    }
+
+    if (!worker->current_metadata) {
+        worker->current_metadata = g_hash_table_new_full(g_direct_hash,
+                                                         g_direct_equal,
+                                                         NULL,
+                                                         value_dtor);
+    }
+
+    if (type == G_TYPE_VALUE_ARRAY) {
+        GValueArray *values = (GValueArray *) value;
+
+        if (values->n_values == 1) {
+            GValue *gval = g_value_array_get_nth(values, 0);
+            new_gval = g_new0(GValue, 1);
+            g_value_init(new_gval, G_VALUE_TYPE(gval));
+            g_value_copy(gval, new_gval);
+
+            GValue *existing = (GValue*)g_hash_table_lookup(worker->current_metadata, (gpointer)key);
+            if(!existing || (GST_VALUE_EQUAL != gst_value_compare(existing, new_gval)) )
+            {
+                was_updated = TRUE;
+            }
+            g_hash_table_insert(worker->current_metadata,
+                                (gpointer)key,
+                                new_gval);
+        } else {
+            GValueArray *new_gvalues = g_value_array_copy(values);
+
+            GValueArray *existing = (GValueArray*)g_hash_table_lookup(worker->current_metadata, (gpointer)key);
+
+            if( existing
+                && new_gvalues->n_values == existing->n_values )
+            {
+                guint size = new_gvalues->n_values;
+
+                guint i = 0;
+                for( ; i < size; ++i )
+                {
+                    GValue *newVal = g_value_array_get_nth(new_gvalues, i);
+                    GValue *existingVal = g_value_array_get_nth(existing, i);
+                    if( GST_VALUE_EQUAL != gst_value_compare(newVal, existingVal) )
+                    {
+                        was_updated = TRUE;
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                was_updated = TRUE;
+            }
+
+            g_hash_table_insert(worker->current_metadata,
+                                (gpointer)key,
+                                new_gvalues);
+        }
+
+        return was_updated;
+    }
+
+    new_gval = g_new0(GValue, 1);
+
+    if (_set_value(new_gval, type, value) == FALSE)
+    {
+        g_warning("Metadata type: %i is not being handled", type);
+        return was_updated;
+    }
+
+    GValue *existing = (GValue*)g_hash_table_lookup(worker->current_metadata, (gpointer)key);
+    if(!existing || (GST_VALUE_EQUAL != gst_value_compare(existing, new_gval)) )
+    {
+        was_updated = TRUE;
+    }
+    g_hash_table_insert(worker->current_metadata, (gpointer)key, new_gval);
+
+    return was_updated;
+
+}
+
+static GHashTable* _build_tagmap(void)
+{
+    GHashTable *hash_table = NULL;
+
+    hash_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_TITLE),
+                        (gpointer)WORKER_METADATA_KEY_TITLE);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_ARTIST),
+                        (gpointer)WORKER_METADATA_KEY_ARTIST);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_AUDIO_CODEC),
+                        (gpointer)WORKER_METADATA_KEY_AUDIO_CODEC);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_VIDEO_CODEC),
+                        (gpointer)WORKER_METADATA_KEY_VIDEO_CODEC);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_BITRATE),
+                        (gpointer)WORKER_METADATA_KEY_BITRATE);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_LANGUAGE_CODE),
+                        (gpointer)WORKER_METADATA_KEY_ENCODING);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_ALBUM),
+                        (gpointer)WORKER_METADATA_KEY_ALBUM);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_GENRE),
+                        (gpointer)WORKER_METADATA_KEY_GENRE);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_TRACK_NUMBER),
+                        (gpointer)WORKER_METADATA_KEY_TRACK);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_ORGANIZATION),
+                        (gpointer)WORKER_METADATA_KEY_ORGANIZATION);
+    g_hash_table_insert(hash_table, g_strdup(GST_TAG_IMAGE),
+                        (gpointer)WORKER_METADATA_KEY_RENDERER_ART_URI);
+
+    return hash_table;
+}
+
+/*
+ * Sets values to given context framework map, allocates it when map is NULL.
+ */
+gpointer _set_context_map_value(gpointer map,
+                                const gchar *tag,
+                                const gchar *value)
+{
+
+    if (map == NULL)
+    {
+        map = context_provider_map_new();
+    }
+
+    if (g_str_equal(tag, GST_TAG_LOCATION))
+    {
+        context_provider_map_set_string(map,
+                                        CONTEXT_PROVIDER_KEY_NOWPLAYING_RESOURCE,
+                                        value);
+    }
+    else if (g_str_equal(tag, GST_TAG_TITLE))
+    {
+        context_provider_map_set_string(map,
+                                        CONTEXT_PROVIDER_KEY_NOWPLAYING_TITLE,
+                                        value);
+    }
+    else if (g_str_equal(tag, GST_TAG_ARTIST))
+    {
+        context_provider_map_set_string(map,
+                                        CONTEXT_PROVIDER_KEY_NOWPLAYING_ARTIST,
+                                        value);
+    }
+    else if (g_str_equal(tag, GST_TAG_ALBUM))
+    {
+        context_provider_map_set_string(map,
+                                        CONTEXT_PROVIDER_KEY_NOWPLAYING_ALBUM,
+                                        value);
+    }
+    else if (g_str_equal(tag, GST_TAG_GENRE))
+    {
+        context_provider_map_set_string(map,
+                                        CONTEXT_PROVIDER_KEY_NOWPLAYING_GENRE,
+                                        value);
+    }
+
+    return map;
+
+}
+
+/*
+ * Emits metadata-changed signals for gst tags.
+ */
+static void _emit_tag(const GstTagList *list,
+                      const gchar *tag,
+                      MafwGstRendererWorker *worker)
+{
+    /* Mapping between Gst <-> MAFW metadata tags
+     * NOTE: This assumes that GTypes matches between GST and MAFW. */
+    static GHashTable *tagmap = NULL;
+    gint i, count;
+    gint mafwtag;
+    GType type;
+    GValueArray *values;
+
+    if (tagmap == NULL) {
+        tagmap = _build_tagmap();
+    }
+
+    g_debug("tag: '%s' (type: %s)", tag, g_type_name(gst_tag_get_type(tag)));
+    /* Is there a mapping for this tag? */
+    mafwtag = (gint)g_hash_table_lookup(tagmap, tag);
+    if (!mafwtag)
+        return;
+
+    if (mafwtag == WORKER_METADATA_KEY_RENDERER_ART_URI) {
+        _emit_renderer_art(worker, list);
+        return;
+    }
+
+    /* Build a value array of this tag.  We need to make sure that strings
+     * are UTF-8.  GstTagList API says that the value is always UTF8, but it
+     * looks like the ID3 demuxer still might sometimes produce non-UTF-8
+     * strings. */
+    count = gst_tag_list_get_tag_size(list, tag);
+
+    type = gst_tag_get_type(tag);
+    values = g_value_array_new(count);
+    for (i = 0; i < count; ++i) {
+        GValue *v = (GValue *)
+            gst_tag_list_get_value_index(list, tag, i);
+        if (type == G_TYPE_STRING) {
+            gchar *orig, *utf8;
+
+            gboolean tagExists = gst_tag_list_get_string_index(list, tag, i, &orig);
+            UNUSED(tagExists); //TODO what if tag does not exists?
+            if (convert_utf8(orig, &utf8)) {
+                GValue utf8gval;
+                memset(&utf8gval, 0, sizeof(utf8gval));
+
+                g_value_init(&utf8gval, G_TYPE_STRING);
+                g_value_take_string(&utf8gval, utf8);
+                g_value_array_append(values, &utf8gval);
+                g_value_unset(&utf8gval);
+            }
+            /* context framework adaptation starts */
+            worker->context_nowplaying =
+                _set_context_map_value(worker->context_nowplaying,
+                                       tag,
+                                       orig);
+            /* context framework adaptation ends */
+            g_free(orig);
+        } else if (type == G_TYPE_UINT) {
+            GValue intgval;
+            memset(&intgval, 0, sizeof(intgval));
+
+            g_value_init(&intgval, G_TYPE_INT);
+            g_value_transform(v, &intgval);
+            g_value_array_append(values, &intgval);
+            g_value_unset(&intgval);
+        } else {
+            g_value_array_append(values, v);
+        }
+    }
+
+    /* context framework adaptation starts */
+    context_provider_set_map(CONTEXT_PROVIDER_KEY_NOWPLAYING,
+                             worker->context_nowplaying, FALSE);
+    /* context framework adaptation ends */
+
+    /* Add the info to the current metadata. */
+    gboolean changed = _current_metadata_add(worker,
+                                             mafwtag,
+                                             G_TYPE_VALUE_ARRAY,
+                                             (const gpointer) values);
+
+    /* Emit the metadata. */
+    if (changed && worker->notify_metadata_handler)
+    {
+        worker->notify_metadata_handler(worker,
+                                        worker->owner,
+                                        mafwtag,
+                                        G_TYPE_VALUE_ARRAY,
+                                        values);
+    }
+
+    g_value_array_free(values);
+}
+
+/**
+ * Collect tag-messages, parse it later, when playing is ongoing
+ */
+static void _handle_tag(MafwGstRendererWorker *worker, GstMessage *msg)
+{
+    /* Do not emit metadata until we get to PLAYING state to speed up playback
+     * start */
+    if (worker->tag_list == NULL)
+        worker->tag_list = g_ptr_array_new();
+    g_ptr_array_add(worker->tag_list, gst_message_ref(msg));
+
+    /* Some tags come in playing state, so in this case we have to emit them
+     * right away (example: radio stations) */
+    if (worker->state == GST_STATE_PLAYING) {
+        _emit_metadatas(worker);
+    }
+}
+
+/**
+ * Parses the list of tag-messages
+ */
+static void _parse_tagmsg(GstMessage *msg, MafwGstRendererWorker *worker)
+{
+    GstTagList *new_tags;
+
+    gst_message_parse_tag(msg, &new_tags);
+    gst_tag_list_foreach(new_tags, (gpointer)_emit_tag, worker);
+    gst_tag_list_free(new_tags);
+    gst_message_unref(msg);
+}
+
+/**
+ * Parses the collected tag messages, and emits the metadatas
+ */
+static void _emit_metadatas(MafwGstRendererWorker *worker)
+{
+    if (worker->tag_list != NULL)
+    {
+        g_ptr_array_foreach(worker->tag_list, (GFunc)_parse_tagmsg, worker);
+        g_ptr_array_free(worker->tag_list, TRUE);
+        worker->tag_list = NULL;
+    }
+}
+
+static void _handle_buffering(MafwGstRendererWorker *worker, GstMessage *msg)
+{
+    /* We set smaller buffer for mms streams */
+    if((g_str_has_prefix(worker->media.location, STREAM_TYPE_MMSH) || g_str_has_prefix(worker->media.location, STREAM_TYPE_MMS))
+        && worker->state != GST_STATE_PLAYING && !worker->buffering)
+    {
+        if(worker->queue)
+        {
+            g_object_set(worker->queue, "high-percent", 30, NULL);
+        }
+        else
+        {
+            g_warning("Queue2 element doesn't exist!");
+        }
+    }
+
+    /* We can ignore buffering messages when we are in READY state or when going to it */
+    if(worker->state == GST_STATE_READY || worker->ready_timeout != 0 )
+    {
+        worker->buffering = TRUE;
+        return;
+    }
+
+    gint percent;
+    gst_message_parse_buffering(msg, &percent);
+    g_debug("buffering: %d", percent);
+
+    /* No state management needed for live pipelines */
+    if (!worker->is_live) {
+        worker->buffering = TRUE;
+        if (percent < 100 && worker->state == GST_STATE_PLAYING) {
+            /* If we need to buffer more, we set larger buffer */
+            if(g_str_has_prefix(worker->media.location, STREAM_TYPE_MMSH) || g_str_has_prefix(worker->media.location, STREAM_TYPE_MMS))
+            {
+                if(worker->queue)
+                {
+                    g_object_set(worker->queue, "high-percent", 100, NULL);
+                }
+                else
+                {
+                    g_warning("Queue2 element doesn't exist!");
+                }
+            }
+            g_debug("setting pipeline to PAUSED not to wolf the buffer down");
+
+            //if there's no requested state transitions i.e. resume/pause let's keep this quiet
+            if( gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS )
+            {
+                worker->report_statechanges = FALSE;
+            }
+
+            /* We can't call _pause() here, since it sets the
+             * "report_statechanges" to TRUE.  We don't want that, application
+             * doesn't need to know that internally the state changed to PAUSED.
+             */
+            gst_element_set_state(worker->pipeline, GST_STATE_PAUSED);
+        }
+
+        if (percent >= 100) {
+            /* On buffering we go to PAUSED, so here we move back to PLAYING */
+            worker->buffering = FALSE;
+            if (worker->state == GST_STATE_PAUSED)
+            {
+                /* If buffering more than once, do this only the first time we
+                 * are done with buffering */
+                if (worker->prerolling)
+                {
+                    g_debug("buffering concluded during prerolling");
+                    _finalize_startup(worker);
+                    _do_play(worker);
+                    /* Send the paused notification */
+                    if (worker->stay_paused &&
+                        worker->notify_pause_handler)
+                    {
+                        worker->notify_pause_handler(worker, worker->owner);
+                    }
+                    worker->prerolling = FALSE;
+                }
+                /* if eos has been reached no automatic playing should be done
+                   only on resume request e.g. eos reached -> seek requested => stays paused after seek&buffering completed */
+                else if (!worker->stay_paused && !worker->eos)
+                {
+                    g_debug("buffering concluded, setting "
+                            "pipeline to PLAYING again");
+                    worker->report_statechanges = TRUE;
+                    gst_element_set_state(worker->pipeline, GST_STATE_PLAYING);
+                }
+            }
+            /* if there's no pending state changes and we're really in PLAYING state... */
+            else if (gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS
+                       && worker->state == GST_STATE_PLAYING)
+            {
+                g_debug("buffering concluded, signalling state change");
+                /* In this case we got a PLAY command while buffering, likely
+                 * because it was issued before we got the first buffering
+                 * signal.  The UI should not do this, but if it does, we have
+                 * to signal that we have executed the state change, since in
+                 * _handle_state_changed we do not do anything if we are
+                 * buffering */
+                if (worker->report_statechanges &&
+                    worker->notify_play_handler) {
+                    worker->notify_play_handler(worker, worker->owner);
+                }
+                _add_duration_seek_query_timeout(worker);
+
+            }
+            /* has somebody requested pause transition? */
+            else if( !worker->stay_paused )
+            {
+                /* we're in PLAYING but pending for paused state change.
+                   Let's request new state change to override the pause */
+                gst_element_set_state(worker->pipeline, GST_STATE_PLAYING);
+            }
+        }
+    }
+
+    /* Send buffer percentage */
+    if (worker->notify_buffer_status_handler)
+        worker->notify_buffer_status_handler(worker, worker->owner, percent);
+}
+
+static void _handle_element_msg(MafwGstRendererWorker *worker, GstMessage *msg)
+{
+    /* Only HelixBin sends "resolution" messages. */
+    if (gst_structure_has_name(msg->structure, "resolution") &&
+        _handle_video_info(worker, msg->structure))
+    {
+        worker->media.has_visual_content = TRUE;
+        set_dolby_video_property(worker, worker->config->mobile_surround_video.state);
+        set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.room, TRUE);
+        set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.color, FALSE);
+    }
+    /* We do RTSP redirect when we try to play .sdp streams */
+    else if(gst_structure_has_name(msg->structure, "redirect"))
+    {
+        /* "new-location" contains the rtsp uri what we are going to play */
+        mafw_gst_renderer_worker_play(worker, gst_structure_get_string(msg->structure, "new-location"));
+    }
+
+}
+
+static GError * _get_specific_missing_plugin_error(GstMessage *msg)
+{
+    const GstStructure *gst_struct;
+    const gchar *type;
+
+    GError *error;
+    gchar *desc;
+
+    desc = gst_missing_plugin_message_get_description(msg);
+
+    gst_struct = gst_message_get_structure(msg);
+    type = gst_structure_get_string(gst_struct, "type");
+
+    if ((type) && ((strcmp(type, MAFW_GST_MISSING_TYPE_DECODER) == 0) ||
+                   (strcmp(type, MAFW_GST_MISSING_TYPE_ENCODER) == 0))) {
+
+        /* Missing codec error. */
+        const GValue *val;
+        const GstCaps *caps;
+        GstStructure *caps_struct;
+        const gchar *mime;
+
+        val = gst_structure_get_value(gst_struct, "detail");
+        caps = gst_value_get_caps(val);
+        caps_struct = gst_caps_get_structure(caps, 0);
+        mime = gst_structure_get_name(caps_struct);
+
+        if (g_strrstr(mime, "video")) {
+            error = g_error_new_literal(WORKER_ERROR,
+                                        WORKER_ERROR_VIDEO_CODEC_NOT_FOUND,
+                                        desc);
+        } else if (g_strrstr(mime, "audio")) {
+            error = g_error_new_literal(WORKER_ERROR,
+                                        WORKER_ERROR_AUDIO_CODEC_NOT_FOUND,
+                                        desc);
+        } else {
+            error = g_error_new_literal(WORKER_ERROR,
+                                        WORKER_ERROR_CODEC_NOT_FOUND,
+                                        desc);
+        }
+    } else {
+        /* Unsupported type error. */
+        error = g_error_new(WORKER_ERROR,
+                            WORKER_ERROR_UNSUPPORTED_TYPE,
+                            "missing plugin: %s", desc);
+    }
+
+    g_free(desc);
+
+    return error;
+}
+
+/*
+ * Asynchronous message handler.  It gets removed from if it returns FALSE.
+ */
+static gboolean _async_bus_handler(GstBus *bus,
+                                   GstMessage *msg,
+                                   MafwGstRendererWorker *worker)
+{
+
+    UNUSED(bus);
+
+    /* No need to handle message if error has already occured. */
+    if (worker->is_error)
+        return TRUE;
+
+    /* Handle missing-plugin (element) messages separately, relaying more
+     * details. */
+    if (gst_is_missing_plugin_message(msg)) {
+        GError *err = _get_specific_missing_plugin_error(msg);
+        /* FIXME?: for some reason, calling the error handler directly
+         * (_send_error) causes problems.  On the other hand, turning
+         * the error into a new GstMessage and letting the next
+         * iteration handle it seems to work. */
+        _post_error(worker, err);
+        return TRUE;
+    }
+    switch (GST_MESSAGE_TYPE(msg)) {
+        case GST_MESSAGE_ERROR:
+            if (!worker->is_error) {
+                gchar *debug;
+                GError *err;
+                debug = NULL;
+                gst_message_parse_error(msg, &err, &debug);
+                g_debug("gst error: domain = %s, code = %d, "
+                        "message = '%s', debug = '%s'",
+                        g_quark_to_string(err->domain), err->code, err->message, debug);
+                if (debug)
+                {
+                    g_free(debug);
+                }
+                               //decodebin2 uses the error only to report text files
+                if (err->code == GST_STREAM_ERROR_WRONG_TYPE && g_str_has_prefix(GST_MESSAGE_SRC_NAME(msg), "decodebin2"))
+                {
+                    err->code = WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE;
+                }
+
+                _send_error(worker, err);
+            }
+            break;
+        case GST_MESSAGE_EOS:
+            if (!worker->is_error) {
+                worker->eos = TRUE;
+                worker->seek_position = -1;
+                if (worker->notify_eos_handler)
+                {
+                    worker->notify_eos_handler(worker, worker->owner);
+                }
+            }
+            break;
+        case GST_MESSAGE_TAG:
+            _handle_tag(worker, msg);
+            break;
+        case GST_MESSAGE_BUFFERING:
+            _handle_buffering(worker, msg);
+            break;
+        case GST_MESSAGE_DURATION:
+            /* in ready state we might not get correct seekability info */
+            if (!worker->in_ready)
+            {
+                _handle_duration(worker);
+            }
+            break;
+        case GST_MESSAGE_ELEMENT:
+            _handle_element_msg(worker, msg);
+            break;
+        case GST_MESSAGE_STATE_CHANGED:
+            if ((GstElement *)GST_MESSAGE_SRC(msg) == worker->pipeline)
+                _handle_state_changed(msg, worker);
+            break;
+        case GST_MESSAGE_APPLICATION:
+            if (gst_structure_has_name(gst_message_get_structure(msg), "ckey"))
+            {
+                _emit_property(worker,
+                               WORKER_PROPERTY_COLORKEY,
+                               G_TYPE_INT,
+                               &worker->colorkey);
+            }
+        default:
+            break;
+    }
+    return TRUE;
+}
+
+/* NOTE this function will possibly be called from a different thread than the
+ * glib main thread. */
+static void _stream_info_cb(GstObject *pipeline, GParamSpec *unused,
+                            MafwGstRendererWorker *worker)
+{
+    UNUSED(pipeline);
+    UNUSED(unused);
+
+    g_debug("stream-info changed");
+    _parse_stream_info(worker);
+}
+
+static void _element_added_cb(GstBin *bin, GstElement *element,
+                              MafwGstRendererWorker *worker)
+{
+    UNUSED(bin);
+    gchar *element_name;
+
+    element_name = gst_element_get_name(element);
+    if(g_str_has_prefix(element_name, "uridecodebin") ||
+       g_str_has_prefix(element_name, "decodebin2"))
+    {
+        g_signal_connect(element, "element-added",
+                         G_CALLBACK(_element_added_cb), worker);
+    }
+    else if(g_str_has_prefix(element_name, "sdpdemux"))
+    {
+        g_object_set(element, "redirect", FALSE, NULL);
+    }
+    else if(g_str_has_prefix(element_name, "queue2"))
+    {
+        worker->queue = element;
+    }
+    g_free(element_name);
+}
+
+/*
+ * Start to play the media
+ */
+static void _start_play(MafwGstRendererWorker *worker)
+{
+    GstStateChangeReturn state_change_info;
+    worker->stay_paused = FALSE;
+    char *autoload_sub = NULL;
+
+    g_assert(worker->pipeline);
+    g_object_set(G_OBJECT(worker->pipeline),
+                 "uri", worker->media.location, NULL);
+
+    if (worker->config->autoload_subtitles) {
+        autoload_sub = uri_get_subtitle_uri(worker->media.location);
+        if (autoload_sub) {
+            g_debug("SUBURI: %s", autoload_sub);
+            g_object_set(G_OBJECT(worker->pipeline),
+                         "suburi", autoload_sub,
+                         "subtitle-font-desc", worker->config->subtitle_font,
+                         "subtitle-encoding", worker->config->subtitle_encoding,
+                         NULL);
+
+            gst_element_set_state(worker->pipeline, GST_STATE_READY);
+            g_free(autoload_sub);
+        }
+    } else {
+        g_object_set(G_OBJECT(worker->pipeline), "suburi", NULL, NULL);
+    }
+
+    g_debug("URI: %s", worker->media.location);
+    g_debug("setting pipeline to PAUSED");
+
+    worker->report_statechanges = TRUE;
+    state_change_info = gst_element_set_state(worker->pipeline,
+                                              GST_STATE_PAUSED);
+    if (state_change_info == GST_STATE_CHANGE_NO_PREROLL) {
+        /* FIXME:  for live sources we may have to handle buffering and
+         * prerolling differently */
+        g_debug ("Source is live!");
+        worker->is_live = TRUE;
+    }
+    worker->prerolling = TRUE;
+
+    worker->is_stream = uri_is_stream(worker->media.location);
+
+}
+
+/*
+ * Constructs gst pipeline
+ *
+ * FIXME: Could the same pipeline be used for playing all media instead of
+ *  constantly deleting and reconstructing it again?
+ */
+static void _construct_pipeline(MafwGstRendererWorker *worker, configuration *config)
+{
+    g_debug("constructing pipeline");
+    g_assert(worker != NULL);
+
+    /* Return if we have already one */
+    if (worker->pipeline)
+        return;
+
+    _free_taglist(worker);
+
+    g_debug("Creating a new instance of playbin2");
+    worker->pipeline = gst_element_factory_make("playbin2", "playbin");
+    if (worker->pipeline == NULL)
+    {
+        /* Let's try with playbin */
+        g_warning ("playbin2 failed, falling back to playbin");
+        worker->pipeline = gst_element_factory_make("playbin", "playbin");
+
+        if (worker->pipeline) {
+            /* Use nwqueue only for non-rtsp and non-mms(h) streams. */
+            gboolean use_nw;
+            use_nw = worker->media.location &&
+                !g_str_has_prefix(worker->media.location, "rtsp://") &&
+                !g_str_has_prefix(worker->media.location, "mms://") &&
+                !g_str_has_prefix(worker->media.location, "mmsh://");
+
+            g_debug("playbin using network queue: %d", use_nw);
+
+            gst_object_ref_sink(worker->pipeline);
+            /* These need a modified version of playbin. */
+            g_object_set(G_OBJECT(worker->pipeline),
+                         "nw-queue", use_nw,
+                         "no-video-transform", TRUE,
+                         NULL);
+
+        }
+    }
+
+    if (!worker->pipeline) {
+        g_critical("failed to create playback pipeline");
+        _send_error(worker,
+                    g_error_new(WORKER_ERROR,
+                                WORKER_ERROR_UNABLE_TO_PERFORM,
+                                "Could not create pipeline"));
+        g_assert_not_reached();
+    }
+
+    worker->bus = gst_pipeline_get_bus(GST_PIPELINE(worker->pipeline));
+    gst_bus_set_sync_handler(worker->bus,
+                             (GstBusSyncHandler)_sync_bus_handler,
+                             worker);
+    worker->async_bus_id = gst_bus_add_watch_full(
+        worker->bus,G_PRIORITY_HIGH,
+        (GstBusFunc)_async_bus_handler,
+        worker, NULL);
+
+    /* Listen for changes in stream-info object to find out whether the media
+     * contains video and throw error if application has not provided video
+     * window. */
+    g_signal_connect(worker->pipeline, "notify::stream-info",
+                     G_CALLBACK(_stream_info_cb), worker);
+
+    g_signal_connect(worker->pipeline, "element-added",
+                     G_CALLBACK(_element_added_cb), worker);
+
+    /* Set audio and video sinks ourselves. We create and configure them only
+     * once. */
+    if (!worker->asink) {
+        const gchar *sink = g_getenv("AUDIO_SINK");
+        worker->asink = gst_element_factory_make(sink?sink: worker->config->asink, NULL);
+        if (!worker->asink){
+            worker->asink = gst_element_factory_make("alsasink", NULL);
+        }
+        if (!worker->asink) {
+            g_critical("Failed to create pipeline audio sink");
+            _send_error(worker,
+                        g_error_new(WORKER_ERROR,
+                                    WORKER_ERROR_UNABLE_TO_PERFORM,
+                                    "Could not create audio sink"));
+            g_assert_not_reached();
+        }
+        g_debug("MafwGstRendererWorker: Using following buffer-time: %lld and latency-time: %lld",
+                config->buffer_time,
+                config->latency_time);
+        gst_object_ref_sink(worker->asink);
+        g_object_set(worker->asink,
+                     "buffer-time", config->buffer_time,
+                     "latency-time", config->latency_time,
+                     NULL);
+    }
+
+    if (worker->config->use_dhmmixer && !worker->amixer)
+    {
+        worker->amixer = gst_element_factory_make("nokiadhmmix", NULL);
+        if( !worker->amixer )
+        {
+            g_warning("Could not create dhmmixer, falling back to basic audiosink!");
+        }
+    }
+
+    if( worker->config->use_dhmmixer && worker->amixer && !worker->audiobin )
+    {
+        worker->audiobin = gst_bin_new("audiobin");
+        if( worker->audiobin )
+        {
+            gst_bin_add(GST_BIN (worker->audiobin), worker->amixer);
+            gst_bin_add(GST_BIN (worker->audiobin), worker->asink);
+            gst_element_link(worker->amixer, worker->asink);
+            GstPad *pad;
+            pad = gst_element_get_static_pad (worker->amixer, "sink");
+            gst_element_add_pad (worker->audiobin, gst_ghost_pad_new ("sink", pad));
+            gst_object_unref (GST_OBJECT (pad));
+
+            gst_object_ref(worker->audiobin);
+
+            /* Use Dolby music settings by default */
+            set_dolby_music_property(worker, worker->config->mobile_surround_music.state);
+            set_dolby_music_sound_property(worker, worker->config->mobile_surround_music.room, TRUE);
+            set_dolby_music_sound_property(worker, worker->config->mobile_surround_music.color, FALSE);
+        }
+        else
+        {
+            gst_object_ref_sink(worker->asink);
+            gst_object_sink(worker->amixer);
+            g_warning("Could not create audiobin! Falling back to basic audio-sink!");
+        }
+    }
+
+
+    if( worker->config->use_dhmmixer && worker->amixer && worker->audiobin )
+    {
+        g_object_set(worker->pipeline,
+                 "audio-sink", worker->audiobin,
+                 "flags", worker->config->flags,
+                  NULL);
+    }
+    else
+    {
+        g_object_set(worker->pipeline,
+                 "audio-sink", worker->asink,
+                 "flags", worker->config->flags,
+                  NULL);
+    }
+
+    if( worker->pipeline )
+    {
+        mafw_gst_renderer_seeker_set_pipeline(worker->seeker, worker->pipeline);
+
+        if( worker->vsink && worker->xid != 0 )
+        {
+            g_object_set(worker->pipeline,
+                         "video-sink", worker->vsink,
+                         NULL);
+        }
+    }
+
+    if (!worker->tsink) {
+        worker->tsink = gst_element_factory_make("textoverlay", NULL);
+        if (!worker->tsink) {
+            g_critical("Failed to create pipeline text sink");
+            _send_error(worker,
+                        g_error_new(WORKER_ERROR,
+                                    WORKER_ERROR_UNABLE_TO_PERFORM,
+                                    "Could not create text sink"));
+            g_assert_not_reached();
+        }
+        gst_object_ref(worker->tsink);
+    }
+    g_object_set(worker->pipeline, "text-sink", worker->tsink, NULL);
+}
+
+guint check_dolby_audioroute(MafwGstRendererWorker *worker, guint prop) {
+    if (g_slist_find(worker->destinations,
+                     GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)) ||
+        g_slist_find(worker->destinations,
+                     GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)))
+    {
+        return prop;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+void set_dolby_music_property(MafwGstRendererWorker *worker, guint prop) {
+    worker->config->mobile_surround_music.state = prop;
+    if (worker->amixer && !worker->media.has_visual_content) {
+        GValue a;
+        guint tempprop = check_dolby_audioroute(worker, prop);
+        if (_set_value(&a, G_TYPE_UINT, &tempprop))
+        {
+            g_object_set_property(G_OBJECT(worker->amixer), "mobile-surround", &a);
+            g_value_unset (&a);
+        }
+    }
+}
+
+void set_dolby_music_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty) {
+    if (isRoomProperty) {
+        worker->config->mobile_surround_music.room = prop;
+    } else {
+        worker->config->mobile_surround_music.color = prop;
+    }
+    if (worker->amixer && !worker->media.has_visual_content) {
+        GValue a;
+
+        if (_set_value(&a, G_TYPE_UINT, &prop))
+        {
+            if (isRoomProperty) {
+                g_object_set_property(G_OBJECT(worker->amixer), "room-size", &a);
+            } else {
+                g_object_set_property(G_OBJECT(worker->amixer), "brightness", &a);
+            }
+            g_value_unset (&a);
+        }
+    }
+}
+
+void set_dolby_video_property(MafwGstRendererWorker *worker, guint prop) {
+    worker->config->mobile_surround_video.state = prop;
+    if (worker->amixer && worker->media.has_visual_content) {
+        GValue a;
+        guint tempprop = check_dolby_audioroute(worker, prop);
+        if (_set_value(&a, G_TYPE_UINT, &tempprop))
+        {
+            g_object_set_property(G_OBJECT(worker->amixer), "mobile-surround", &a);
+            g_value_unset (&a);
+        }
+    }
+}
+
+void set_dolby_video_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty) {
+    if (isRoomProperty) {
+        worker->config->mobile_surround_video.room = prop;
+    } else {
+        worker->config->mobile_surround_video.color = prop;
+    }
+    if (worker->amixer && worker->media.has_visual_content) {
+        GValue a;
+
+        if (_set_value(&a, G_TYPE_UINT, &prop))
+        {
+            if (isRoomProperty) {
+                g_object_set_property(G_OBJECT(worker->amixer), "room-size", &a);
+            } else {
+                g_object_set_property(G_OBJECT(worker->amixer), "brightness", &a);
+            }
+            g_value_unset (&a);
+        }
+    }
+}
+
+/*
+ * @seek_type: GstSeekType
+ * @position: Time in seconds where to seek
+ * @key_frame_seek: True if this is a key frame based seek
+ * @error: Possible error that is set and returned
+ */
+static void _do_seek(MafwGstRendererWorker *worker,
+                     GstSeekType seek_type,
+                     gint position,
+                     gboolean key_frame_seek,
+                     GError **error)
+{
+    gboolean ret;
+    gint64 spos;
+    GstSeekFlags flags = GST_SEEK_FLAG_FLUSH;
+
+    g_assert(worker != NULL);
+
+    if (!worker->media.seekable == SEEKABILITY_SEEKABLE)
+    {
+        goto err;
+    }
+
+    /* According to the docs, relative seeking is not so easy:
+    GST_SEEK_TYPE_CUR - change relative to currently configured segment.
+    This can't be used to seek relative to the current playback position -
+    do a position query, calculate the desired position and then do an
+    absolute position seek instead if that's what you want to do. */
+    if (seek_type == GST_SEEK_TYPE_CUR)
+    {
+        gint curpos = mafw_gst_renderer_worker_get_position(worker);
+        position = curpos + position;
+        seek_type = GST_SEEK_TYPE_SET;
+    }
+
+    if (position < 0) {
+        position = 0;
+    }
+
+    worker->seek_position = position;
+
+    if (worker->state != GST_STATE_PLAYING && worker->state != GST_STATE_PAUSED )
+    {
+        g_debug("_do_seek: Not in playing or paused state, seeking delayed.");
+        return;
+    }
+    else if( worker->is_live && worker->state == GST_STATE_PAUSED )
+    {
+        g_debug("_do_seek: Live source can be seeked only in playing state, seeking delayed!");
+        return;
+    }
+
+    worker->report_statechanges = FALSE;
+
+    if (key_frame_seek == TRUE)
+    {
+        /* tries to do key frame seeks at least with some change */
+        ret = mafw_gst_renderer_seeker_seek_to(worker->seeker, worker->seek_position);
+    }
+    else
+    {
+        spos = (gint64)position * GST_SECOND;
+        g_debug("seek: type = %d, offset = %lld", seek_type, spos);
+
+        /* exact seek */
+        ret = gst_element_seek(worker->pipeline,
+                               1.0,
+                               GST_FORMAT_TIME,
+                               flags,
+                               seek_type,
+                               spos,
+                               GST_SEEK_TYPE_NONE,
+                               GST_CLOCK_TIME_NONE);
+    }
+
+    if (ret)
+    {
+        /* Seeking is async, so seek_position should not be invalidated here */
+        return;
+    }
+
+err:
+    g_set_error(error,
+                WORKER_ERROR,
+                WORKER_ERROR_CANNOT_SET_POSITION,
+                "Seeking to %d failed", position);
+    worker->report_statechanges = TRUE;
+    worker->seek_position = -1;
+    mafw_gst_renderer_seeker_cancel(worker->seeker);
+}
+
+void mafw_gst_renderer_worker_set_current_frame_on_pause(
+    MafwGstRendererWorker *worker,
+    gboolean current_frame_on_pause)
+{
+
+    worker->current_frame_on_pause = current_frame_on_pause;
+
+    _emit_property(worker,
+                   WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE,
+                   G_TYPE_BOOLEAN,
+                   &worker->current_frame_on_pause);
+}
+
+gboolean mafw_gst_renderer_worker_get_current_frame_on_pause(
+    MafwGstRendererWorker *worker)
+{
+    return worker->current_frame_on_pause;
+}
+
+configuration *mafw_gst_renderer_worker_create_default_configuration(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return _create_default_configuration();
+}
+
+void mafw_gst_renderer_worker_set_configuration(MafwGstRendererWorker *worker,
+                                                configuration *config)
+{
+    if( config == NULL )
+    {
+        g_warning("NULL config was tried to be set!");
+        return;
+    }
+
+    if( worker->config )
+    {
+        _free_configuration(worker->config);
+    }
+    worker->config = config;
+
+    if( (worker->pipeline == NULL)
+        || (worker->state == GST_STATE_NULL && gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS) )
+    {
+        _reset_pipeline_and_worker(worker);
+        _construct_pipeline(worker, worker->config);
+    }
+}
+
+/*
+ * Sets the pipeline PAUSED-to-READY timeout to given value (in seconds). If the
+ * pipeline is already in PAUSED state and this called with zero value the pipeline
+ * get immediately set to READY state.
+ */
+void mafw_gst_renderer_worker_set_ready_timeout(MafwGstRendererWorker *worker,
+                                                guint seconds)
+{
+    g_debug(G_STRFUNC);
+
+    worker->config->seconds_to_pause_to_ready = seconds;
+
+    /* zero is a special case: if we are already in PAUSED state, a pending
+     * ready timeout has not yet elapsed and we are asked to set the timeout
+     * value to zero --> remove the pending tmo and go immediately to READY.
+     * This forces GStreamer to release all pipeline resources and for the
+     * outsiders it looks like we are still in the PAUSED state. */
+    if (seconds == 0 && worker->ready_timeout && worker->state == GST_STATE_PAUSED)
+    {
+        _remove_ready_timeout(worker);
+        _add_ready_timeout(worker);
+    }
+
+}
+
+void mafw_gst_renderer_worker_set_position(MafwGstRendererWorker *worker,
+                                           GstSeekType seek_type,
+                                           gint position, GError **error)
+{
+    _do_seek(worker, seek_type, position, TRUE, error);
+    if (worker->notify_seek_handler)
+        worker->notify_seek_handler(worker, worker->owner);
+}
+
+static gint64 _get_duration(MafwGstRendererWorker *worker)
+{
+    gint64 value = DURATION_UNQUERIED;
+    GstFormat format = GST_FORMAT_TIME;
+
+    gboolean right_query = gst_element_query_duration(worker->pipeline, &format, &value);
+    if( !right_query )
+    {
+        /* just in case gstreamer messes with the value */
+        value = DURATION_UNQUERIED;
+    }
+    return value;
+}
+
+/*
+ * Gets current position, rounded down into precision of one second.  If a seek
+ * is pending, returns the position we are going to seek.  Returns -1 on
+ * failure.
+ */
+gint mafw_gst_renderer_worker_get_position(MafwGstRendererWorker *worker)
+{
+    GstFormat format;
+    gint64 time = 0;
+    g_assert(worker != NULL);
+
+    /* If seek is ongoing, return the position where we are seeking. */
+    if (worker->seek_position != -1)
+    {
+        return worker->seek_position;
+    }
+
+    /* Otherwise query position from pipeline. */
+    format = GST_FORMAT_TIME;
+    if (worker->pipeline &&
+        gst_element_query_position(worker->pipeline, &format, &time))
+    {
+        return (gint)(time / GST_SECOND);
+    }
+    /* lets return the duration if we're in eos and the pipeline cannot return position */
+    else if( worker->pipeline && worker->eos )
+    {
+        gint64 duration = _get_duration(worker);
+        if( duration > 0 )
+        {
+            return (gint)(duration / GST_SECOND);
+        }
+    }
+    return -1;
+}
+
+/*
+ * Returns the duration of the current media in seconds
+ */
+gint64 mafw_gst_renderer_worker_get_duration(MafwGstRendererWorker *worker)
+{
+    gint64 duration = _get_duration(worker);
+    if( duration >= 0 )
+    {
+        gint64 second_precision = (duration + (GST_SECOND/2)) / GST_SECOND;
+
+        if( !_seconds_duration_equal(duration, worker->media.length_nanos) )
+        {            
+            worker->media.length_nanos = duration;
+
+            if( _current_metadata_add(worker,
+                                      WORKER_METADATA_KEY_DURATION,
+                                      G_TYPE_INT64,
+                                      (const gpointer)&second_precision) )
+            {
+                _emit_metadata(worker,
+                               WORKER_METADATA_KEY_DURATION,
+                               G_TYPE_INT64,
+                               &second_precision);
+            }
+        }
+        return second_precision;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+gint64 mafw_gst_renderer_worker_get_last_known_duration(MafwGstRendererWorker *worker)
+{
+    if( worker->media.length_nanos <= 0 )
+    {
+        return worker->media.length_nanos;
+    }
+    else
+    {
+        return (worker->media.length_nanos + (GST_SECOND/2)) / GST_SECOND;
+    }
+}
+
+GHashTable *mafw_gst_renderer_worker_get_current_metadata(
+    MafwGstRendererWorker *worker)
+{
+    return worker->current_metadata;
+}
+
+void mafw_gst_renderer_worker_set_xid(MafwGstRendererWorker *worker, XID xid)
+{
+    /* Store the target window id */
+    g_debug("Setting xid: %x", (guint)xid);
+    worker->xid = xid;
+
+    if( !worker->vsink )
+    {
+        g_debug("Creating video-sink as XID has been set, %s", worker->config->vsink);
+        worker->vsink = gst_element_factory_make(worker->config->vsink, NULL);
+        if (!worker->vsink) {
+            worker->vsink = gst_element_factory_make("xvimagesink", NULL);
+        }
+        if (!worker->vsink) {
+            g_critical("Failed to create pipeline video sink");
+            _send_error(worker,
+                        g_error_new(WORKER_ERROR,
+                                    WORKER_ERROR_UNABLE_TO_PERFORM,
+                                    "Could not create video sink"));
+            g_assert_not_reached();
+        }
+        gst_object_ref_sink(worker->vsink);
+
+        //special case for xvimagesink
+        {
+            gchar* element_name = gst_element_get_name(worker->vsink);
+            g_object_set(G_OBJECT(worker->vsink),
+                         "colorkey", 0x080810,
+                         NULL);
+            if (g_str_has_prefix(element_name, "xvimagesink"))
+            {
+                g_object_set(G_OBJECT(worker->vsink),
+                             "handle-events", TRUE,
+                             "force-aspect-ratio", TRUE,
+                             NULL);
+            }
+            g_free(element_name);
+        }
+
+        //do not dare to set video-sink in any other state
+        if( worker->pipeline && worker->state == GST_STATE_NULL )
+        {
+             g_object_set(worker->pipeline,
+                          "video-sink", worker->vsink,
+                          NULL);
+        }
+    }
+
+    /* We don't want to set XID to video sink here when in READY state, because
+       it prevents "prepare-xwindow-id" message. Setting it when we are
+       PAUSED or PLAYING is fine, because we already got "prepare-xwindow-id". */
+    if(worker->state == GST_STATE_PLAYING ||
+       worker->state == GST_STATE_PAUSED)
+    {
+        /* Check if we should use it right away */
+        mafw_gst_renderer_worker_apply_xid(worker);
+    }
+
+    _emit_property(worker, WORKER_PROPERTY_XID, G_TYPE_UINT, &worker->xid);
+
+}
+
+XID mafw_gst_renderer_worker_get_xid(MafwGstRendererWorker *worker)
+{
+    return worker->xid;
+}
+
+void mafw_gst_renderer_worker_set_render_rectangle(MafwGstRendererWorker *worker, render_rectangle *rect)
+{
+    /* Store the target window id */
+    g_debug("Setting render rectangle: X:%d,Y:%d  Width:%d, Height:%d",
+            rect->x, rect->y, rect->width, rect->height);
+
+    worker->x_overlay_rectangle.x = rect->x;
+    worker->x_overlay_rectangle.y = rect->y;
+    worker->x_overlay_rectangle.width = rect->width;
+    worker->x_overlay_rectangle.height = rect->height;
+
+    /* Check if we should use it right away */
+    mafw_gst_renderer_worker_apply_render_rectangle(worker);
+
+    GValueArray *rect_array = g_value_array_new(4);
+    GValue x;
+    GValue y;
+    GValue width;
+    GValue height;
+
+    _set_value(&x, G_TYPE_INT, &(rect->x));
+    _set_value(&y, G_TYPE_INT, &(rect->y));
+    _set_value(&width, G_TYPE_INT, &(rect->width));
+    _set_value(&height, G_TYPE_INT, &(rect->height));
+
+    g_value_array_insert(rect_array, 0, &x );
+    g_value_array_insert(rect_array, 1, &y );
+    g_value_array_insert(rect_array, 2, &width );
+    g_value_array_insert(rect_array, 3, &height );
+
+    GValue value;
+    memset(&value, 0, sizeof(value));
+    g_value_init(&value, G_TYPE_VALUE_ARRAY);
+    g_value_take_boxed(&value, rect_array);
+
+    _emit_property(worker, WORKER_PROPERTY_RENDER_RECTANGLE, G_TYPE_VALUE_ARRAY, &value);
+
+    g_value_unset(&value);
+}
+
+const render_rectangle* mafw_gst_renderer_worker_get_render_rectangle(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return &worker->x_overlay_rectangle;
+}
+
+gboolean mafw_gst_renderer_worker_get_autopaint(MafwGstRendererWorker *worker)
+{
+    return worker->autopaint;
+}
+
+void mafw_gst_renderer_worker_set_autopaint(MafwGstRendererWorker *worker,
+                                            gboolean autopaint)
+{
+    /* TODO Is this a bug or a feature? */
+    worker->autopaint = autopaint;
+    if (worker->vsink)
+        g_object_set(worker->vsink, "autopaint-colorkey", autopaint, NULL);
+
+    _emit_property(worker,
+                   WORKER_PROPERTY_AUTOPAINT,
+                   G_TYPE_BOOLEAN,
+                   &autopaint);
+
+}
+
+gboolean mafw_gst_renderer_worker_set_playback_speed(MafwGstRendererWorker* worker,
+                                                     gfloat speed)
+{
+    gboolean retVal = FALSE;
+
+    if (worker->state == GST_STATE_PLAYING)
+    {
+        worker->playback_speed = speed;
+
+        gint64 current_position;
+        GstFormat format = GST_FORMAT_TIME;
+
+        if (worker->pipeline && gst_element_query_position(worker->pipeline,
+                                                           &format,
+                                                           &current_position))
+        {
+
+            retVal = gst_element_seek(worker->pipeline,
+                                      speed,
+                                      GST_FORMAT_DEFAULT,
+                                      GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_KEY_UNIT,
+                                      GST_SEEK_TYPE_NONE,
+                                      current_position,
+                                      GST_SEEK_TYPE_NONE,
+                                      GST_CLOCK_TIME_NONE);
+
+            if(retVal)
+            {
+                _emit_property(worker,
+                               WORKER_PROPERTY_PLAYBACK_SPEED,
+                               G_TYPE_FLOAT,
+                               &speed);
+            }
+        }
+    }
+
+    return retVal;
+}
+
+gfloat mafw_gst_renderer_worker_get_playback_speed(MafwGstRendererWorker* worker)
+{
+    return worker->playback_speed;
+}
+
+void mafw_gst_renderer_worker_set_force_aspect_ratio(MafwGstRendererWorker *worker, gboolean force)
+{
+
+    worker->force_aspect_ratio = force;
+    if (worker->vsink)
+    {
+        g_object_set(worker->vsink, "force-aspect-ratio", force, NULL);
+    }
+    _emit_property(worker, WORKER_PROPERTY_FORCE_ASPECT_RATIO, G_TYPE_BOOLEAN, &force);
+
+}
+
+gboolean mafw_gst_renderer_worker_get_force_aspect_ratio(MafwGstRendererWorker *worker)
+{
+    return worker->force_aspect_ratio;
+}
+
+gint mafw_gst_renderer_worker_get_colorkey(MafwGstRendererWorker *worker)
+{
+    return worker->colorkey;
+}
+
+gboolean mafw_gst_renderer_worker_get_seekable(MafwGstRendererWorker *worker)
+{
+    return worker->media.seekable == SEEKABILITY_SEEKABLE;
+}
+
+gboolean mafw_gst_renderer_worker_get_streaming(MafwGstRendererWorker *worker)
+{
+    return uri_is_stream(worker->media.location);
+}
+
+const char* mafw_gst_renderer_worker_get_uri(MafwGstRendererWorker *worker)
+{
+    return worker->media.location;
+}
+
+static void _do_play(MafwGstRendererWorker *worker)
+{
+    g_assert(worker != NULL);
+
+    if (worker->pipeline == NULL) {
+        g_debug("play without a pipeline!");
+        return;
+    }
+    worker->report_statechanges = TRUE;
+
+    /* If we have to stay paused, we do and add the ready timeout. Otherwise, we
+     * move the pipeline */
+    if (!worker->stay_paused) {
+        /* If pipeline is READY, we move it to PAUSED, otherwise, to PLAYING */
+        if (worker->state == GST_STATE_READY) {
+            gst_element_set_state(worker->pipeline, GST_STATE_PAUSED);
+            g_debug("setting pipeline to PAUSED");
+        } else {
+            gst_element_set_state(worker->pipeline, GST_STATE_PLAYING);
+            g_debug("setting pipeline to PLAYING");
+        }
+    }
+    else {
+        g_debug("staying in PAUSED state");
+        _add_ready_timeout(worker);
+    }
+}
+
+void mafw_gst_renderer_worker_play(MafwGstRendererWorker *worker,
+                                   const gchar *uri)
+{
+    g_assert(uri);
+
+    mafw_gst_renderer_worker_stop(worker);
+    _reset_media_info(worker);
+
+    /* Set the item to be played */
+    worker->media.location = g_strdup(uri);
+
+    _start_play(worker);
+}
+
+/*
+ * Currently, stop destroys the Gst pipeline and resets the worker into
+ * default startup configuration.
+ */
+void mafw_gst_renderer_worker_stop(MafwGstRendererWorker *worker)
+{
+    g_debug("worker stop");
+    g_assert(worker != NULL);
+
+    /* If location is NULL, this is a pre-created pipeline */
+    if (worker->async_bus_id && worker->pipeline && !worker->media.location)
+        return;
+
+    _reset_pipeline_and_worker(worker);
+
+    /* context framework adaptation starts */
+    if (worker->context_nowplaying) {
+        context_provider_map_free(worker->context_nowplaying);
+        worker->context_nowplaying = NULL;
+    }
+    context_provider_set_null(CONTEXT_PROVIDER_KEY_NOWPLAYING);
+    /* context framework adaptation ends */
+
+    /* We are not playing, so we can let the screen blank */
+    if (worker->blanking__control_handler)
+    {
+        worker->blanking__control_handler(worker, worker->owner, FALSE);
+    }
+
+    /* And now get a fresh pipeline ready */
+    _construct_pipeline(worker, worker->config);
+}
+
+void mafw_gst_renderer_worker_pause(MafwGstRendererWorker *worker)
+{
+    g_assert(worker != NULL);
+
+    if (worker->buffering && worker->state == GST_STATE_PAUSED &&
+        !worker->prerolling)
+    {
+        /* If we are buffering and get a pause, we have to
+         * signal state change and stay_paused */
+        g_debug("Pausing while buffering, signalling state change");
+
+        /* We need to make sure that we go into real PAUSE state */
+        if (worker->blanking__control_handler)
+        {
+            worker->blanking__control_handler(worker, worker->owner, FALSE);
+        }
+        _do_pause_postprocessing(worker);
+    }
+    else
+    {
+        worker->report_statechanges = TRUE;
+        if (worker->seek_position == -1 && worker->state == GST_STATE_PLAYING )
+        {
+            gst_element_set_state(worker->pipeline, GST_STATE_PAUSED);
+            if (worker->blanking__control_handler)
+            {
+                worker->blanking__control_handler(worker, worker->owner, FALSE);
+            }
+        }
+    }
+
+    worker->stay_paused = TRUE;
+    worker->pause_frame_taken = FALSE;
+}
+
+/*
+ * Notifier to call when audio/video routing changes
+ */
+void mafw_gst_renderer_worker_notify_media_destination(
+    MafwGstRendererWorker *worker,
+    GSList *destinations)
+{
+    g_assert(worker != NULL);
+    g_assert(destinations != NULL);
+
+    /* 1. update our records of current destinations */
+    g_slist_free(worker->destinations);
+    worker->destinations = g_slist_copy(destinations);
+
+    /* 2. prevent blanking if we are playing video and outputting it on our own
+     * display, otherwise disable it */
+    if (worker->blanking__control_handler &&
+        worker->media.has_visual_content &&
+        worker->state == GST_STATE_PLAYING &&
+        g_slist_find(worker->destinations,
+                     GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)))
+    {
+        worker->blanking__control_handler(worker, worker->owner, TRUE);
+    }
+    else
+    {
+        worker->blanking__control_handler(worker, worker->owner, FALSE);
+    }
+
+    /* 3. disabling Dolby Headphone effect if not outputting to audio jack or
+     * bluetooth headphones, otherwise using the effect. Actual route check is done
+     * in set_dolby_*****_property function*/
+    set_dolby_music_property(worker, worker->config->mobile_surround_music.state);
+    set_dolby_video_property(worker, worker->config->mobile_surround_video.state);
+
+}
+
+void mafw_gst_renderer_worker_pause_at(MafwGstRendererWorker *worker, guint position)
+{
+    /* the current implementation works only from ready i.e. stopped state */
+    g_assert( worker != NULL);
+    worker->stay_paused = TRUE;
+    worker->pause_frame_taken = FALSE;
+    worker->seek_position = position;
+
+    if( worker->vsink )
+    {
+        g_object_set(worker->vsink, "show-preroll-frame",
+                     FALSE, NULL);
+    }
+}
+
+void mafw_gst_renderer_worker_resume(MafwGstRendererWorker *worker)
+{
+    worker->stay_paused = FALSE;
+    if (worker->buffering && worker->state == GST_STATE_PAUSED &&
+        !worker->prerolling) {
+        /* If we are buffering we cannot resume, but we know that the pipeline
+         * will be moved to PLAYING as stay_paused is FALSE, so we just
+         * activate the state change report, this way as soon as buffering
+         * is finished the pipeline will be set to PLAYING and the state
+         * change will be reported */
+        worker->report_statechanges = TRUE;
+        g_debug("Resumed while buffering, activating pipeline state changes");
+        /* Notice though that we can receive the Resume before we get any
+           buffering information. In that case we go with the "else" branch
+           and set the pipeline to to PLAYING. However, it is possible that
+           in this case we get the fist buffering signal before the PAUSED ->
+           PLAYING state change. In that case, since we ignore state changes
+           while buffering we never signal the state change to PLAYING. We
+           can only fix this by checking, when we receive a PAUSED -> PLAYING
+           transition if we are buffering, and in that case signal the state
+           change (if we get that transition while buffering is on, it can
+           only mean that the client resumed playback while buffering, and
+           we must notify the state change) */
+    } else {
+        _do_play(worker);
+    }
+
+    /* we want to resume no use for these timers anymore */
+    _remove_pause_frame_timeout(worker);
+    _remove_ready_timeout(worker);
+}
+
+MafwGstRendererWorker *mafw_gst_renderer_worker_new(gpointer owner)
+{
+    MafwGstRendererWorker *worker;
+
+    g_debug("%s", G_STRFUNC);
+
+    worker = g_new0(MafwGstRendererWorker, 1);
+    worker->owner = owner;
+    worker->report_statechanges = TRUE;
+    worker->state = GST_STATE_NULL;
+    worker->seek_position = -1;
+    worker->ready_timeout = 0;
+    worker->pause_frame_timeout = 0;
+    worker->duration_seek_timeout = 0;
+    worker->duration_seek_timeout_loop_count = 0;
+    worker->in_ready = FALSE;
+    worker->xid = 0;
+    worker->x_overlay_rectangle.x = -1;
+    worker->x_overlay_rectangle.y = -1;
+    worker->x_overlay_rectangle.width = -1;
+    worker->x_overlay_rectangle.height = -1;
+    worker->autopaint = TRUE;
+    worker->playback_speed = 1;
+    worker->colorkey = -1;
+    worker->vsink = NULL;
+    worker->asink = NULL;
+    worker->tsink = NULL;
+    worker->amixer = NULL;
+    worker->audiobin = NULL;
+    worker->tag_list = NULL;
+    worker->current_metadata = NULL;
+    worker->media.seekable = SEEKABILITY_SEEKABLE;
+
+    worker->destinations = NULL;
+
+    worker->current_frame_on_pause = FALSE;
+    worker->taking_screenshot = FALSE;
+    worker->force_aspect_ratio = TRUE;
+    _init_tmp_files_pool(worker);
+    worker->notify_seek_handler = NULL;
+    worker->notify_pause_handler = NULL;
+    worker->notify_play_handler = NULL;
+    worker->notify_buffer_status_handler = NULL;
+    worker->notify_eos_handler = NULL;
+    worker->notify_metadata_handler = NULL;
+    worker->notify_error_handler = NULL;
+    worker->blanking__control_handler = NULL;
+    worker->screenshot_handler = NULL;
+
+    worker->config = _create_default_configuration();
+
+    worker->seeker = mafw_gst_renderer_seeker_new();
+
+    if (!_context_fw_initialised)
+    {
+        /* context framework adaptation starts */
+        if (context_provider_init(DBUS_BUS_SESSION, CONTEXT_PROVIDER_BUS_NAME)) {
+            _context_fw_initialised = TRUE;
+            context_provider_install_key(CONTEXT_PROVIDER_KEY_NOWPLAYING, FALSE,
+                                         NULL, NULL);
+            g_debug("Initialized context framework provider");
+        }
+        else {
+            g_warning("Could not initialize context framework provider");
+        }
+    }
+    /* context framework adaptation ends */
+
+    return worker;
+
+}
+
+void mafw_gst_renderer_worker_exit(MafwGstRendererWorker *worker)
+{
+    _destroy_tmp_files_pool(worker);
+    _reset_pipeline_and_worker(worker);
+
+    /* We are not playing, so we can let the screen blank */
+    if (worker->blanking__control_handler)
+    {
+        worker->blanking__control_handler(worker, worker->owner, FALSE);
+    }
+
+    /* now finally sinks/bins are released */
+    if( worker->audiobin )
+    {
+        gst_object_unref(worker->audiobin);
+        worker->audiobin = NULL;
+    }
+    else if( worker->asink )
+    {
+        gst_object_unref(worker->asink);
+        worker->asink = NULL;
+    }
+
+    if( worker->vsink )
+    {
+        gst_object_unref(worker->vsink);
+        worker->vsink = NULL;
+    }
+
+    context_provider_stop();
+    _context_fw_initialised = FALSE;
+
+    if( worker->destinations )
+    {
+        g_slist_free(worker->destinations);
+        worker->destinations = NULL;
+    }
+
+    if( worker->config )
+    {
+        _free_configuration(worker->config);
+        worker->config = NULL;
+    }
+
+    if( worker->seeker )
+    {
+        mafw_gst_renderer_seeker_free(worker->seeker);
+        worker->seeker = NULL;
+    }
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/LibCredsStub.cpp b/qmafw-gst-subtitles-renderer/unittests/common/LibCredsStub.cpp
new file mode 100644 (file)
index 0000000..f372630
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QObject>
+#include <sys/creds.h>
+
+namespace Stub
+{
+    bool global_route_provider_trusted = true;
+}
+
+creds_t creds_gettask(pid_t /*pid*/)
+{
+    return (creds_t)1;
+}
+
+int creds_have_p(const creds_t creds, creds_type_t type, creds_value_t value)
+{
+    Q_UNUSED(creds);
+    Q_UNUSED(type);
+    Q_UNUSED(value);
+
+    if( Stub::global_route_provider_trusted )
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+long creds_str2creds(const char *credential, creds_value_t *value)
+{
+    Q_UNUSED(credential);
+    Q_UNUSED(value);
+
+    return 1234;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/MafwBasicRendererStub.cpp b/qmafw-gst-subtitles-renderer/unittests/common/MafwBasicRendererStub.cpp
new file mode 100644 (file)
index 0000000..c3a1e3b
--- /dev/null
@@ -0,0 +1,42 @@
+#include <MafwBasicRenderer.h>
+#include "MafwStubHelper.h"
+
+MafwStubHelper* m_stubHelper = 0;
+MafwRendererPolicy* m_policyStub;
+
+void setStubHelper(MafwStubHelper* stubHlp)
+{
+    m_stubHelper = stubHlp;
+}
+
+void setMafwRendererPolicy(MafwRendererPolicy *policy )
+{
+    m_policyStub = policy;
+}
+
+bool MafwBasicRenderer::initialize()
+{
+    return m_stubHelper->getReturn("initialize").toBool();
+}
+
+bool MafwBasicRenderer::setDefaultRendererPolicy(MafwRendererPolicy::PolicyGroup)
+{
+    return m_stubHelper->getReturn("setDefaultRendererPolicy").toBool();
+}
+
+MafwRendererPolicy* MafwBasicRenderer::rendererPolicy() const
+{
+    return m_policyStub;
+}
+
+bool MafwBasicRenderer::setMafwProperty(const QString &name, const QVariant &value)
+{
+    return MafwRenderer::setMafwProperty(name, value);
+}
+
+bool MafwBasicRenderer::pause()
+{
+    doPause();
+    return true;
+}
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/MafwPlaylistFileUtilityStub.cpp b/qmafw-gst-subtitles-renderer/unittests/common/MafwPlaylistFileUtilityStub.cpp
new file mode 100644 (file)
index 0000000..129a1e9
--- /dev/null
@@ -0,0 +1,66 @@
+#include "MafwGstRendererPlaylistFileUtility.h"
+#include "MafwGstRenderer.h"
+#include <QUrl>
+#include <QTimer>
+#include <QDebug>
+#include "MafwStubHelper.h"
+
+MafwGstRenderer* m_rnd = 0;
+QStringList stubPlaylistFileUtilityUris = QStringList() << "testUri1" << "testUri2";
+
+MafwGstRendererPlaylistFileUtility::MafwGstRendererPlaylistFileUtility(QObject* parent):
+        QObject(parent)
+{
+    m_rnd = static_cast<MafwGstRenderer*>(parent);
+}
+
+MafwGstRendererPlaylistFileUtility::~MafwGstRendererPlaylistFileUtility(){}
+
+void MafwGstRendererPlaylistFileUtility::parsePlaylistFile(const QUrl&)
+{    
+    qDebug() << "MafwGstRendererPlaylistFileUtility::parsePlaylistFile";
+    m_uriList.append(stubPlaylistFileUtilityUris);
+    Q_EMIT parsingReady(true);
+    Q_EMIT firstItemParsed();
+}
+
+QStringList MafwGstRendererPlaylistFileUtility::getUriList()
+{
+    return m_uriList;
+}
+
+QString MafwGstRendererPlaylistFileUtility::takeFirstUri()
+{
+    if (m_uriList.isEmpty())
+    {
+        return QString();
+    }
+    else
+    {
+        return m_uriList.takeFirst();
+    }
+}
+
+void MafwGstRendererPlaylistFileUtility::uriParsed(TotemPlParser*,
+                      gchar*,
+                      gpointer,
+                      MafwGstRendererPlaylistFileUtility*)
+{}
+
+void MafwGstRendererPlaylistFileUtility::readyCb(TotemPlParser*, GAsyncResult*, MafwGstRendererPlaylistFileUtility*)
+{}
+
+void MafwGstRendererPlaylistFileUtility::setPendingError(MafwError& error)
+{
+    m_pendingError = error;
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::takePendingError
+ ********************************************************************/
+MafwError MafwGstRendererPlaylistFileUtility::takePendingError()
+{
+    MafwError error = m_pendingError;
+    m_pendingError = MafwError();
+    return error;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/MafwRendererPolicyStub.cpp b/qmafw-gst-subtitles-renderer/unittests/common/MafwRendererPolicyStub.cpp
new file mode 100644 (file)
index 0000000..7018be8
--- /dev/null
@@ -0,0 +1,39 @@
+#include "MafwRendererPolicyStub.h"
+
+MafwRendererPolicyStub::MafwRendererPolicyStub()
+{
+}
+
+MafwRendererPolicyStub::~MafwRendererPolicyStub()
+{
+
+}
+
+bool MafwRendererPolicyStub::initialize(MafwRendererPolicy::PolicyGroup group)
+{
+    return group == MafwRendererPolicy::MediaPlayer;
+}
+
+void MafwRendererPolicyStub::setDefaultResources(MafwRendererPolicy::PolicyResourceFlags)
+{
+    //nothing to do here
+}
+
+void MafwRendererPolicyStub::request(MafwRendererPolicy::PolicyResourceFlags)
+{
+
+}
+
+void MafwRendererPolicyStub::release(MafwRendererPolicy::PolicyResourceFlags flags)
+{
+    m_latestRelease = flags;
+}
+
+MafwRendererPolicy::PolicyResourceFlags MafwRendererPolicyStub::latestReleaseFlags()
+{
+    MafwRendererPolicy::PolicyResourceFlags toReturn = m_latestRelease;
+    m_latestRelease = 0;
+    return toReturn;
+}
+
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/MafwRendererPolicyStub.h b/qmafw-gst-subtitles-renderer/unittests/common/MafwRendererPolicyStub.h
new file mode 100644 (file)
index 0000000..5a476e9
--- /dev/null
@@ -0,0 +1,21 @@
+#include<MafwRendererPolicy.h>
+
+class MafwRendererPolicyStub : public MafwRendererPolicy
+{
+    Q_OBJECT
+
+public:
+    MafwRendererPolicyStub();
+    ~MafwRendererPolicyStub();
+
+    bool initialize(MafwRendererPolicy::PolicyGroup);
+    void setDefaultResources(QFlags<MafwRendererPolicy::PolicyResourceFlag>);
+    void request(QFlags<MafwRendererPolicy::PolicyResourceFlag>);
+    void release(QFlags<MafwRendererPolicy::PolicyResourceFlag>);
+
+    //testing functions
+    MafwRendererPolicy::PolicyResourceFlags latestReleaseFlags();
+
+private:
+    MafwRendererPolicy::PolicyResourceFlags m_latestRelease;
+};
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/MafwRoutingInfoHandlerStub.cpp b/qmafw-gst-subtitles-renderer/unittests/common/MafwRoutingInfoHandlerStub.cpp
new file mode 100644 (file)
index 0000000..f33d822
--- /dev/null
@@ -0,0 +1,67 @@
+
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwRoutingInfoHandler.h"
+
+#include <contextsubscriber/contextproperty.h>
+#include <contextsubscriber/contextpropertyinfo.h>
+#include <contextsubscriber/contextproviderinfo.h>
+
+#include <QDebug>
+#include <QDBusReply>
+#include <QDBusConnectionInterface>
+
+bool routeTrusted = false;
+
+MafwRoutingInfoHandler::MafwRoutingInfoHandler(ContextProperty& property) :
+        m_property(property)
+{
+
+}
+
+MafwRoutingInfoHandler::~MafwRoutingInfoHandler()
+{
+}
+
+void MafwRoutingInfoHandler::startProviderCheck()
+{
+    qDebug() << "startProviderCheck";
+}
+
+ void MafwRoutingInfoHandler::callFinishedSlot(QDBusPendingCallWatcher*)
+ {
+     qDebug() << "callFinishedSlot";
+ }
+
+void MafwRoutingInfoHandler::gotReply(int)
+{
+    Q_EMIT routeChanged(routeTrusted);
+}
+
+void MafwRoutingInfoHandler::error()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    Q_EMIT routeChanged(false);
+}
+
+bool MafwRoutingInfoHandler::isPidTrusted (int)
+{
+
+    return true;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/MafwStubHelper.cpp b/qmafw-gst-subtitles-renderer/unittests/common/MafwStubHelper.cpp
new file mode 100644 (file)
index 0000000..9e2d4fa
--- /dev/null
@@ -0,0 +1,140 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+
+#include <QDebug>
+#include <QStringList>
+
+#include "MafwStubHelper.h"
+
+MafwStubHelper::MafwStubHelper()
+{
+    m_expectedCalls = QQueue<ExpectedItem*>();
+}
+
+MafwStubHelper::~MafwStubHelper()
+{
+       clear();
+}
+
+void MafwStubHelper::printExpects() const
+{
+    QStringList expectedNames;
+    for(int i=0; i<m_expectedCalls.size(); i++ )
+    {
+        expectedNames << m_expectedCalls[i]->expectedName;
+    }
+    qDebug() << "Expected calls enqueued (" << m_expectedCalls.size() << "): \n\t" << expectedNames.join(",\n\t ");
+}
+
+void MafwStubHelper::expect(const QString& function, QVariant returnVal)
+{
+    QList<QVariant> emptyParams;
+    QList<QVariant> returnList;
+    returnList << returnVal;
+    expect(function, emptyParams, returnList);
+}
+
+
+void MafwStubHelper::expect(const QString function, const QList<QVariant> params,
+                                                       const QList<QVariant> returns)
+{
+       qDebug() << "MafwStubHelper::expect, function = " << function << " " << returns.at(0);
+       
+       ExpectedItem* item = new ExpectedItem;
+       item->expectedName = function;
+       item->expectedParams = params;
+       item->returnValues = returns;
+       m_expectedCalls.enqueue(item);
+}
+
+QVariant MafwStubHelper::getReturn(const QString& function)
+{
+    QList<QVariant> emptyParams;
+    QList<QVariant> returnList;
+    getReturn(function, emptyParams, returnList);
+    if (returnList.isEmpty())
+    {
+        return QVariant();
+    }
+    else
+    {
+        return returnList.first();
+    }
+}
+
+void MafwStubHelper::getReturn(const QString function, const QList<QVariant> params,
+                                                          QList<QVariant>& returns)
+{
+    // Check if the call is expected
+    if ( m_expectedCalls.isEmpty() )
+    {
+        qDebug() << "MafwStubHelper::getReturn, function = " << function <<", no expected calls";
+        return;
+    }
+    if (!m_expectedCalls.isEmpty() && function.compare(m_expectedCalls.head()->expectedName))
+    {
+        qDebug() << "MafwStubHelper::getReturn:  " << function << ", not expected (2)";
+        printExpects();
+        return;
+    }
+    ExpectedItem* item = m_expectedCalls.dequeue();
+    
+    // Check if the parameters match
+    if (!item->expectedParams.isEmpty())
+    {
+        for (int i = 0; i < item->expectedParams.count() && item->expectedParams.count() == params.count(); ++i)
+        {
+            if (item->expectedParams.at(i) != params.at(i))
+            {
+                qDebug() << "MafwStubHelper::getReturn:  " << function <<", not expected (2)";
+                return;
+            }
+        }
+    }
+    // Expected parameters list was empty but given was not
+    else if (!params.isEmpty())
+    {
+        qDebug() << "MafwStubHelper::getReturn: " << function <<", not expected (3)";
+        return;
+    }
+    else
+    {
+    }
+    
+    // Everything ok, let's find the return values
+    returns = item->returnValues;
+    
+    qDebug() << "MafwStubHelper::getReturn, function: " << function << ", returns: " << returns;
+    
+    delete item;
+}
+
+bool MafwStubHelper::allCallsConsumed() const
+{      
+    return m_expectedCalls.isEmpty();
+}
+
+void MafwStubHelper::clear()
+{
+    qDebug() << "MafwStubHelper::clear()";
+    
+    qDeleteAll(m_expectedCalls);
+    m_expectedCalls.clear();
+}
+
+// End of file
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/MafwStubHelper.h b/qmafw-gst-subtitles-renderer/unittests/common/MafwStubHelper.h
new file mode 100644 (file)
index 0000000..87a6871
--- /dev/null
@@ -0,0 +1,108 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFWSTUBHELPER_H_
+#define MAFWSTUBHELPER_H_
+
+#include <QQueue>
+#include <QList>
+#include <QMultiMap>
+#include <QString>
+#include <QVariant>
+
+/**
+ * This class is meant to help implementing stubs needed in unit testing. 
+ * 
+ * Usage: Create instance of MafwStubHelper and provide your stub access 
+ * to it. Initialize MafwStubHelper with function calls the stub is 
+ * expected to get. Implement your stub to ask for return values from 
+ * MafwStubHelper. At the end of a test case, check if all expected
+ * calls are consumed. 
+ */
+
+
+class MafwStubHelper
+{
+public:
+       MafwStubHelper();
+       ~MafwStubHelper();
+       
+       /**
+        * expect - Adds call to expected calls
+        * 
+        * @param  function  Name of the expected function call, without paranthesis.
+        * @param  params    List of expected parameters given to function call.
+        * @param  returns   List of return values to be given to the stub.
+        */
+       void expect(const QString function, const QList<QVariant> params, const QList<QVariant> returns);
+       
+       /**
+     * expect - Adds call to expected calls
+     * 
+     * @param  function  Name of the expected function call, without paranthesis.
+     * @param  returnVal The return value to be given to the stub.
+     */
+       void expect(const QString& function, QVariant returnVal);
+       
+       /**
+        * getReturn - Consumes call from expected calls
+        * 
+        * @param  function  Name of the function call, without paranthesis.
+        * @param  params    List of parameters given to function call.
+        * @param  returns   Empty list for getting the return values.
+        *                                       List is empty at return if function wasn't the next expected function call.
+        */
+       void getReturn(const QString function, const QList<QVariant> params, QList<QVariant>& returns);
+       
+       /**
+     * getReturn - Consumes call from expected calls
+     * 
+     * @param  function  Name of the function call, without paranthesis.
+     * @return return value is invalid if function wasn't the next expected function call.
+     */
+       QVariant getReturn(const QString& function);
+       
+       /**
+        * allCallsConsumed - Checks if all expected calls are consumed
+        * 
+        * @return true, if all expected calls are consumed
+        *         false otherwise.
+        */
+       bool allCallsConsumed() const;
+
+       /**
+        * clear - Clears all data
+        */
+       void clear();
+
+private:
+        void printExpects() const;
+
+       
+private:
+       
+       struct ExpectedItem
+       {
+               QString expectedName;
+               QList<QVariant> expectedParams;
+               QList<QVariant> returnValues;
+       };
+       
+       QQueue<ExpectedItem*> m_expectedCalls;
+};
+
+#endif /*MAFWSTUBHELPER_H_*/
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/QNetworkStubs.cpp b/qmafw-gst-subtitles-renderer/unittests/common/QNetworkStubs.cpp
new file mode 100644 (file)
index 0000000..d97aa74
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "QNetworkStubs.h"
+
+#include <QDebug>
+#include <QTimer>
+#include <QtNetwork/QNetworkConfiguration>
+#include <QtNetwork/QNetworkConfigurationManager>
+
+
+NetworkStubHelper networkStub;
+int NetworkStubHelper::networkConfigurationManagerInstances = 0;
+
+/**
+
+  QNetworkConfiguration
+
+  **/
+
+bool NetworkStubHelper::currentCreatedConfigIsValid = false;
+
+static int staticCreationId = 0;
+class QNetworkConfigurationPrivate : public QSharedData
+{
+public:
+    int creationId;
+    bool isValid;
+};
+
+QNetworkConfiguration::QNetworkConfiguration()
+{
+    d = new QNetworkConfigurationPrivate;
+    d->creationId = ++staticCreationId;
+    d->isValid = networkStub.currentCreatedConfigIsValid;
+}
+
+QNetworkConfiguration::~QNetworkConfiguration()
+{
+
+}
+
+QNetworkConfiguration::QNetworkConfiguration(const QNetworkConfiguration &other)
+{
+    d = new QNetworkConfigurationPrivate;
+    d->creationId = other.d->creationId;
+}
+
+QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const
+{
+    return networkStub.m_currentConfState;
+}
+
+QString QNetworkConfiguration::name() const
+{
+    return "Test conf";
+}
+
+bool QNetworkConfiguration::isValid() const
+{
+    return d->isValid;
+}
+
+QNetworkConfiguration& QNetworkConfiguration::operator=(QNetworkConfiguration const &other)
+{
+    d->creationId = other.d->creationId;
+    return *this;
+}
+
+bool QNetworkConfiguration::operator==(const QNetworkConfiguration &other ) const
+{
+    return d->creationId == other.d->creationId;
+}
+
+/**
+
+  QNetworkConfigurationManager
+
+  **/
+
+QNetworkConfigurationManager::QNetworkConfigurationManager(QObject *parent)
+    :
+    QObject(parent)
+{
+    ++networkStub.networkConfigurationManagerInstances;
+    if( networkStub.networkConfigurationManagerInstances == 1)
+    {
+        connect( &networkStub, SIGNAL(configurationChange(QNetworkConfiguration)),
+                     this, SIGNAL(configurationChanged(QNetworkConfiguration)));
+    }
+}
+
+QNetworkConfigurationManager::~QNetworkConfigurationManager()
+{
+    --networkStub.networkConfigurationManagerInstances;
+    if( networkStub.networkConfigurationManagerInstances == 0 )
+    {
+        networkStub.disconnect(this);
+    }
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/QNetworkStubs.h b/qmafw-gst-subtitles-renderer/unittests/common/QNetworkStubs.h
new file mode 100644 (file)
index 0000000..4c31744
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef QNETWORKSTUBS_H
+#define QNETWORKSTUBS_H
+
+#include <QObject>
+#include <QtNetwork/QNetworkConfiguration>
+
+class QNetworkConfigurationManager;
+
+class NetworkStubHelper : public QObject
+{
+    Q_OBJECT
+
+    static int networkConfigurationManagerInstances;
+
+    friend class QNetworkConfiguration;
+    friend class QNetworkConfigurationManager;
+public:
+    static bool currentCreatedConfigIsValid;
+
+    void emitConfigurationChange(const QNetworkConfiguration &config,
+                                 QNetworkConfiguration::StateFlags confState)
+    {
+        m_currentConfState = confState;
+        Q_EMIT configurationChange(config);
+    }
+
+    void changeCurrentConfiguration(int id);
+
+Q_SIGNALS:
+    void configurationChange(QNetworkConfiguration config);
+
+private:
+    QNetworkConfiguration::StateFlags m_currentConfState;
+};
+
+#endif // QNETWORKSTUBS_H
diff --git a/qmafw-gst-subtitles-renderer/unittests/common/renderer-worker-stub.c b/qmafw-gst-subtitles-renderer/unittests/common/renderer-worker-stub.c
new file mode 100644 (file)
index 0000000..b8deb3d
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <string.h> //memset
+#include "mafw-gst-renderer-worker.h"
+#include "mafw-gst-renderer-utils.h"
+
+GError* global_error = 0;
+gint global_position = 0;
+gint global_worker_audio_destination = -1;
+gint global_worker_video_destination = -1;
+gchar *global_worker_uri = 0;
+gint global_worker_stop_called = 0;
+gint global_worker_seek_request = 0;
+GSList *global_worker_destinations = NULL;
+guint global_ready_timeout = 99999;
+
+guint m_volume;
+gboolean m_mute;
+gboolean m_current_frame_on_pause;
+gboolean m_force_aspect_ratio;
+gfloat m_playback_speed = 1;
+XID m_xid;
+
+render_rectangle m_render_rectangle;
+configuration *current_worker_conf;
+
+
+gboolean global_worker_playing = FALSE;
+
+#define UNUSED(x) (void)(x)
+
+void mafw_gst_renderer_worker_set_volume(MafwGstRendererWorker *worker,
+                                         guint volume)
+{
+    UNUSED(worker);
+    m_volume = volume;
+}
+
+guint mafw_gst_renderer_worker_get_volume(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return m_volume;
+}
+
+void mafw_gst_renderer_worker_set_mute(MafwGstRendererWorker *worker,
+                                       gboolean mute)
+{
+    UNUSED(worker);
+    m_mute = mute;
+}
+
+gboolean mafw_gst_renderer_worker_get_mute(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return m_mute;
+}
+
+gint64 mafw_gst_renderer_worker_get_last_known_duration(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return 10;
+}
+
+const char* mafw_gst_renderer_worker_get_uri(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return global_worker_uri;
+}
+
+gboolean mafw_gst_renderer_worker_get_seekable(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return TRUE;
+}
+
+void _free_configuration(configuration *config)
+{
+    if( !config )
+    {
+        return;
+    }
+
+    if( config->asink )
+    {
+        g_free(config->asink);
+    }
+    if( config->vsink )
+    {
+        g_free(config->vsink);
+    }
+
+    g_free(config);
+}
+
+void mafw_gst_renderer_worker_set_current_frame_on_pause(
+    MafwGstRendererWorker *worker,
+    gboolean current_frame_on_pause)
+{
+    UNUSED(worker);
+    m_current_frame_on_pause = current_frame_on_pause;
+}
+
+gboolean mafw_gst_renderer_worker_get_current_frame_on_pause(
+    MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return m_current_frame_on_pause;
+}
+
+void mafw_gst_renderer_worker_set_position(MafwGstRendererWorker *worker,
+                                           GstSeekType seek_type,
+                                           gint position, GError **error)
+{
+    UNUSED(worker);
+    UNUSED(seek_type);
+    global_worker_seek_request = position;
+    *error = global_error;
+}
+
+gint mafw_gst_renderer_worker_get_position(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return global_position;
+}
+
+void mafw_gst_renderer_worker_set_xid(MafwGstRendererWorker *worker, XID xid)
+{
+    UNUSED(worker);
+    m_xid = xid;
+}
+
+gboolean mafw_gst_renderer_worker_get_streaming(MafwGstRendererWorker *worker)
+{
+    return uri_is_stream(global_worker_uri);
+}
+
+XID mafw_gst_renderer_worker_get_xid(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return m_xid;
+}
+
+
+void mafw_gst_renderer_worker_set_render_rectangle(MafwGstRendererWorker *worker, render_rectangle *rect)
+{
+    UNUSED(worker);
+    m_render_rectangle.x = rect->x;
+    m_render_rectangle.y = rect->y;
+    m_render_rectangle.width = rect->width;
+    m_render_rectangle.height = rect->height;
+}
+
+const render_rectangle* mafw_gst_renderer_worker_get_render_rectangle(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return &m_render_rectangle;
+}
+
+
+gboolean mafw_gst_renderer_worker_get_autopaint(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return TRUE;
+}
+
+void mafw_gst_renderer_worker_set_ready_timeout(MafwGstRendererWorker *worker,
+                                                guint seconds)
+{
+    UNUSED(worker);
+    global_ready_timeout = seconds;
+}
+
+void mafw_gst_renderer_worker_set_autopaint(MafwGstRendererWorker *worker,
+                                            gboolean autopaint)
+{
+    UNUSED(worker);
+    UNUSED(autopaint);
+}
+
+gint mafw_gst_renderer_worker_get_colorkey(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return 1;
+}
+
+void mafw_gst_renderer_worker_play(MafwGstRendererWorker *worker,
+                                   const gchar *uri)
+{
+    UNUSED(worker);
+    UNUSED(uri);
+    global_worker_playing = TRUE;
+    g_free(global_worker_uri);
+    global_worker_uri = g_strdup(uri);
+    worker->notify_play_handler(worker, worker->owner);
+}
+
+void mafw_gst_renderer_worker_stop(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    global_worker_playing = FALSE;
+    ++global_worker_stop_called;
+
+    g_free(global_worker_uri);
+    global_worker_uri = NULL;
+}
+
+void mafw_gst_renderer_worker_pause(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    global_worker_playing = FALSE;
+    worker->notify_pause_handler(worker, worker->owner);
+}
+
+void mafw_gst_renderer_worker_pause_at(MafwGstRendererWorker *worker, guint position)
+{
+    UNUSED(worker);
+    UNUSED(position);
+}
+
+void mafw_gst_renderer_worker_resume(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+}
+
+MafwGstRendererWorker *mafw_gst_renderer_worker_new(gpointer owner)
+{
+    MafwGstRendererWorker *newWorker = g_new0(MafwGstRendererWorker, 1);
+    newWorker->owner = owner;
+    newWorker->config = g_new0(configuration, 1);
+    return newWorker;
+}
+
+void mafw_gst_renderer_worker_exit(MafwGstRendererWorker *worker)
+{
+    if( worker )
+    {
+        _free_configuration(worker->config);
+        worker->config = NULL;
+    }
+}
+
+gboolean mafw_gst_renderer_worker_set_playback_speed(MafwGstRendererWorker *worker, gfloat speed)
+{
+    UNUSED(worker);
+
+    if(!global_worker_playing)
+    {
+        return FALSE;
+    }
+
+    m_playback_speed = speed;
+
+    GValue v;
+    memset(&v, 0, sizeof(GValue));
+    g_value_init(&v, G_TYPE_FLOAT);
+    g_value_set_float(&v, m_playback_speed);
+
+    worker->notify_property_handler(worker, worker->owner, WORKER_PROPERTY_PLAYBACK_SPEED, &v);
+    g_value_unset(&v);
+
+    return TRUE;
+}
+
+gfloat mafw_gst_renderer_worker_get_playback_speed(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return m_playback_speed;
+}
+
+void mafw_gst_renderer_worker_set_force_aspect_ratio(MafwGstRendererWorker *worker, gboolean force)
+{
+    UNUSED(worker);
+    m_force_aspect_ratio = force;
+}
+
+gboolean mafw_gst_renderer_worker_get_force_aspect_ratio(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+    return m_force_aspect_ratio;
+}
+
+void mafw_gst_renderer_worker_notify_media_destination(MafwGstRendererWorker *worker,
+                                                       GSList *destination)
+{
+    UNUSED(worker);
+    g_slist_free(global_worker_destinations);
+    global_worker_destinations = g_slist_copy(destination);
+}
+
+configuration* mafw_gst_renderer_worker_create_default_configuration(MafwGstRendererWorker *worker)
+{
+    configuration *config = g_malloc0(sizeof(configuration));
+    config->asink = g_strdup("pulsesink");
+    config->vsink = g_strdup("omapxvsink");
+    config->flags = 67;
+    config->buffer_time = 300000;
+    config->latency_time = 100000;
+
+    /* timers */
+    config->milliseconds_to_pause_frame = 1000;
+    config->seconds_to_pause_to_ready = 3;
+
+    /* dhmmixer */
+    config->use_dhmmixer = TRUE;
+
+    config->mobile_surround_music.state = 0;
+    config->mobile_surround_music.room = 2;
+    config->mobile_surround_music.color = 2;
+    config->mobile_surround_video.state = 0;
+    config->mobile_surround_video.room = 2;
+    config->mobile_surround_video.color = 2;
+
+    return config;
+}
+
+void mafw_gst_renderer_worker_set_configuration(MafwGstRendererWorker *worker, configuration *config)
+{
+    if( worker->config )
+    {
+        _free_configuration(worker->config);
+    }
+    worker->config = config;
+    current_worker_conf = config;
+}
+
+void set_dolby_music_property(MafwGstRendererWorker *worker, guint prop)
+{
+    worker->config->mobile_surround_music.state = prop;
+}
+
+void set_dolby_music_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty)
+{
+    if (isRoomProperty)
+    {
+        worker->config->mobile_surround_music.room = prop;
+    }
+    else
+    {
+        worker->config->mobile_surround_music.color = prop;
+    }
+}
+
+void set_dolby_video_property(MafwGstRendererWorker *worker, guint prop)
+{
+    worker->config->mobile_surround_video.state = prop;
+}
+
+void set_dolby_video_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty)
+{
+    if (isRoomProperty)
+    {
+        worker->config->mobile_surround_video.room = prop;
+    }
+    else
+    {
+        worker->config->mobile_surround_video.color = prop;
+    }
+}
+
+gint64 mafw_gst_renderer_worker_get_duration(MafwGstRendererWorker *worker)
+{
+    UNUSED(worker);
+
+    return 0;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/media b/qmafw-gst-subtitles-renderer/unittests/media
new file mode 120000 (symlink)
index 0000000..11718d8
--- /dev/null
@@ -0,0 +1 @@
+ut_MafwGstRendererWorker/media/
\ No newline at end of file
diff --git a/qmafw-gst-subtitles-renderer/unittests/run_all_tests.sh b/qmafw-gst-subtitles-renderer/unittests/run_all_tests.sh
new file mode 100755 (executable)
index 0000000..d953d4d
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+STATUS=0
+
+qmake -project SUBDIRS+=`find . -type d -name ut_\*` -t subdirs -nopwd
+qmake
+if [ $SINGLE_PROCESS == "yes" ]; then 
+  make -B 
+else
+  make -B -j3
+fi
+if [ $? -ne 0 ]; then
+  exit 1
+fi
+
+files=`find . -maxdepth 2 -name 'ut_*' -type f -perm -u+x -print`
+
+echo '<?xml version="1.0"?>' > result.xml
+echo '<unittestresults>'  >> result.xml
+for file in $files; do
+    echo "Running test $file"
+    $file -lightxml -o tmp_result.xml;
+    
+    if [ $? -ne 0 ]; then
+      STATUS=2
+    fi
+
+    cat tmp_result.xml >>result.xml
+done
+echo '</unittestresults>'  >> result.xml
+rm -f tmp_result.xml
+sh run_valgrind.sh
+
+echo "Done"
+exit $STATUS
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/run_valgrind.sh b/qmafw-gst-subtitles-renderer/unittests/run_valgrind.sh
new file mode 100755 (executable)
index 0000000..41136e9
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+export G_SLICE=always-malloc G_DEBUG=gc-friendly 
+#WAIT_TIMEOUT is for worker test
+export WAIT_TIMEOUT=25000
+find . -maxdepth 2 -name 'ut_*' -type f -perm -u+x -print | xargs -t -i{} valgrind --leak-check=full --xml=yes --suppressions=test.suppressions --xml-file={}.vg.xml {}
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/test.suppressions b/qmafw-gst-subtitles-renderer/unittests/test.suppressions
new file mode 100644 (file)
index 0000000..aa76012
--- /dev/null
@@ -0,0 +1,2744 @@
+{
+   <Possibly lost: Maemo::QmDisplayState::QmDisplayState>
+   Memcheck:Leak
+   ...
+   fun:_ZN5Maemo14QmDisplayStateC1EP7QObject
+   ...
+}
+{
+   <Possibly lost: ContextProperty::ContextProperty>
+   Memcheck:Leak
+   ...
+   fun:_ZN15ContextPropertyC1ERK7QStringP7QObject
+}
+{
+   <Possibly lost: QDBusConnection::sessionBus()>
+   Memcheck:Leak
+   fun:malloc
+   fun:dbus_malloc
+   ...
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   fun:dbus_message_new_signal
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libQtDBus.so.*
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+   obj:/targets/*/usr/lib/libQtDBus.so.*
+   fun:_ZN15QDBusConnection10sessionBusEv
+}
+{
+   <Possibly lost:  QDBusConnection::connectToBus>
+   Memcheck:Leak
+   fun:calloc
+   fun:dbus_malloc0
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   fun:dbus_parse_address
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libQtDBus.so.*
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+   obj:/targets/*/usr/lib/libQtDBus.so.*
+}
+{
+   <Possibly lost dbus_message_new_signal>
+   Memcheck:Leak
+   fun:realloc
+   fun:dbus_realloc
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   fun:dbus_message_new_signal
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+   obj:/targets/*/usr/lib/libdbus-1.so.*
+}
+{
+   <Possibly lost: start_thread>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_slice_alloc
+   ...
+   fun:g_main_context_new
+   fun:_ZN27QEventDispatcherGlibPrivateC1EP13_GMainContext
+   fun:_ZN20QEventDispatcherGlibC1EP7QObject
+   obj:/targets/*/usr/lib/libQtCore.so.*
+   obj:/targets/*/usr/lib/libQtCore.so.*
+   fun:start_thread
+}
+{
+   <Possibly lost: g_option_context_parse>
+   Memcheck:Leak
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+   fun:g_option_context_parse
+}
+{
+   <Possibly lost: gst_element_register>
+   Memcheck:Leak
+   ...
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_object_newv
+   ...
+   fun:gst_element_register
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+}
+{
+   <Possibly lost: gst_task_pool_new>
+   Memcheck:Leak
+   fun:*alloc
+   fun:g_malloc*
+   ...
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_object_newv
+   fun:gst_task_pool_new
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+}
+{
+   <Possibly lost: gst_caps_new_simple>
+   Memcheck:Leak
+   ...
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/lib/libglib-2.*
+   ...
+   fun:gst_caps_new_simple
+}
+
+{
+   <Possibly lost: gst_caps_copy>
+   Memcheck:Leak
+   ...
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/lib/libglib-2.*
+   ...
+   fun:gst_caps_copy
+   ...
+   fun:g_object_newv
+   fun:g_object_new_valist
+}
+
+{
+   <Possibly lost: gst_pad_set_caps>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:gst_pad_set_caps
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+}
+
+{
+   <Possibly lost: gst_pad_start_task>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   ...
+   fun:gst_pad_start_task
+   ...
+   obj:/targets/*/usr/lib/libgstbase-0.1*
+}
+
+
+{
+   <Possibly lost: gst_update_registry>
+   Memcheck:Leak
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+   fun:gst_registry_binary_read_cache
+   fun:gst_update_registry
+}
+
+{
+   <Possibly lost: gst_pad_new_from_template>
+   Memcheck:Leak
+   fun:memalign
+   ...
+   fun:g_object_new
+   fun:gst_pad_new_from_template
+   obj:/targets/*/usr/lib/libgstbase-0.1*
+}
+
+
+{
+   <Possibly lost: g_type_class_ref>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2.*
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   fun:g_type_create_instance
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_object_newv
+   fun:gst_task_pool_new
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+   fun:g_type_class_ref
+}
+{
+   <Possibly lost: gst_buffer_new_and_alloc>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   ...
+   fun:gst_buffer_new_and_alloc
+}
+{
+   <Possibly lost: gst_element_factory_make>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2.*
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   fun:g_type_create_instance
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_object_newv
+   ...
+   fun:gst_element_factory_create
+   fun:gst_element_factory_make
+}
+{
+   <Possibly lost: gst_caps_is_subset>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   ...
+   fun:gst_caps_subtract
+   fun:gst_caps_is_subset
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.25.0
+}
+{
+   <Possibly lost: gst_element_change_state>
+   Memcheck:Leak
+   fun:memalign
+   ...
+   fun:gst_element_change_state
+   ...
+}
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_ptr_array_add
+   fun:g_main_context_check
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_main_context_pending
+   fun:_ZN20QEventDispatcherGlib16hasPendingEventsEv
+   fun:_ZN16QCoreApplication16hasPendingEventsEv
+}
+{
+   <Possibly lost: QEventDispatcherGlibPrivateC2EP13_GMainContext>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_slice_alloc
+   fun:g_array_sized_new
+   fun:g_array_new
+   fun:g_static_private_set
+   fun:g_get_filename_charsets
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_thread_init_glib
+   fun:g_thread_init
+   fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+}
+{
+   <Possibly lost: QCoreApplicationPrivate >
+   Memcheck:Leak
+   ...
+   fun:g_get_language_names
+   fun:g_thread_init
+   fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+   fun:_ZN16QCoreApplication4initEv
+   fun:_ZN16QCoreApplicationC2ER23QCoreApplicationPrivate
+}
+{
+   <Possibly lost: QApplicationPrivate::createEventDispatcher()>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   ...
+   fun:g_get_filename_charsets
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_thread_init_glib
+   fun:g_thread_init
+   fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+}
+{
+   <Possibly lost: QCoreApplication::init() 1>
+   Memcheck:Leak
+   fun:calloc
+   fun:g_malloc0
+   ...
+   fun:g_get_filename_charsets
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_thread_init_glib
+   fun:g_thread_init
+   fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+   fun:_ZN16QCoreApplication4initEv
+}
+{
+   <Possibly lost: QCoreApplication::init() 2>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_array_set_size
+   fun:g_static_private_set
+   fun:g_get_language_names
+   fun:g_thread_init
+   fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+   fun:_ZN16QCoreApplication4initEv
+}
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_slice_alloc
+   ...
+   ...
+   fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+}
+
+{
+   <Possibly lost: QApplication::QApplication>
+   Memcheck:Leak
+   fun:_Znwj
+   obj:/targets/*/usr/lib/libQtCore.so.*
+   obj:/targets/*/usr/lib/libQtCore.so.*
+   obj:/targets/*/usr/lib/libQtCore.so.*
+   fun:_ZN9QSettingsC1ENS_5ScopeERK7QStringS3_P7QObject
+   fun:_ZN19QApplicationPrivate18x11_apply_settingsEv
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+   fun:main
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/usr/lib/libfontconfig.so.*
+   obj:/targets/*/usr/lib/libfontconfig.so.*
+   ...
+   obj:/targets/*/usr/lib/libexpat.so.*
+   obj:/targets/*/usr/lib/libexpat.so.*
+   ...
+   fun:XML_ParseBuffer
+   fun:FcConfigParseAndLoad
+   fun:FcConfigParseAndLoad
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_ptr_array_add
+   fun:g_main_context_check
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_main_context_iteration
+   fun:_ZN20QEventDispatcherGlib13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_ZN16QCoreApplication13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEEi
+   fun:_ZN5QTestL5qWaitEi
+}
+
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   fun:_dl_relocate_object
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+   obj:*/ld-2.5.so
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   fun:_dl_relocate_object
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:do_dlopen
+   fun:_dl_catch_error
+   fun:dlerror_run
+   fun:__libc_dlopen_mode
+   fun:__gconv_find_shlib
+   fun:find_module
+   fun:__gconv_lookup_cache
+   fun:__gconv_find_transform
+   
+   obj:*/ld-2.5.so
+}                      
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   fun:__libc_dlopen_mode
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   fun:__libc_dlopen_mode
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+   fun:__libc_dlopen_mode
+   obj:/targets/*/lib/libc-2.5.so
+   obj:/targets/*/lib/libc-2.5.so
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+   fun:main
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+   fun:main
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   obj:/targets/*/usr/lib/libQtGui.so.4.6.0
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+   fun:_ZN8QLibrary4loadEv
+   obj:/targets/*/usr/lib/libQtGui.so.*
+   fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   obj:/targets/*/lib/ld-2.5.so
+   obj:/targets/*/lib/libdl-2.5.so
+   fun:dlopen
+   fun:_ZN15QLibraryPrivate8load_sysEv
+   fun:_ZN15QLibraryPrivate4loadEv
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   fun:_ZN11QMetaObject16checkConnectArgsEPKcS1_
+}
+{
+   <insert a suppression name here>
+   Memcheck:Addr1
+   fun:_ZN11QMetaObject16checkConnectArgsEPKcS1_
+}
+{
+   <insert a suppression name here>
+   Memcheck:Cond
+   fun:strlen
+   fun:_dl_init_paths
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+   obj:/targets/*/lib/ld-2.*.so
+}
+{  
+   <insert a suppression name here>
+   Memcheck:Cond
+   fun:_dl_relocate_object
+   fun:dl_main
+   fun:_dl_sysdep_start
+   fun:_dl_start
+   obj:/targets/*/lib/ld-2.*.so
+}
+{
+   <DEFINITELY LOST: XGetDefault>
+   Memcheck:Leak
+   fun:realloc
+   obj:/targets/*/usr/lib/libX11.so.*
+   obj:/targets/*/usr/lib/libX11.so.*
+   obj:/targets/*/usr/lib/libX11.so.*
+   fun:_XlcCreateLC
+   fun:_XlcDefaultLoader
+   fun:_XOpenLC
+   fun:_XrmInitParseInfo
+   obj:/targets/*/usr/lib/libX11.so.*
+   fun:XrmGetStringDatabase
+   obj:/targets/*/usr/lib/libX11.so.*
+   fun:XGetDefault
+}
+{
+   <suppresion for the known g_type_init leak>
+   Memcheck:Leak
+   ...
+   fun:g_type_init_with_debug_flags
+   fun:g_type_init
+   ...
+}
+
+{
+   <G_TYPE_VALUE macro seems to leak memory>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   ...
+   fun:g_type_register_static
+   fun:g_boxed_type_register_static
+   fun:g_value_get_type
+   ...
+}
+
+{
+   <G_TYPE_VALUE macro seems to leak memory>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   ...
+   fun:g_type_register_static
+   fun:g_param_type_register_static
+   fun:gst_param_spec_mini_object_get_type
+   ...
+}
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2.*
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   fun:g_type_create_instance
+   fun:gst_mini_object_new
+   fun:gst_buffer_new
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+   obj:/targets/*/usr/lib/libgstbase-0.10*
+   obj:/targets/*/usr/lib/libgstbase-0.10*
+   obj:/targets/*/usr/lib/libgstreamer-0*
+}
+
+
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2*
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   fun:gst_poll_new
+   fun:gst_poll_new_timer
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+   fun:g_type_create_instance
+   obj:/targets/*/usr/lib/libgobject-2*
+   fun:g_object_newv
+   fun:g_object_new_valist
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object
+   fun:openaux
+   fun:_dl_catch_error
+   fun:_dl_map_object_deps
+   fun:dl_open_worker
+   fun:_dl_catch_error
+   fun:_dl_open
+   fun:dlopen_doit
+   fun:_dl_catch_error
+}
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:memalign
+   fun:posix_memalign
+   obj:/targets/*/lib/libglib-2*
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   obj:/targets/*/usr/lib/libgstreamer-0.1*
+   fun:g_value_init
+   fun:gst_value_init_and_copy
+   fun:gst_structure_copy
+   fun:gst_ffmpegcsp_transform_caps
+   obj:/targets/*/usr/lib/libgstbase-0.1*
+   obj:/targets/*/usr/lib/libgstbase-0.1*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/ld-2.10.*
+   ...
+   obj:/targets/*/lib/libc-2.10.*
+   obj:/targets/*/lib/libc-2.10.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/ld-2.10.*
+   ...
+   obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+   obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/ld-2.10.*
+   ...
+   obj:/targets/*/lib/libc-2.10.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/ld-2.10.*
+   ...
+   obj:/targets/*/lib/libdl-2.10.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/libdl-2.10.*
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/libdl-2.10.*
+   fun:dlopen
+   obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+   obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+   obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+   obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+   fun:_ZN15QDBusConnection9systemBusEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.10.*
+   ...
+   fun:gst_plugin_feature_load
+   fun:gst_element_factory_create
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.10.*
+   obj:/targets/*/lib/ld-2.10.*
+   ...
+   fun:gst_plugin_load_file
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   fun:g_strdupv
+   fun:gst_type_find_register
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgsttypefindfunctions.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+   fun:gst_plugin_load_file
+   fun:gst_plugin_load_by_name
+   fun:gst_plugin_feature_load
+   fun:gst_type_find_factory_call_function
+   fun:gst_type_find_helper_get_range_ext
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   ...
+   fun:gst_plugin_load_file
+   fun:gst_plugin_load_by_name
+}
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/lib/ld-2.10.*
+   fun:gst_type_find_factory_call_function
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_pcm_prepare
+   fun:snd_pcm_hw_params
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_dmix_open
+   fun:_snd_pcm_dmix_open
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:_snd_pcm_softvol_open
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_pcm_hwsync
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_start
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_start
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_mmap_writei
+   fun:snd_pcm_writei
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_pcm_hwsync
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_hwsync
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_delay
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   fun:gst_ring_buffer_delay
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_pcm_start
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_dmix_open
+   fun:_snd_pcm_dmix_open
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:_snd_pcm_softvol_open
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:_snd_pcm_plug_open
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_timer_start
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_start
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_start
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_mmap_writei
+   fun:snd_pcm_writei
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_pcm_hwsync
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_hwsync
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_poll_descriptors_revents
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_wait
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   obj:/targets/*/lib/libglib-2.0.so.0.2400.1
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_timer_stop
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_drop
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_drop
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   fun:gst_ring_buffer_pause
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_pcm_hwsync
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_mmap_commit
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_mmap_commit
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_mmap_writei
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_class_ref
+   fun:g_object_newv
+   fun:gst_element_factory_create
+   fun:gst_element_factory_make
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   fun:gst_element_change_state
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   ...
+   fun:gst_element_factory_create
+   fun:gst_element_factory_make
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   ...
+   fun:gst_element_factory_make
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+   fun:gst_element_provide_clock
+}
+
+
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   ioctl(arg)
+   fun:ioctl
+   fun:snd_pcm_hwsync
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_avail_update
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_poll_descriptors_revents
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_wait
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_hook_load
+   fun:snd_config_hook_load_for_all_cards
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_hook_load
+   fun:snd_config_hook_load_for_all_cards
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:snd_config_hook_load
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+   fun:gst_plugin_load_file
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   fun:gst_element_set_state
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   fun:g_io_modules_scan_all_in_directory
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   fun:g_vfs_get_file_for_uri
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:_snd_pcm_empty_open
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_search_definition
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+   fun:gst_plugin_load_file
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:_snd_pcm_softvol_open
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:_snd_pcm_plug_open
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:_snd_pcm_asym_open
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_add_interface_static
+   fun:gst_tag_reader_add_interface_to_type
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_hook_load
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_searcha_hooks
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_search_definition
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+   fun:g_object_newv
+   fun:g_object_new
+   fun:g_io_module_new
+   fun:g_io_modules_scan_all_in_directory
+   obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_rate_open
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_pcm_hw_params
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   fun:gst_ring_buffer_acquire
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_register_static
+   fun:g_boxed_type_register_static
+   fun:gst_tag_list_get_type
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   fun:g_type_class_ref
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+   fun:gst_plugin_load_file
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_hook_load
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_searcha_hooks
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   fun:snd_config_search_definition
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   fun:snd_config_*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   fun:snd_config_searcha_hooks
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   fun:g_desktop_app_info_lookup_get_type
+   obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+   fun:g_once_impl
+   fun:g_vfs_get_default
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   fun:g_input_stream_get_type
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+   obj:/targets/*/usr/lib/libgstbase-0.10.so.0.26.0
+   obj:/targets/*/usr/lib/libgstbase-0.10.so.0.26.0
+   fun:gst_pad_activate_pull
+   fun:gst_pad_activate_pull
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:strdup
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   fun:gst_ring_buffer_open_device
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/lib/ld-2.10.1.so
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   fun:snd_config_update_r
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   semctl(IPC_SET, arg.buf)
+   fun:semctl
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+   ...
+   obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   fun:gst_element_change_state
+}
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   ...
+   fun:g_type_class_ref
+   fun:g_object_new_valist
+   fun:g_object_new
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   ...
+   fun:g_type_class_ref
+   fun:g_object_new_valist
+   fun:g_object_new
+}
+
+
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   fun:gst_plugin_load_file
+   fun:gst_plugin_load_by_name
+   fun:gst_plugin_feature_load
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   obj:/targets/*/lib/libdl-2.10.1.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   ...
+   obj:/targets/*/usr/lib/gio/modules/libgio-playready-vfs.so
+   fun:g_vfs_get_file_for_uri
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/lib/ld-2.10.1.so
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   fun:gst_plugin_load_file
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   obj:/targets/*/lib/libdl-2.10.1.so
+   fun:dlopen
+   fun:g_module_open
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   fun:gst_plugin_load_file
+   fun:gst_plugin_load_by_name
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:g_malloc0
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+   ...
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   obj:/targets/*/lib/ld-2.10.1.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   ...
+   obj:/targets/*/usr/lib/libgstbase-0.10.so.0.26.0
+   fun:gst_pad_get_range
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   ...
+   obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+   fun:g_type_create_instance
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   ...
+   fun:gst_element_factory_create
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   ...
+   fun:g_object_new
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   fun:g_slice_alloc0
+   ...
+   fun:g_object_new
+   fun:gst_element_factory_create
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   fun:gst_plugin_load_by_name
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dl_allocate_tls
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstwavparse.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dl_allocate_tls
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+   ...
+   fun:_ZN24ut_MafwGstRendererWorker19rendererArtTestCaseEv
+   fun:_ZN24ut_MafwGstRendererWorker11qt_metacallEN11QMetaObject4CallEiPPv
+   fun:_ZN11QMetaObject8metacallEP7QObjectNS_4CallEiPPv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_strdup
+   fun:g_module_open
+   fun:gst_plugin_load_file
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   ...
+   fun:g_type_class_ref
+   fun:g_object_new_valist
+}
+
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   ...
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:dbus_malloc
+   ...
+   fun:dbus_pending_call_block
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   ...
+   fun:dbus_connection_send_with_reply
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   ...
+   fun:dbus_connection_send_with_reply
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+   fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+   fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:dbus_malloc
+   ...
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:dbus_malloc
+   ...
+   obj:/targets/*/usr/lib/libdbus-1.so.3.5.1
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:realloc
+   ...
+   obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+   fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   ...
+   fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+   fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   ...
+   fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+   fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:realloc
+   fun:g_realloc
+   obj:/targets/maemo6-i486/usr/lib/libgobject-2.0.so.*
+   obj:/targets/maemo6-i486/usr/lib/libgobject-2.0.so.*
+   fun:g_type_register_static
+   fun:gconf_client_get_type
+   fun:gconf_client_get_default
+   obj:/targets/*/usr/lib/libgq-gconf.so.*
+   ...
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:dbus_malloc0
+   ...
+   fun:_ZN9GConfItem12update_valueEb
+   fun:_ZN9GConfItemC1ERK7QStringP7QObject
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:dbus_realloc
+   ...
+   fun:dbus_message_append_args
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:_ZN15QDBusConnection10sessionBusEv
+   fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_Z7qMallocj
+   ...
+   obj:/targets/maemo6-i486/usr/lib/libdbus-1.so.3.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:_Znwj
+   obj:/targets/*/usr/lib/libQtDBus.so.4.*
+   ...
+   fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+   fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:_Znwj
+   fun:_ZN14QObjectPrivate13addConnectionEiPNS_10ConnectionE
+   ...
+   fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:_Znwj
+   ...
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+   obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   ...
+   fun:_ZN15QDBusConnection10sessionBusEv
+   fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_Z7qMallocj
+   ...
+   fun:_ZN11QMetaObject8metacallEP7QObjectNS_4CallEiPPv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:dbus_realloc
+   ...
+   obj:/targets/*/usr/lib/libdbus-1.so.3.5.1
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_Z7qMallocj
+   ...
+   fun:dbus_connection_set_watch_functions
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:_Znwj
+   ...
+   obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:dbus_realloc
+   ...
+   obj:/targets/*/usr/lib/libdbus-1.so.3.5.1
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:_Znwj
+   ...
+   fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+   fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_Z7qMallocj
+   fun:_ZN9QListData11detach_growEPii
+   ...
+   fun:_ZN16QCoreApplication6notifyEP7QObjectP6QEvent
+   fun:_ZN16QCoreApplication14notifyInternalEP7QObjectP6QEvent
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:dbus_malloc0
+   ...
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+   obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:_Z8qReallocPvj
+   ...
+   obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:_Z8qReallocPvj
+   ...
+   fun:_ZN22QDBusAbstractInterfaceC2ERK7QStringS2_PKcRK15QDBusConnectionP7QObject
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   ...
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_Z7qMallocj
+   ...
+   obj:/targets/*/lib/ld-2.*.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:_Znaj
+   ...
+   obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:_Znaj
+   ...
+   fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   ...
+   fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_Z7qMallocj
+   ...
+   fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:realloc
+   ...
+   fun:dbus_connection_send_with_reply_and_block
+   fun:dbus_bus_register
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:dbus_malloc0
+   ...
+   obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   obj:/targets/maemo6-i486/usr/lib/libfontconfig.so.1.*
+   ...
+   fun:XML_ParseBuffer
+   fun:FcConfigParseAndLoad
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+   fun:main
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   ...
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+   fun:main
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.*.so
+   ...
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+   fun:main
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Cond
+   obj:/targets/*/lib/ld-2.10.1.so
+   ...
+   fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+   fun:_ZN12QApplicationC1ERiPPci
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:realloc
+   ...
+   fun:g_type_register_static
+   ...
+   fun:_ZN9GConfItemC1ERK7QStringP7QObject
+   fun:_ZN20MafwGstRendererDolby10initializeEv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:realloc
+   fun:g_realloc
+   fun:g_realloc_n
+   ...
+   fun:g_type_register_static
+   ...
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2*.so.*
+   obj:/targets/*/usr/lib/libgobject-2*.so.*
+   obj:/targets/*/usr/lib/libgobject-2*.so.*
+   obj:/targets/*/usr/lib/libgobject-2*.so.*
+   obj:/targets/*/usr/lib/libgobject-2*.so.*
+   fun:g_type_add_interface_static
+   ...
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:g_malloc0
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+   fun:g_param_spec_flags
+   obj:/targets/*/usr/lib/libgio-2.*.so.*
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+   fun:g_io_extension_ref_class
+   obj:/targets/*/usr/lib/libgio-2.*.so.*
+   fun:g_once_impl
+   obj:/targets/*/usr/lib/libgio-2.*.so.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   ...
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   fun:g_once_impl
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   ...
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   fun:g_type_class_ref
+   fun:g_object_newv
+   fun:g_object_new
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   fun:g_vfs_get_file_for_path
+   fun:g_file_new_for_path
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   fun:g_type_add_interface_static
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   fun:g_vfs_get_file_for_path
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   fun:g_realloc_n
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   fun:g_vfs_get_file_for_path
+   fun:g_file_new_for_path
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:g_malloc0
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+   fun:g_type_create_instance
+   fun:g_param_spec_internal
+   fun:g_param_spec_int
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+   fun:g_io_extension_ref_class
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   fun:g_realloc_n
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   obj:/targets/*/usr/lib/libgobject-2.0.so.*
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   fun:g_file_get_type
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   obj:/targets/*/usr/lib/libgio-2.0.so.*
+   fun:g_vfs_get_file_for_path
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dl_allocate_tls
+   fun:pthread_create@@GLIBC_2.1
+   obj:/targets/*/usr/lib/libgthread-2.0.so.*
+   fun:g_thread_create_full
+   obj:/targets/*/lib/libglib-2.0.so.*
+   fun:g_thread_pool_push
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+   fun:gst_task_pool_push
+   fun:gst_task_set_state
+   fun:gst_pad_start_task
+   obj:/targets/*/usr/lib/libgstbase-0.10.so.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_register_static
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   fun:g_realloc_n
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   fun:gst_data_queue_get_type
+   fun:gst_data_queue_new_full
+   obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+   obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+   fun:gst_element_get_request_pad
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   fun:g_realloc_n
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_register_static
+   fun:gst_x_overlay_get_type
+   fun:mafw_gst_renderer_worker_apply_xid
+   fun:_sync_bus_handler
+   fun:gst_bus_post
+   fun:_ZN24ut_MafwGstRendererWorker18pauseFrameTestCaseEv
+   fun:_ZN24ut_MafwGstRendererWorker11qt_metacallEN11QMetaObject4CallEiPPv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   fun:g_realloc_n
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_register_static
+   fun:g_enum_register_static
+   obj:/targets/*/usr/lib/libgsttag-0.10.so.*
+   fun:g_once_impl
+   fun:gst_tag_image_type_get_type
+   fun:_ZN24ut_MafwGstRendererWorker19rendererArtTestCaseEv
+   fun:_ZN24ut_MafwGstRendererWorker11qt_metacallEN11QMetaObject4CallEiPPv
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Addr4
+   obj:/targets/*/usr/lib/libqttracker.so.1~6.12.8
+   ...
+   obj:/targets/*/usr/lib/libqttracker.so.1~6.12.8
+   obj:/targets/*/usr/lib/libqttracker.so.1~6.12.8
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_slice_alloc
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_add_interface_static
+   fun:g_type_module_get_type
+   fun:g_io_module_get_type
+   fun:g_io_module_new
+   fun:g_io_modules_scan_all_in_directory
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_class_ref
+   fun:g_type_class_ref
+   fun:g_object_newv
+   fun:g_object_new
+   fun:g_io_module_new
+   fun:g_io_modules_scan_all_in_directory
+   obj:/targets/*/usr/lib/libgio-2.*
+   obj:/targets/*/usr/lib/libgio-2.*
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:realloc
+   fun:g_realloc
+   fun:g_realloc_n
+   obj:/targets/*/usr/lib/libgobject-2.*
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_register_static
+   fun:g_type_register_static_simple
+   obj:/targets/*/usr/lib/libgio-2.*
+   obj:/targets/*/usr/lib/libgio-2.*
+   obj:/targets/*/usr/lib/libgio-2.*
+   fun:g_vfs_get_file_for_path
+   obj:/targets/*/usr/lib/gio/modules/libprdrm-gio-vfs0.so
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:g_malloc
+   fun:g_memdup
+   obj:/targets/*/usr/lib/libgobject-2.*
+   fun:g_type_class_ref
+   fun:g_object_newv
+   fun:g_object_new
+   obj:/targets/*/usr/lib/libgio-2.*
+   obj:/targets/*/usr/lib/libgio-2.*
+   fun:g_vfs_get_file_for_path
+   obj:/targets/*/usr/lib/gio/modules/libprdrm-gio-vfs0.so
+   fun:g_vfs_get_file_for_path
+}
+
+
+
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.cpp
new file mode 100644 (file)
index 0000000..9bf94a4
--- /dev/null
@@ -0,0 +1,209 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include <QTimer>
+
+#include <string.h>
+#include <glib.h>
+#include <gst/gst.h>
+
+#include "MafwGstScreenshot.h"
+#include "ut_GstScreenshot.h"
+
+static gchar *global_failing_gst_element = NULL;
+
+/* START OF STUB DEFINITIONS */
+GstElement *gst_element_factory_make(const gchar *factoryname, const gchar *name)
+{
+
+    GstElementFactory *factory;
+
+    qDebug() << __PRETTY_FUNCTION__ << factoryname;
+
+    if (global_failing_gst_element != NULL &&
+        g_str_equal(factoryname, global_failing_gst_element))
+    {
+        qDebug() << "SIMULATED FAIL OF gst_element_factory_make()";
+        return NULL;
+    }
+    else
+    {
+        factory = gst_element_factory_find(factoryname);
+        return gst_element_factory_create(factory, name);
+    }
+
+}
+/* END OF STUB DEFINITIONS */
+
+void ut_GstScreenshot::testFailures()
+{
+    gint width = 1024;
+    gint height = 1024;
+    gint size = width * height + width * height / 2;
+    GstBuffer *buf = gst_buffer_new_and_alloc(size);
+    QCOMPARE(GST_OBJECT_REFCOUNT_VALUE(buf), 1);
+
+    memset(GST_BUFFER_DATA(buf), 0, size);
+
+    /* no caps set, returns false */
+    QVERIFY(m_screenshot->savePauseFrame(buf,
+                                   "/dev/null") == FALSE);
+
+    buf = gst_buffer_new_and_alloc(size);
+    memset(GST_BUFFER_DATA(buf), 0, size);
+
+    GstCaps *caps;
+    caps = gst_caps_new_simple("video/x-raw-yuv",
+                               "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I','4','2','0'),
+                               "framerate", GST_TYPE_FRACTION, 25, 1,
+                               "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+                               "width", G_TYPE_INT, width,
+                               "height", G_TYPE_INT, height,
+                               NULL);
+    gst_buffer_set_caps(buf, caps);
+
+    /* fakesrc creation fails, returns false */
+    global_failing_gst_element = g_strdup("fakesrc");
+    QVERIFY(m_screenshot->savePauseFrame(buf,
+                                   "/dev/null") == FALSE);
+
+    gst_caps_unref(caps);
+
+    /* TODO: Gst pipeline errors are difficult to test... */
+}
+
+void ut_GstScreenshot::testConvert()
+{
+    gint width = 1024;
+    gint height = 512;
+    gint size = width * height + width * height / 2;
+    GstBuffer *buf = gst_buffer_new_and_alloc(size);
+    memset(GST_BUFFER_DATA(buf), 0, size);
+
+    /* set caps, returns true */
+    GstCaps *caps;
+    caps = gst_caps_new_simple("video/x-raw-yuv",
+                               "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I','4','2','0'),
+                               "framerate", GST_TYPE_FRACTION, 25, 1,
+                               "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+                               "width", G_TYPE_INT, width,
+                               "height", G_TYPE_INT, height,
+                               NULL);
+    gst_buffer_set_caps(buf, caps);
+    QVERIFY(m_screenshot->savePauseFrame(buf,
+                                   "/dev/null") == TRUE);
+
+    QTest::qWait(500);
+    QVERIFY(m_gotScreenshotSignal == TRUE);
+
+    gst_caps_unref(caps);
+}
+
+
+void ut_GstScreenshot::testCancel()
+{
+    gint width = 1024;
+    gint height = 512;
+    gint size = width * height + width * height / 2;
+    GstBuffer *buf = gst_buffer_new_and_alloc(size);
+    memset(GST_BUFFER_DATA(buf), 0, size);
+
+    QFETCH(uint, timeout);
+
+    /* set caps, returns true */
+    GstCaps *caps;
+    caps = gst_caps_new_simple("video/x-raw-yuv",
+                               "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I','4','2','0'),
+                               "framerate", GST_TYPE_FRACTION, 25, 1,
+                               "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+                               "width", G_TYPE_INT, width,
+                               "height", G_TYPE_INT, height,
+                               NULL);
+    gst_buffer_set_caps(buf, caps);
+
+    QVERIFY(m_screenshot->savePauseFrame(buf,
+                                   "/dev/null") == TRUE);
+    QTest::qWait(timeout);
+    if (m_gotScreenshotSignal == false )
+    {
+        m_screenshot->cancelPauseFrame();
+        QVERIFY(m_gotCancelSignal == TRUE);
+    }
+}
+
+void ut_GstScreenshot::testCancel_data()
+{
+    QTest::addColumn<uint>("timeout");
+    QTest::newRow("0 ms") << (uint)0;
+    QTest::newRow("1 ms") << (uint)1;
+    QTest::newRow("5 ms") << (uint)5;
+    QTest::newRow("10 ms") << (uint)10;
+    QTest::newRow("20 ms") << (uint)20;
+    QTest::newRow("35 ms") << (uint)35;
+    QTest::newRow("50 ms") << (uint)50;
+    QTest::newRow("100 ms") << (uint)100;
+}
+
+void ut_GstScreenshot::slotScreenshot(char *location, GError *error)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    Q_UNUSED(location);
+    Q_UNUSED(error);
+    m_gotScreenshotSignal = TRUE;
+}
+
+void ut_GstScreenshot::slotCancelScreenshot()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_gotCancelSignal = TRUE;
+}
+
+void ut_GstScreenshot::init()
+{
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    gst_init(0, 0);
+
+    m_gotScreenshotSignal = FALSE;
+    m_gotCancelSignal = FALSE;
+
+    m_screenshot = new MafwGstScreenshot(this);
+    connect(m_screenshot, SIGNAL(screenshotTaken(char*,GError*)), this, SLOT(slotScreenshot(char*,GError*)));
+    connect(m_screenshot, SIGNAL(screenshotCancelled()), this, SLOT(slotCancelScreenshot()));
+
+    global_failing_gst_element = NULL;
+
+}
+
+void ut_GstScreenshot::cleanup()
+{
+
+    qDebug() << __PRETTY_FUNCTION__;
+    g_free(global_failing_gst_element);
+    
+    while(QCoreApplication::hasPendingEvents())
+    {
+        QCoreApplication::sendPostedEvents();
+        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+        QCoreApplication::processEvents();
+    }
+    delete m_screenshot;
+}
+
+QTEST_MAIN(ut_GstScreenshot)
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.h b/qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.h
new file mode 100644 (file)
index 0000000..b9fca86
--- /dev/null
@@ -0,0 +1,52 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#ifndef UT_GSTSCREENSHOT_H_
+#define UT_GSTSCREENSHOT_H_
+
+#include <QObject>
+#include <QtTest/QtTest>
+
+#include "MafwGstScreenshot.h"
+
+class MafwGstScreenshot;
+
+class ut_GstScreenshot: public QObject
+{
+    Q_OBJECT
+
+private slots: // tests, don't touch the test order
+
+    void testFailures();
+    void testConvert();
+    void testCancel();
+    void testCancel_data();
+
+    void init();
+    void cleanup();
+
+protected slots:
+    void slotScreenshot(char *location, GError *error);
+    void slotCancelScreenshot();
+    
+private: //data
+    MafwGstScreenshot *m_screenshot;
+    bool m_gotCancelSignal;
+    bool m_gotScreenshotSignal;
+};
+
+#endif
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.pro b/qmafw-gst-subtitles-renderer/unittests/ut_GstScreenshot/ut_GstScreenshot.pro
new file mode 100644 (file)
index 0000000..3afb79c
--- /dev/null
@@ -0,0 +1,29 @@
+TEMPLATE        = app
+
+CONFIG -= gui
+CONFIG += console
+
+isEmpty(PREFIX) {
+    PREFIX=/usr
+}
+
+CONFIG          += qt link_pkgconfig release
+CONFIG          += qtestlib
+PKGCONFIG       += glib-2.0 gobject-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10
+
+LIBS            +=  -lgcov
+
+DEPENDPATH      += . ../../inc ../../src
+INCLUDEPATH     += . ../../inc
+
+QMAKE_CXXFLAGS  += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+QMAKE_CFLAGS    += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+
+QMAKE_CLEAN     += *.gcda *.gcno *.gcov ut_GstScreenshot *.vg.xml vgcore.*
+
+HEADERS         += ut_GstScreenshot.h \
+                   MafwGstScreenshot.h
+
+SOURCES         += ut_GstScreenshot.cpp \
+                   MafwGstScreenshot.cpp
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/ContextFWStub.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/ContextFWStub.cpp
new file mode 100644 (file)
index 0000000..61e9da0
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <contextsubscriber/contextproperty.h>
+#include <contextsubscriber/contextproviderinfo.h>
+#include <contextsubscriber/contextpropertyinfo.h>
+#include <sys/creds.h>
+#include <QDebug>
+#include <QDBusConnectionInterface>
+
+ContextProperty *global_video_route_property = 0;
+ContextProperty *global_audio_route_property = 0;
+QString global_audio_route("");
+QString global_video_route("");
+ContextPropertyInfo propertyInfo("key");
+
+ContextProperty::ContextProperty(const QString& key, QObject*)
+{
+    if (key == "/com/nokia/policy/video_route" && global_video_route_property == 0)
+    {
+        global_video_route_property = this;
+    }
+    else if (key == "/com/nokia/policy/audio_route" && global_audio_route_property == 0)
+    {
+        global_audio_route_property = this;
+    }
+}
+
+ContextProperty::~ContextProperty()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    if (this == global_video_route_property)
+    {
+        global_video_route_property = 0;
+    }
+    else if (this == global_audio_route_property)
+    {
+        global_audio_route_property = 0;
+    }
+}
+
+// this non-const function is used to trigger the signal emissions
+void ContextProperty::ignoreCommander()
+{
+    Q_EMIT global_video_route_property->valueChanged();
+    Q_EMIT global_audio_route_property->valueChanged();
+}
+
+QString ContextProperty::key() const
+{
+    if (this == global_video_route_property)
+    {
+        return "/com/nokia/policy/video_route";
+    }
+    else if (this == global_audio_route_property)
+    {
+        return "/com/nokia/policy/audio_route";
+    }
+    else
+    {
+        return  "";
+    }
+}
+
+QVariant ContextProperty::value() const
+{
+    if (this == global_video_route_property)
+    {
+        return QVariant(global_video_route);
+    }
+    else if (this == global_audio_route_property)
+    {
+        return QVariant(global_audio_route);
+    }
+    else
+    {
+        return  QVariant();
+    }
+}
+
+const ContextPropertyInfo* ContextProperty::info() const
+{
+    return &propertyInfo;
+}
+
+ContextPropertyInfo::ContextPropertyInfo(const QString &key, QObject *parent)
+{
+    Q_UNUSED(key);
+    Q_UNUSED(parent);
+}
+
+const QList<ContextProviderInfo> ContextPropertyInfo::providers() const
+{
+    QList<ContextProviderInfo> list;
+    list << ContextProviderInfo("contextkit-dbus", "system:com.nokia.policy.pcfd");
+    return list;
+}
+
+// d-bus stub
+bool QDBusError::isValid() const
+{
+    return false;
+}
+
+QDBusMessage::MessageType QDBusMessage::type() const
+{
+    if( this->member()=="GetConnectionUnixProcessID" )
+    {
+        return QDBusMessage::ReplyMessage;
+    }
+
+    return QDBusMessage::SignalMessage;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/MafwGstRendererDolbyStub.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/MafwGstRendererDolbyStub.cpp
new file mode 100644 (file)
index 0000000..8262b95
--- /dev/null
@@ -0,0 +1,122 @@
+#include "MafwGstRendererDolby.h"
+
+#include <QDebug>
+
+const int DEFAULT_COLOR = 2;
+const int DEFAULT_ROOM_SIZE = 2;
+const int MAX_VALUE = 4;
+
+enum MafwDolbyStates
+{
+    MafwDolbyOff,
+    MafwDolbyOn,
+    MafwDolbyAuto
+};
+
+MafwGstRendererDolby::MafwGstRendererDolby( QObject* parent ):
+        QObject(parent),
+        m_dolbyConfMusic(0),
+        m_dolbyConfMusicRoom(0),
+        m_dolbyConfMusicColor(0),
+        m_dolbyConfVideo(0),
+        m_dolbyConfVideoRoom(0),
+        m_dolbyConfVideoColor(0)
+{
+    qDebug() << Q_FUNC_INFO;
+    m_currentMusicDolbyState = MafwDolbyOff;
+    m_currentMusicDolbyRoom = DEFAULT_ROOM_SIZE;
+    m_currentMusicDolbyColor = DEFAULT_COLOR;
+    m_currentVideoDolbyState = MafwDolbyOff;
+    m_currentVideoDolbyRoom = DEFAULT_ROOM_SIZE;
+    m_currentVideoDolbyColor = DEFAULT_COLOR;
+}
+
+void MafwGstRendererDolby::initialize()
+{
+    qDebug() << Q_FUNC_INFO;
+}
+
+MafwGstRendererDolby::~MafwGstRendererDolby()
+{
+    qDebug() << Q_FUNC_INFO;
+}
+
+bool MafwGstRendererDolby::setMusicDolbyState (uint value)
+{
+}
+
+bool MafwGstRendererDolby::setMusicDolbyRoom (int value)
+{
+    qDebug() << Q_FUNC_INFO;
+    return true;
+}
+
+bool MafwGstRendererDolby::setMusicDolbyColor (int value)
+{
+    qDebug() << Q_FUNC_INFO;
+    return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyState (uint value)
+{
+    qDebug() << Q_FUNC_INFO;
+    return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyRoom (int value)
+{
+    qDebug() << Q_FUNC_INFO;
+    return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyColor (int value)
+{
+    qDebug() << Q_FUNC_INFO;
+    return true;
+}
+
+void MafwGstRendererDolby::valueMusicChanged()
+{
+    qDebug() << Q_FUNC_INFO;
+}
+
+void MafwGstRendererDolby::valueVideoChanged()
+{
+    qDebug() << Q_FUNC_INFO;
+}
+
+uint MafwGstRendererDolby::getMusicDolbyState ()
+{
+    qDebug() << Q_FUNC_INFO;
+    return m_currentMusicDolbyState;
+}
+
+int MafwGstRendererDolby::getMusicDolbyRoom ()
+{
+    qDebug() << Q_FUNC_INFO;
+    return m_currentMusicDolbyRoom;
+}
+
+int MafwGstRendererDolby::getMusicDolbyColor ()
+{
+    qDebug() << Q_FUNC_INFO;
+    return m_currentMusicDolbyColor;
+}
+
+uint MafwGstRendererDolby::getVideoDolbyState ()
+{
+    qDebug() << Q_FUNC_INFO;
+    return m_currentVideoDolbyState;
+}
+
+int MafwGstRendererDolby::getVideoDolbyRoom ()
+{
+    qDebug() << Q_FUNC_INFO;
+    return m_currentVideoDolbyRoom;
+}
+
+int MafwGstRendererDolby::getVideoDolbyColor ()
+{
+    qDebug() << Q_FUNC_INFO;
+    return m_currentVideoDolbyColor;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/MafwMmcMonitorStub.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/MafwMmcMonitorStub.cpp
new file mode 100644 (file)
index 0000000..f34050a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwMmcMonitor.h"
+#include <QDebug>
+
+bool stubMmcMounted = true;
+MafwMmcMonitor* stubMmcMonitor;
+
+const QString MafwMmcMonitor::MMC_URI_PREFIX="file:///home/user/MyDocs";
+
+MafwMmcMonitor::MafwMmcMonitor(QObject* parent) : QObject(parent), m_mounted(false)
+{
+    stubMmcMonitor = this;
+}
+
+MafwMmcMonitor::~MafwMmcMonitor()
+{
+    stubMmcMonitor = 0;
+}
+
+bool MafwMmcMonitor::isMounted()
+{
+    return stubMmcMounted;
+}
+
+void MafwMmcMonitor::preUnmountEvent(const QString &/*state*/)
+{
+    Q_EMIT stubMmcMonitor->preUnmount();
+}
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/QSettingsStub.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/QSettingsStub.cpp
new file mode 100644 (file)
index 0000000..a8e4d06
--- /dev/null
@@ -0,0 +1,32 @@
+#include <QSettings>
+
+QMap<QString, QVariant> globalSettingsMap;
+
+//QSettings stub
+QSettings::QSettings( const QString&, const QString&, QObject* ){}
+//Hope we will never need below ctor stub, because it is used somehow by unit test framework.
+//QSettings::QSettings(QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(QSettings::Format, QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(const QString&, QSettings::Format, QObject*){}
+QSettings::QSettings(QObject*){}
+QSettings::~QSettings(){}
+
+QVariant QSettings::value(const QString& key, const QVariant& defaultValue) const
+{
+    return globalSettingsMap.value(key, defaultValue);
+}
+
+bool QSettings::contains(const QString &key) const
+{
+    return true;
+}
+
+void QSettings::beginGroup(const QString &prefix)
+{
+
+}
+
+void QSettings::endGroup()
+{
+
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/QmSystemStub.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/QmSystemStub.cpp
new file mode 100644 (file)
index 0000000..3b04019
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <qmdisplaystate.h>
+#include <QDebug>
+
+int global_qmsystemstub_setBlankingPauseCalled;
+
+namespace MeeGo {
+    QmDisplayState::QmDisplayState(QObject* parent) : QObject(parent)
+    {
+    }
+
+    QmDisplayState::~QmDisplayState(){}
+
+    bool QmDisplayState::setBlankingPause(void)
+    {
+        global_qmsystemstub_setBlankingPauseCalled++;
+        return true;
+    }
+    bool QmDisplayState::cancelBlankingPause(void)
+    {
+        return true;
+    }
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/Ut_MafwGstRenderer.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/Ut_MafwGstRenderer.cpp
new file mode 100644 (file)
index 0000000..dbbded0
--- /dev/null
@@ -0,0 +1,1662 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "Ut_MafwGstRenderer.h"
+
+#include <QDebug>
+#include <QVariant>
+#include <QDBusMessage>
+#include <MafwContent.h>
+#include <MafwMediaInfo.h>
+#include "MafwGstRendererVolume.h"
+#include "MafwMetadata.h"
+#include "MafwGstRendererPlaylistFileUtility.h"
+#include "MafwStubHelper.h"
+#include "MafwRendererPolicyStub.h"
+#include "mafw-gst-renderer-worker.h"
+#include "MafwMediaInfo.h"
+
+#include "QNetworkStubs.h"
+#include <QtNetwork/QNetworkConfiguration>
+
+#define private public // access private members from unit tests
+#include "MafwGstRenderer.h"
+#include "MafwMmcMonitor.h"
+
+extern void setStubHelper(MafwStubHelper* stubHlp);
+extern void setMafwRendererPolicy(MafwRendererPolicy *policy );
+
+extern GError* global_error;
+extern gint global_position;
+extern int global_qmsystemstub_setBlankingPauseCalled;
+extern ContextProperty *global_video_route_property;
+extern ContextProperty *global_audio_route_property;
+extern QString global_audio_route;
+extern QString global_video_route;
+extern gboolean global_worker_playing;
+extern const gchar* global_worker_uri;
+extern int global_worker_stop_called;
+extern int global_worker_seek_request;
+extern guint global_ready_timeout;
+extern GSList *global_worker_destinations;
+extern NetworkStubHelper networkStub;
+extern configuration *current_worker_conf;
+extern QMap<QString, QVariant> globalSettingsMap;
+
+extern bool stubMmcMounted;
+extern MafwMmcMonitor* stubMmcMonitor;
+extern QStringList stubPlaylistFileUtilityUris;
+
+void Ut_MafwGstRenderer::initTestCase()
+{
+    qRegisterMetaType<MafwError>();
+    qRegisterMetaType<MafwError::Code>();
+    qRegisterMetaType<QVariant>();
+    g_type_init();
+
+    m_stubHelper = new MafwStubHelper;
+    setStubHelper(m_stubHelper);
+    m_rendererPolicy = new MafwRendererPolicyStub();
+    setMafwRendererPolicy(m_rendererPolicy);
+
+    m_metadataCount = 0;
+
+    /* Section to test initialization */
+    MafwGstRenderer *renderer = new MafwGstRenderer("renderer_uuid", "renderer-plugin", "rendere_name");
+    //Basic renderer initialize fails
+    m_stubHelper->expect("initialize", false);
+    QVERIFY(renderer->initialize(0) == false);
+    // Let setDefaultRendererPolicy fail now to get more complete unittesting.
+    // Failure in loading policy is not considered fatal at this point.
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("setDefaultRendererPolicy", false);
+    QVERIFY(renderer->initialize(0) == true);
+    delete renderer;
+    /* Section End */
+
+    m_renderer = new MafwGstRenderer("renderer_uuid", "renderer-plugin", "rendere_name");
+
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("setDefaultRendererPolicy", true);
+    QVERIFY(m_renderer->initialize(0) == true);    
+    QVERIFY(m_renderer->m_worker);
+
+    //redundant initialize call
+    QVERIFY(m_renderer->initialize(0) == true);
+
+    global_qmsystemstub_setBlankingPauseCalled = 0;
+}
+
+void Ut_MafwGstRenderer::testPlayURI()
+{
+    //rendererPlaying signal not emitted there
+    MafwMediaInfo content("");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+
+    m_renderer->doPlay(content);
+}
+
+/**
+ * PlaylistFileUtilityStub gives always two uris to play
+ */
+void Ut_MafwGstRenderer::testPlayPlaylistFile()
+{
+    QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+
+    MafwMediaInfo mediaInfo;
+    QMap<QString, QVariant> testUri;
+    QMap<QString, QVariant> testMimeType;
+    testUri.insert(MAFW_METADATA_KEY_URI, "file:///var/tmp/tunein-station.pls");
+    testMimeType.insert(MAFW_METADATA_KEY_MIME, "audio/x-scpls");
+
+    mediaInfo.setMetaData(testUri);
+    mediaInfo.setMetaData(testMimeType);
+
+    m_renderer->doPlay(mediaInfo);
+    QTest::qWait(10);
+    QCOMPARE(playSpy.count(), 1);
+    QList<QVariant> arguments = playSpy.takeFirst();
+    QCOMPARE(arguments.count(), 1);
+    QCOMPARE(arguments.at(0).toInt(), 1); //MafwRendererPlayingUri::CurrentUri
+
+//Test that next uri is started to play if playing first stops because of an error
+    GError* error = g_error_new_literal(1, 2, "Playlist uri playback error");
+    m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+    QTest::qWait(10);
+    QCOMPARE(playSpy.count(), 0);
+    QVERIFY(global_worker_playing);
+    QCOMPARE(QString(global_worker_uri), QString("testUri2"));
+
+//Test that renderer does not go playing state anymore when all uris is used
+    m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+    QTest::qWait(10);
+    QCOMPARE(playSpy.count(), 0);
+
+    g_error_free(error);
+}
+
+void Ut_MafwGstRenderer::testStop()
+{
+    //@TODO doStop needs to be tested for all the states the renderer can be in.
+    QSignalSpy spy(m_renderer, SIGNAL(rendererStopped()));
+    m_renderer->doStop();
+    QCOMPARE(spy.count(), 1);
+    //Not clear that should signal be emitted when calling doStop at stopped state
+    m_renderer->doStop();
+    m_renderer->doStop();
+}
+
+void Ut_MafwGstRenderer::testPause()
+{
+    m_renderer->doPause();
+}
+
+void Ut_MafwGstRenderer::testResume()
+{
+    m_renderer->doResume();
+}
+
+void Ut_MafwGstRenderer::testSeek()
+{
+    QSignalSpy errorSpy(m_renderer, SIGNAL(rendererError(MafwError)));
+    global_error = g_error_new_literal(1, 2, "The seek error");
+    m_renderer->doSeek(1, MafwRenderer::SeekAbsolute);
+    QCOMPARE(errorSpy.count(), 1);
+
+    global_error = 0;
+    m_renderer->doSeek(100, MafwRenderer::SeekRelative);
+}
+
+void Ut_MafwGstRenderer::testDefaultConfiguration()
+{
+    QVERIFY2(sizeof(configuration) == 64, "You've (or somebody else) most likely changed the configuration struct! Update the unittests also!");
+
+    MafwGstRenderer *rnd = new MafwGstRenderer("tesssssst", "conf-test-plug", "conf-test-rnd");
+    QSettings settings("test-set", QSettings::NativeFormat);
+
+    m_stubHelper->expect("initialize", true);
+
+    rnd->initialize(&settings);
+
+    QCOMPARE(current_worker_conf->asink, "pulsesink");
+    QCOMPARE(current_worker_conf->vsink, "omapxvsink");
+    QCOMPARE(current_worker_conf->buffer_time, 300000LL);
+    QCOMPARE(current_worker_conf->latency_time, 100000LL);
+    QCOMPARE(current_worker_conf->flags, 67);
+
+    QCOMPARE(current_worker_conf->mobile_surround_music.state, 0U);
+    QCOMPARE(current_worker_conf->mobile_surround_music.color, 2);
+    QCOMPARE(current_worker_conf->mobile_surround_music.room, 2);
+    QCOMPARE(current_worker_conf->mobile_surround_video.state, 0U);
+    QCOMPARE(current_worker_conf->mobile_surround_video.color, 2);
+    QCOMPARE(current_worker_conf->mobile_surround_video.room, 2);
+
+    QCOMPARE(current_worker_conf->milliseconds_to_pause_frame, 1000U);
+    QCOMPARE(current_worker_conf->seconds_to_pause_to_ready, 3U);
+    QCOMPARE(current_worker_conf->use_dhmmixer, 1);
+
+    delete rnd;
+
+}
+
+void Ut_MafwGstRenderer::testConfiguration()
+{
+    globalSettingsMap.clear();
+    globalSettingsMap.insert("audio-sink", "no-audio");
+    globalSettingsMap.insert("video-sink", "no-video");
+    globalSettingsMap.insert("flags", 67);
+    globalSettingsMap.insert("use_dhmmixer", false);
+    globalSettingsMap.insert("buffer-time", 313);
+    globalSettingsMap.insert("latency-time", 007);
+
+    globalSettingsMap.insert("pause-frame", 13000);
+    globalSettingsMap.insert("pause-to-ready", 7);
+
+    globalSettingsMap.insert("dhm-music-surround", 6);
+    globalSettingsMap.insert("dhm-music-color", 5);
+    globalSettingsMap.insert("dhm-music-room-size", 4);
+    globalSettingsMap.insert("dhm-video-surround", 3);
+    globalSettingsMap.insert("dhm-video-color", 12);
+    globalSettingsMap.insert("dhm-video-room-size", 1);
+
+    MafwGstRenderer *rnd = new MafwGstRenderer("tesst", "conf-test-plug", "conf-test-rnd");
+    QSettings settings("test-set", QSettings::NativeFormat);
+    m_stubHelper->expect("initialize", true);
+    rnd->initialize(&settings);
+
+    QCOMPARE(current_worker_conf->asink, "no-audio");
+    QCOMPARE(current_worker_conf->vsink, "no-video");
+    QCOMPARE(current_worker_conf->buffer_time, 313LL);
+    QCOMPARE(current_worker_conf->latency_time, 007LL);
+    QCOMPARE(current_worker_conf->flags, 67);
+
+    QCOMPARE(current_worker_conf->mobile_surround_music.state, 6U);
+    QCOMPARE(current_worker_conf->mobile_surround_music.color, 5);
+    QCOMPARE(current_worker_conf->mobile_surround_music.room, 4);
+
+    // for some reason video values are overwritten via gconf in unittests
+    QCOMPARE(current_worker_conf->mobile_surround_video.state, 3U);
+    QCOMPARE(current_worker_conf->mobile_surround_video.color, 12);
+    QCOMPARE(current_worker_conf->mobile_surround_video.room, 1);
+
+    QCOMPARE(current_worker_conf->milliseconds_to_pause_frame, 13000U);
+    QCOMPARE(current_worker_conf->seconds_to_pause_to_ready, 7U);
+    QCOMPARE(current_worker_conf->use_dhmmixer, 0);
+
+    globalSettingsMap.clear();
+
+    delete rnd;
+}
+
+void Ut_MafwGstRenderer::testNextHint()
+{
+    MafwMediaInfo content("");
+    QMap<QString,QList<QVariant> >map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.next_uri";
+    content.setMetaData(map);
+
+    m_renderer->doNextHint(content);
+}
+
+void Ut_MafwGstRenderer::testPosition()
+{
+    QVERIFY(connect(m_renderer, SIGNAL(rendererError(MafwError)), this, SLOT(positionError(MafwError))));
+    //set renderer to playing state first
+    MafwMediaInfo content("");
+    QMap<QString,QList<QVariant> >map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+
+    m_renderer->doPlay(content);
+
+   // Normal case
+   m_position = 0;
+   global_position = 157;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+   QVERIFY2(m_position == 157, "Wrong position");
+
+   //repeated call with same value
+   m_position = 0;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+   QVERIFY2(m_position == 157, "Wrong position");
+
+   // Normal case, maxint position
+   m_position = 0;
+   int maxint = 2147483647;
+   global_position = maxint;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+   QVERIFY2(m_position == (uint)maxint, "Wrong position");
+
+   // Normal case, position to 0
+   global_position = 0;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+   QVERIFY2(m_position == 0, "Wrong position");
+
+   // Errorenuous position case
+   m_position = 0;
+   global_position = -1;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+   QVERIFY2(m_position == 0, "Wrong position");
+   QVERIFY2(m_error.code() == MafwError::RendererError_CannotGetPosition, "Wrong error code");
+
+   //Errorenuous position case, -maxint
+   m_position = 0;
+   global_position = -maxint;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+   QVERIFY2(m_position == 0, "Wrong position");
+
+   //NULL result slot
+   global_position = 1;
+   m_renderer->getPosition(0, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+
+   //Not existing error slot
+   global_position = -1;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+
+   // Stopped case when 0 should be returned
+   m_renderer->doStop();
+   m_position = 0;
+   global_position = -1;
+   m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+   QTest::qWait(10);
+   QVERIFY2(m_position == 0, "Wrong position");
+}
+
+void Ut_MafwGstRenderer::testProperty()
+{
+    QFETCH(QString, name);
+    QFETCH(QVariant, value);
+    bool success = m_renderer->setMafwProperty(name, value);
+    QVERIFY2(success, "Unable to set property");
+
+    m_renderer->mafwProperty(name, this, SLOT(propertyChanged(const QString&, const QVariant&)));
+    QTest::qWait(10);
+
+    //@TODO getter for current-frame-on-pause needs to be implemented
+    if (name == "colorkey")
+    {
+        QCOMPARE(m_value, QVariant(1)); //value comes from worker stub
+
+        //Test unexisting slot case
+        m_renderer->mafwProperty(name, this, SLOT(propertyChanged2(const QString&, const QVariant&)));
+        QTest::qWait(10);
+    }
+    else if (name != "unknown"
+             && name!= "current-frame-on-pause"
+             && name != MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE )
+    {
+        QCOMPARE(m_name, name);
+        QCOMPARE(m_value, value);
+    }
+}
+
+void Ut_MafwGstRenderer::testProperty_data()
+{
+    QTest::addColumn<QString>("name");
+    QTest::addColumn<QVariant>("value");
+
+    QTest::newRow("volume") << "volume" << QVariant(1);
+    QTest::newRow("force-aspect-ratio") << "force-aspect-ratio" << QVariant(false);
+    QTest::newRow("autopaint") << "autopaint" << QVariant(true);
+    QTest::newRow("xid") << "xid" << QVariant(12345);
+    QTest::newRow("current-frame-on-pause") << "current-frame-on-pause" << QVariant(true);
+    QTest::newRow("colorkey") << "colorkey" << QVariant(23456);
+    QTest::newRow("render-rectangle") << "render-rectangle" << QVariant(QString("%1,%2,%3,%4").arg(1).arg(2).arg(3).arg(4));
+    QTest::newRow("unknown property") << "unknown" << QVariant(true);
+}
+
+void Ut_MafwGstRenderer::testPlaybackSpeedProperty()
+{
+    QString propertyName = "playback-speed";
+
+    QSignalSpy propertyChangedSpy(m_renderer, SIGNAL(mafwPropertyChanged(const QString&, const QVariant&)));
+
+    //
+    //Stopped - won't accept the property
+    //
+    m_renderer->setMafwProperty(propertyName, 0);
+    m_renderer->setMafwProperty(propertyName, 1);
+    m_renderer->setMafwProperty(propertyName, -1);
+    QCOMPARE(propertyChangedSpy.size(), 0);
+
+    //
+    //Playing
+    //
+    //then test in playing state
+    MafwMediaInfo content("");
+    QMap<QString,QList<QVariant> >map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+
+    m_renderer->doPlay(content);
+
+    //no change in playback, just expect the signal
+    m_renderer->setMafwProperty(propertyName, 1);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    QList<QVariant> arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(1));
+
+    m_renderer->setMafwProperty(propertyName, 2);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(2));
+
+    m_renderer->setMafwProperty(propertyName, 2);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(2));
+
+    m_renderer->setMafwProperty(propertyName, -1);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(-1));
+
+    m_renderer->setMafwProperty(propertyName, 0.3);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(0.3));
+
+    m_renderer->setMafwProperty(propertyName, 1.3);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(1.3));
+
+    m_renderer->setMafwProperty(propertyName, -0.3);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(-0.3));
+
+    m_renderer->setMafwProperty(propertyName, -1.3);
+    QTest::qWait(20);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(-1.3));
+    //check that mafwProperty() returns the correct value
+    m_value = QVariant(0);
+    QVERIFY(m_renderer->mafwProperty(propertyName, this, SLOT(propertyChanged(const QString&, const QVariant&))));
+    QTest::qWait(20);
+    QCOMPARE(m_value.toFloat(), float(-1.3));
+
+    //TODO what does 0 mean?
+    m_renderer->setMafwProperty(propertyName, 0);
+    QCOMPARE(propertyChangedSpy.size(), 1);
+    arguments = propertyChangedSpy.takeFirst();
+    QCOMPARE(arguments.count(), 2);
+    QCOMPARE(arguments.at(0).toString(), propertyName);
+    //There is a QVariant inside QVariant
+    QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(0));
+
+    //
+    //Paused - won't accept the property
+    //
+    m_renderer->doPause();
+    m_renderer->setMafwProperty(propertyName, 3);
+    //check that mafwProperty() returns the correct value
+    m_value = QVariant(-1); //not same as the last value set in playing state
+    QVERIFY(m_renderer->mafwProperty(propertyName, this, SLOT(propertyChanged(const QString&, const QVariant&))));
+    QTest::qWait(20);
+    QCOMPARE(m_value, QVariant(0)); //the value that was last set in playing state
+
+    //TODO test property value after resume
+
+    //
+    //Stopped - won't accept the property
+    //
+    m_renderer->doStop();
+
+    m_renderer->setMafwProperty(propertyName, 3);
+    //check that mafwProperty() returns the correct value
+    m_value = QVariant(-1); //not same as the last value set in playing state
+    QVERIFY(m_renderer->mafwProperty(propertyName, this, SLOT(propertyChanged(const QString&, const QVariant&))));
+    QTest::qWait(20);
+    QCOMPARE(m_value, QVariant(0)); //the value that was last set in playing state
+
+}
+
+void Ut_MafwGstRenderer::cleanupTestCase()
+{
+    delete m_renderer;
+    g_slist_free(global_worker_destinations);
+
+    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+    while(QCoreApplication::hasPendingEvents())
+    {
+        QCoreApplication::sendPostedEvents();
+        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+        QCoreApplication::processEvents();
+    }
+}
+
+/**
+ * Pointers to callback functions after are set to renderer worker at
+ * MafwGstRenderer::initialize
+ */
+void Ut_MafwGstRenderer::testCallbacks()
+{
+    GValue intValue;
+    GValue uintValue;
+    GValue boolValue;
+    GValue stringValue;
+    GValue uninitValue;
+    GValue objectValue;
+    GValue doubleValue;
+    GValue int64Value;
+
+    memset(&intValue, 0, sizeof(GValue));
+    memset(&uintValue, 0, sizeof(GValue));
+    memset(&boolValue, 0, sizeof(GValue));
+    memset(&stringValue, 0, sizeof(GValue));
+    memset(&uninitValue, 0, sizeof(GValue));
+    memset(&objectValue, 0, sizeof(GValue));
+    memset(&doubleValue, 0, sizeof(GValue));
+    memset(&int64Value, 0, sizeof(GValue));
+
+    g_value_init(&intValue, G_TYPE_INT);
+    g_value_init(&uintValue, G_TYPE_UINT);
+    g_value_init(&boolValue, G_TYPE_BOOLEAN);
+    g_value_init(&stringValue, G_TYPE_STRING);
+    g_value_init(&objectValue, G_TYPE_OBJECT);
+    g_value_init(&doubleValue, G_TYPE_DOUBLE);
+    g_value_init(&int64Value, G_TYPE_INT64);
+
+    g_value_set_int(&intValue, -123);
+    g_value_set_uint(&uintValue, (uint)-1);
+    g_value_set_boolean(&boolValue, TRUE);
+    g_value_set_string(&stringValue, "The test property");
+    g_value_set_double(&doubleValue, 1.01);
+    g_value_set_int64(&int64Value, 1234567890);
+
+//playCallback
+    QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+    m_renderer->m_worker->notify_play_handler(m_renderer->m_worker, m_renderer);
+    QCOMPARE(playSpy.count(), 1);
+
+//pauseCallback
+    QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+    m_renderer->m_worker->notify_pause_handler(m_renderer->m_worker, m_renderer);
+    QCOMPARE(pauseSpy.count(), 1);
+
+//errorCallback
+    QSignalSpy errorSpy(m_renderer, SIGNAL(rendererError(MafwError)));
+    GError* error = g_error_new_literal(1, 2, "The unit test error");
+    GError* error2 = g_error_new_literal(1, -1, "Another unit test error");
+    m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+    m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error2);
+    QCOMPARE(errorSpy.count(), 2);
+    g_error_free(error);
+    g_error_free(error2);
+
+//eosCallback
+    QSignalSpy eosSpy(m_renderer, SIGNAL(rendererEos()));
+    m_renderer->m_worker->notify_eos_handler(m_renderer->m_worker, m_renderer);
+    QTest::qWait(10); //renderer paused will be emitted asynchronously
+    QCOMPARE(eosSpy.count(), 1);
+
+//metadataCallback
+    QSignalSpy metadataSpy(m_renderer, SIGNAL(metadataChanged(const QString&, const QList<QVariant>&)));
+    GValueArray *array = g_value_array_new(0);
+    g_value_array_append(array, &stringValue);
+    g_value_array_append(array, &doubleValue);
+    g_value_array_append(array, &int64Value);
+
+    //unknown metadata key
+    m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, -1, G_TYPE_VALUE_ARRAY, array);
+    //invalid type
+    m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, 1, G_TYPE_VALUE, &stringValue);
+    //valid case
+    m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, 1, G_TYPE_VALUE_ARRAY, array);
+
+    QCOMPARE(metadataSpy.count(), 1);
+    g_value_array_free(array);
+
+//propertyCallback
+    int count = 0;
+    QSignalSpy propertySpy(m_renderer, SIGNAL(mafwPropertyChanged(const QString&, const QVariant&)));
+
+    //auto paint
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_AUTOPAINT, &boolValue);
+    QCOMPARE(propertySpy.count(), ++count);
+
+    //color key
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_COLORKEY, &intValue);
+    QCOMPARE(propertySpy.count(), ++count);
+
+    //xid
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_XID, &uintValue);
+    QCOMPARE(propertySpy.count(), ++count);
+
+    //pause frame
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE, &boolValue);
+    QCOMPARE(propertySpy.count(), ++count);
+
+    //force aspect ratio
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_FORCE_ASPECT_RATIO, &boolValue);
+    QCOMPARE(propertySpy.count(), ++count);
+
+    //playback speed
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_PLAYBACK_SPEED, &doubleValue);
+    QCOMPARE(propertySpy.count(), ++count);
+
+    //unknown property id
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, 6, &uintValue);
+    QCOMPARE(propertySpy.count(), ++count);
+
+    //!G_IS_VALUE
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE, &uninitValue);
+    QCOMPARE(propertySpy.count(), count);
+
+    //unsupported value g_type
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_MUTE, &objectValue);
+    QCOMPARE(propertySpy.count(), count);
+
+    //boolean property with string value, currently there is no check -> emits mafwPropertyChanged( "mute", "The test property" )
+    m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_MUTE, &intValue);
+
+
+//bufferStatusCallback
+    QSignalSpy bufferSpy(m_renderer, SIGNAL(bufferingInfo(float)));
+    m_renderer->m_worker->notify_buffer_status_handler(m_renderer->m_worker, m_renderer, (gdouble)1.001);
+    m_renderer->m_worker->notify_buffer_status_handler(m_renderer->m_worker, m_renderer, (gdouble)-1.001);
+    m_renderer->m_worker->notify_buffer_status_handler(m_renderer->m_worker, m_renderer, (gdouble)1001);
+    QCOMPARE(bufferSpy.count(), 3);
+
+    g_value_unset(&intValue);
+    g_value_unset(&uintValue);
+    g_value_unset(&boolValue);
+    g_value_unset(&stringValue);
+    g_value_unset(&int64Value);
+    g_value_unset(&doubleValue);
+}
+
+void Ut_MafwGstRenderer::testGetCurrentMediaInfo()
+{
+    QFETCH(QString, name);
+    QFETCH(QList<QVariant>, values);
+
+    qDebug() << "values.size():" << values.size();
+
+    MafwMediaInfo content("");
+    MafwMediaInfo mediaInfo;
+    QMap<QString,QList<QVariant> > map;
+    QMap<QString,QList<QVariant> >old_map;
+
+    bool success = false;
+    m_name = name;
+
+    GValueArray *array = g_value_array_new(0);
+
+    if(name == "all")
+    {
+        QList<QVariant> valueList;
+        valueList.append("http://test.play.uri");
+        map[MAFW_METADATA_KEY_URI] = valueList;
+        old_map[MAFW_METADATA_KEY_URI] = valueList;
+        mediaInfo.setMetaData(map);
+        content.setMetaData(old_map);
+
+        GValue geevalue;
+        memset(&geevalue, 0, sizeof(GValue));
+        g_value_init(&geevalue, G_TYPE_STRING);
+        g_value_set_string(&geevalue, "http://test.play.uri");
+        g_value_array_append(array, &geevalue);
+        g_value_unset(&geevalue);
+
+        m_renderer->doPlay(content);
+        m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, 18, G_TYPE_VALUE_ARRAY, array);
+        success = m_renderer->getCurrentMediaInfo(this, SLOT(media_info_result(const MafwMediaInfo& )));
+        QTest::qWait(10);
+
+        if(success)
+        {
+            QCOMPARE(m_media_values.at(0), mediaInfo.firstMetaData(MAFW_METADATA_KEY_URI));
+        }
+        else if(!success)
+        {
+            QVERIFY(success);
+        }
+    }
+    else
+    {
+        //URI must be set
+        QMap<QString, QVariant> onlyURI;
+        onlyURI[MAFW_METADATA_KEY_URI] = "http://2222.222.22";
+        content.setMetaData(onlyURI);
+        m_renderer->doPlay(content);
+
+        map[name] = values;
+        old_map[name] = values;
+        mediaInfo.setMetaData(map);
+        content.setMetaData(old_map);
+        m_metadataCount++;
+
+        Q_FOREACH(QVariant value, values)
+        {
+            GValue geevalue;
+            memset(&geevalue, 0, sizeof(GValue));
+            QString type = value.typeName();
+
+            if(type == "QString")
+            {
+                g_value_init(&geevalue, G_TYPE_STRING);
+                g_value_set_string(&geevalue, value.toByteArray());
+            }
+            else if(type == "int")
+            {
+                g_value_init(&geevalue, G_TYPE_INT);
+                g_value_set_int(&geevalue, value.toInt());
+            }
+            else if(type == "float")
+            {
+                g_value_init(&geevalue, G_TYPE_DOUBLE);
+                g_value_set_double(&geevalue, value.toDouble());
+            }
+            else if(type == "bool")
+            {
+                g_value_init(&geevalue, G_TYPE_BOOLEAN);
+                g_value_set_boolean(&geevalue, value.toBool());
+            }
+
+            g_value_array_append(array, &geevalue);
+            g_value_unset(&geevalue);
+        }
+        qDebug() << "array.size:" << array->n_values;
+        m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, m_metadataCount, G_TYPE_VALUE_ARRAY, array);
+
+        success = m_renderer->getCurrentMediaInfo(this, SLOT(media_info_result(const MafwMediaInfo& )), name);
+        QTest::qWait(10);
+
+        if(success)
+        {
+            //TODO rethink this and do the test properly if more metadata start to have related info attached
+            //Related metadata is returned with paused-thumbnail-uri.
+            if(name == "paused-thumbnail-uri")
+            {
+                values.append(QVariant(QString("http://2222.222.22")));
+                values.append(QVariant(0));
+            }
+            qDebug() << m_media_values;
+            qDebug() << values;
+            QCOMPARE(m_media_values, values);
+        }
+        else if(!success)
+        {
+            QVERIFY(success);
+        }
+    }
+
+    g_value_array_free(array);
+}
+
+void Ut_MafwGstRenderer::testGetCurrentMediaInfo_data()
+{
+    QTest::addColumn<QString>("name");
+    QTest::addColumn<QList<QVariant> >("values");
+
+    QTest::newRow("all") << "all" << QList<QVariant>();
+    QTest::newRow("title") << MAFW_METADATA_KEY_TITLE << ( QList<QVariant>() << QVariant("test-title") );
+    QTest::newRow("artist") << MAFW_METADATA_KEY_ARTIST << ( QList<QVariant>() << QVariant("test-artist") << QVariant("test-artist 2") );
+    QTest::newRow("audio-codec") << MAFW_METADATA_KEY_AUDIO_CODEC << ( QList<QVariant>() << QVariant("test-audio-codec") );
+    QTest::newRow("video-codec") << MAFW_METADATA_KEY_VIDEO_CODEC << ( QList<QVariant>() << QVariant("test-video-codec") );
+    QTest::newRow("bitrate") << MAFW_METADATA_KEY_BITRATE << ( QList<QVariant>() << QVariant(256) );
+    QTest::newRow("encoding") << MAFW_METADATA_KEY_ENCODING << ( QList<QVariant>() << QVariant("test-encoding") );
+    QTest::newRow("album") << MAFW_METADATA_KEY_ALBUM << ( QList<QVariant>() << QVariant("test-album") );
+    QTest::newRow("genre") << MAFW_METADATA_KEY_GENRE << ( QList<QVariant>() << QVariant("test-genre") );
+    QTest::newRow("track") << MAFW_METADATA_KEY_TRACK << ( QList<QVariant>() << QVariant(1) );
+    QTest::newRow("organization") << MAFW_METADATA_KEY_ORGANIZATION << ( QList<QVariant>() << QVariant("test-organization") );
+    QTest::newRow("renderer-art-uri") << MAFW_METADATA_KEY_RENDERER_ART_URI << ( QList<QVariant>() << QVariant("http://test.renderer.art.uri") );
+    QTest::newRow("res-x") << MAFW_METADATA_KEY_RES_X << ( QList<QVariant>() << QVariant(480) );
+    QTest::newRow("res-y") << MAFW_METADATA_KEY_RES_Y << ( QList<QVariant>() << QVariant(640) );
+    QTest::newRow("video-framerate") << MAFW_METADATA_KEY_VIDEO_FRAMERATE << ( QList<QVariant>() << QVariant(float(30/1)) );
+    QTest::newRow("duration") << MAFW_METADATA_KEY_DURATION << ( QList<QVariant>() << QVariant(5) );
+    QTest::newRow("is-seekable") << MAFW_METADATA_KEY_IS_SEEKABLE << ( QList<QVariant>() << QVariant(true) );
+    QTest::newRow("paused-thumbnail-uri") << MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI << ( QList<QVariant>() << QVariant("file:///test.thumbnail.paused.uri") );// << QVariant("http://test.play.uri") << QVariant(666) );
+    QTest::newRow("uri") << MAFW_METADATA_KEY_URI << ( QList<QVariant>() << QVariant("http://test.play.uri") );
+}
+
+void Ut_MafwGstRenderer::testErrorCodeScenarios()
+{
+    m_renderer->m_playingPlaylistFile = false;
+
+    QFETCH(QString, uri);
+    QFETCH(int, workerError);
+    QFETCH(MafwError::Code, emittedError);
+
+    global_worker_uri = g_strdup(uri.toAscii().constData());
+
+    QSignalSpy errorSpy(m_renderer, SIGNAL(rendererError(MafwError)));
+
+    GError* gerror = g_error_new_literal(1, workerError, "Media not found");
+    m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, gerror);
+
+    QCOMPARE(errorSpy.size(), 1);
+
+    QVariantList params = errorSpy.takeFirst();
+    MafwError mafwError = params.at(0).value<MafwError>();
+
+    QCOMPARE(mafwError.code(), MafwError::Code(emittedError));
+
+    g_error_free(gerror);
+}
+
+void Ut_MafwGstRenderer::testErrorCodeScenarios_data()
+{
+    QTest::addColumn<QString>("uri");
+    QTest::addColumn<int>("workerError");
+    QTest::addColumn<MafwError::Code>("emittedError");
+
+    QTest::newRow("Local file not found") << "file:///donotexits.mp3" << int(WORKER_ERROR_MEDIA_NOT_FOUND) << MafwError::RendererError_MediaNotFound;
+    QTest::newRow("Stream could not be connected") << "mms:///donotexits.mp3" << int(WORKER_ERROR_MEDIA_NOT_FOUND) << MafwError::RendererError_URINotAvailable;
+}
+
+void Ut_MafwGstRenderer::testBlankingPreventer()
+{
+    m_renderer->m_worker->blanking__control_handler(m_renderer->m_worker, m_renderer, TRUE );
+    QCOMPARE( global_qmsystemstub_setBlankingPauseCalled, 1 );
+    QTest::qWait( 50*1000 ); // >45 secs
+    QCOMPARE( global_qmsystemstub_setBlankingPauseCalled, 2 );
+    global_qmsystemstub_setBlankingPauseCalled = 0;
+
+    m_renderer->m_worker->blanking__control_handler(m_renderer->m_worker, m_renderer, FALSE );
+    QTest::qWait( 50*1000 ); // >45 secs
+    // no more calls arrived
+    QCOMPARE( global_qmsystemstub_setBlankingPauseCalled, 0 );
+}
+
+void Ut_MafwGstRenderer::testPolicyPropertyHandler()
+{
+    m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, true);
+    QVERIFY(global_ready_timeout == 0);
+
+    m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, false);
+    QCOMPARE(global_ready_timeout, (guint)MAFW_GST_RENDERER_WORKER_READY_TIMEOUT);
+
+    m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, true);
+    QVERIFY(global_ready_timeout == 0);
+
+    m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, false);
+    QCOMPARE(global_ready_timeout, (guint)MAFW_GST_RENDERER_WORKER_READY_TIMEOUT);
+
+}
+
+void Ut_MafwGstRenderer::testMediaRouting()
+{
+
+    QVERIFY(global_audio_route_property);
+    QVERIFY(global_video_route_property);
+
+    global_audio_route = "tvout";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 3);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "tvout";
+    global_video_route = "tvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 2);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "null";
+    global_video_route = "builtin";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 2);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+    global_audio_route = "headset";
+    global_video_route = "kjkjkjfg";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 2);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+
+    MafwMediaInfo content("test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing == TRUE); //should be playing now
+    global_audio_route = "ihf";
+    global_video_route = "builtin";
+    m_renderer->m_audioRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_length(global_worker_destinations) == 2);
+
+    global_audio_route = "earpiece";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 3);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "bthsp";
+    global_video_route = "kjkjkjfg";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 2);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+
+    global_audio_route = "bta2dp";
+    global_video_route = "builtin";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 2);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+    global_audio_route = "lkglklkgh";
+    global_video_route = "bugvfdd";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 1);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+
+    global_audio_route = "fmtx";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 3);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_FM_RADIO)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "ihfandfmtx";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 4);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_FM_RADIO)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "earpieceandtvout";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 3);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "headphone";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 3);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "ihfandheadset";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 4);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "ihfandheadphone";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 4);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "ihfandbthsp";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 4);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "tvoutandbthsp";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 4);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    global_audio_route = "tvoutandbta2dp";
+    global_video_route = "builtinandtvout";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(global_worker_destinations);
+    QVERIFY(g_slist_length(global_worker_destinations) == 4);
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+    // provider dies
+    global_audio_route = "earpiece";
+    global_video_route = "builtin";
+    m_renderer->m_audioRoute->ignoreCommander();
+    m_renderer->m_videoRoute->ignoreCommander();
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+    QList<QVariant> args;
+    args << "name" << "old" << "";
+    QDBusMessage dbusMsg;
+    dbusMsg.setArguments(args);
+    m_renderer->handleContextProviderRemoval(  dbusMsg );
+    QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+}
+
+void Ut_MafwGstRenderer::testStamping()
+{
+    // start playing
+    MafwMediaInfo content("MafwTrackerSource::test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file:///home/user/MyDocs/test.play.uri";
+    content.setMetaData(map);
+
+    m_renderer->doPlay(content);
+
+    QVERIFY( m_renderer->m_playedStamped==false );
+    QTest::qWait(5200);
+    QVERIFY( m_renderer->m_playedStamped==true );
+    m_renderer->doStop();
+
+    //http uri
+    MafwMediaInfo content2("MafwTrackerSource::test_uuid2");
+    QMap<QString,QList<QVariant> > map2;
+    map2[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content2.setMetaData(map2);
+
+    m_renderer->doPlay(content2);
+
+    QVERIFY( m_renderer->m_playedStamped==false );
+    QTest::qWait(5200);
+    QVERIFY( m_renderer->m_playedStamped==false );
+    m_renderer->doStop();
+
+    // play uri case (no uuid)
+    MafwMediaInfo content3;
+    QMap<QString,QList<QVariant> > map3;
+    map3[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file://test.play.uri";
+    content3.setMetaData(map3);
+
+    m_renderer->doPlay(content3);
+
+    QVERIFY( m_renderer->m_playedStamped==false );
+    QTest::qWait(5200);
+    QVERIFY( m_renderer->m_playedStamped==true );
+    m_renderer->doStop();
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWhenPlaying()
+{
+    MafwMediaInfo content("test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing); //should be playing now
+
+    NetworkStubHelper::currentCreatedConfigIsValid = true;
+    QNetworkConfiguration config;
+
+    global_worker_stop_called = 0;
+    networkStub.emitConfigurationChange(config,
+                                        QNetworkConfiguration::Active);
+    QVERIFY(global_worker_playing);
+    QCOMPARE(global_worker_uri, "http://test.play.uri");
+    QCOMPARE(global_worker_stop_called, 1);
+
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file://test.play.uri";
+    content.setMetaData(map);
+
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing); //should be playing now
+
+    //another network config is activated
+    QNetworkConfiguration config2;
+    networkStub.emitConfigurationChange(config2,
+                                        QNetworkConfiguration::Active);
+
+    QVERIFY(global_worker_playing); //should keep playing as URI is file://
+
+    m_renderer->doStop();
+    QVERIFY(!global_worker_playing);
+
+    //checks that activating new network config stops play when streaming
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing);
+
+    QNetworkConfiguration config3;
+    global_worker_stop_called = 0;
+    networkStub.emitConfigurationChange(config3, QNetworkConfiguration::Active);
+    QCOMPARE(global_worker_uri, "http://test.play.uri");
+    QCOMPARE(global_worker_stop_called, 1);
+    QVERIFY(global_worker_playing);
+
+    //checks that deactivating the current configuration stops playback
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing);
+    networkStub.emitConfigurationChange(config3, QNetworkConfiguration::Discovered);
+    QVERIFY(!global_worker_playing);
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWithNoPlaylistFileUtil()
+{
+    delete m_renderer->m_playlistFileUtil;
+    m_renderer->m_playlistFileUtil = 0;
+    testNetworkChangesWhenPlaying();
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWhenPaused()
+{
+    MafwMediaInfo content("test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+
+    QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+    QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+    QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+    QSignalSpy resumeSpy(m_renderer, SIGNAL(rendererResumed()));
+
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing); //should be playing now
+
+    m_renderer->doPause();
+
+    QCOMPARE(playSpy.size(), 1);
+    playSpy.clear();
+    QCOMPARE(pauseSpy.size(), 1);
+    pauseSpy.clear();
+    QVERIFY(!global_worker_playing); //should be playing now
+
+    global_position = 313;
+    QNetworkConfiguration config;
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+
+    QVERIFY(!global_worker_playing);
+    QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+
+    QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Paused);
+    QCOMPARE(m_renderer->m_haltState.m_position, 313);
+    QCOMPARE(m_renderer->m_haltState.m_uri, QString("http://test.play.uri"));
+
+    QCOMPARE(stopSpy.size(), 0);
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 0);
+
+    global_worker_seek_request = 0;
+
+    m_renderer->doResume();
+
+    QCOMPARE(stopSpy.size(), 0);
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 1);
+
+    QVERIFY(global_worker_playing);
+
+    QCOMPARE(QString(global_worker_uri), QString("http://test.play.uri"));
+    QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+    QVERIFY(!m_renderer->m_haltState.isSet());
+
+    QCOMPARE(global_worker_seek_request, 313);
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWhenPausedAndRendererStopped()
+{
+    MafwMediaInfo content("test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+    content.setMetaData(map);
+
+    QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+    QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+    QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing); //should be playing now
+
+    m_renderer->doPause();
+
+    QCOMPARE(playSpy.size(), 1);
+    playSpy.clear();
+    QCOMPARE(pauseSpy.size(), 1);
+    pauseSpy.clear();
+    QVERIFY(!global_worker_playing); //should be playing now
+
+    global_position = 313;
+    QNetworkConfiguration config;
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+
+    m_renderer->doStop();
+    QCOMPARE(stopSpy.size(), 1);
+    QVERIFY(!m_renderer->m_haltState.isSet());
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesToInactiveAndPauseResumeRequested()
+{
+    QFETCH(int, resumeDelay);
+    MafwGstRendererHaltState::DECAY_TIME = 3;
+
+    MafwMediaInfo content("test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.resume-pause.uri";
+    content.setMetaData(map);
+
+    QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+    QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+    QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing); //should be playing now
+
+    QCOMPARE(playSpy.size(), 1);
+    playSpy.clear();
+
+    global_position = 999;
+    QNetworkConfiguration config;
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+    m_renderer->doPause();
+    QCOMPARE(pauseSpy.size(), 1);
+    pauseSpy.clear();
+
+    QVERIFY(m_renderer->m_haltState.isSet());
+    QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Paused);
+    QCOMPARE(m_renderer->m_haltState.m_position, 999);
+    QCOMPARE(m_renderer->m_haltState.m_uri, QString("http://test.resume-pause.uri"));
+
+    global_worker_seek_request = 0;
+
+    QTest::qWait(resumeDelay);
+
+    m_renderer->doResume();
+    QCOMPARE(global_worker_seek_request, 999);
+    QVERIFY(global_worker_playing); //should be playing yeah there's no network but it will try
+    QVERIFY(!m_renderer->m_haltState.isSet());
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesToInactiveAndPauseResumeRequested_data()
+{
+    QTest::addColumn<int>("resumeDelay");
+    QTest::newRow("short delay") << 1000;
+    QTest::newRow("same as decay") << 3000;
+    QTest::newRow("longer than decay") << 5000;
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWithPlaylistURI()
+{
+    QStringList playlistUris = QStringList() << "http://test.uriplaylist.item/1" << "http://test.uriplaylist.item/2";
+    stubPlaylistFileUtilityUris.clear();
+    stubPlaylistFileUtilityUris = playlistUris;
+
+    MafwMediaInfo content("test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.playlist.m3u"; //does not matter
+    map[MAFW_METADATA_KEY_MIME] = QList<QVariant>() << "audio/x-scpls";
+    content.setMetaData(map);
+
+    QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+    QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+    QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+    QSignalSpy resumeSpy(m_renderer, SIGNAL(rendererResumed()));
+
+    m_renderer->doPlay(content);
+
+    //time to parse the playlist
+    QTest::qWait(75);
+
+    QVERIFY(global_worker_playing); //should be playing now
+
+    QCOMPARE(playSpy.size(), 1);
+    playSpy.clear();
+
+    global_position = 007;
+    global_worker_stop_called = 0;
+
+    NetworkStubHelper::currentCreatedConfigIsValid = false;
+    QNetworkConfiguration config;
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+    QVERIFY(!global_worker_playing);
+    QCOMPARE(global_worker_stop_called, 1);
+    QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+
+    QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Playing);
+    QCOMPARE(m_renderer->m_haltState.m_position, 007);
+    QCOMPARE(m_renderer->m_haltState.m_uri, playlistUris.at(0));
+
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(stopSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 0);
+
+    global_worker_seek_request = 0;
+
+    NetworkStubHelper::currentCreatedConfigIsValid = true;
+    QNetworkConfiguration configActive;
+    networkStub.emitConfigurationChange(configActive, QNetworkConfiguration::Active);
+
+    QVERIFY(global_worker_playing);
+    QCOMPARE(global_worker_seek_request, 007);
+
+    QCOMPARE(stopSpy.size(), 0);
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 0);
+
+    QCOMPARE(QString(global_worker_uri), playlistUris.at(0));
+    QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+    QVERIFY(!m_renderer->m_haltState.isSet());
+
+    //Test that next uri is started to play if playing first stops because of an error
+    GError* error = g_error_new_literal(1, 2, "Playlist uri playback error");
+    m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+    QTest::qWait(10);
+
+    QVERIFY(global_worker_playing);
+    QCOMPARE(stopSpy.size(), 0);
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 0);
+
+    QCOMPARE(QString(global_worker_uri), playlistUris.at(1));
+
+    m_renderer->doStop();
+    QVERIFY(!global_worker_playing);
+    QCOMPARE(stopSpy.size(), 1);
+
+    g_error_free(error);
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesHaltStateDecay()
+{
+    MafwGstRendererHaltState::DECAY_TIME = 4;
+
+    MafwMediaInfo content("test_uuid");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.decay.uri";
+    content.setMetaData(map);
+
+    QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+    QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+    QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+    QSignalSpy resumeSpy(m_renderer, SIGNAL(rendererResumed()));
+
+    m_renderer->doPlay(content);
+    QVERIFY(global_worker_playing); //should be playing now
+
+    QCOMPARE(playSpy.size(), 1);
+    playSpy.clear();
+
+    global_position = 313;
+    NetworkStubHelper::currentCreatedConfigIsValid = false;
+    QNetworkConfiguration config;
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+    QVERIFY(!global_worker_playing);
+    QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+
+    QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Playing);
+    QCOMPARE(m_renderer->m_haltState.m_position, 313);
+    QCOMPARE(m_renderer->m_haltState.m_uri, QString("http://test.decay.uri"));
+
+    QCOMPARE(stopSpy.size(), 0);
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 0);
+
+    global_worker_stop_called = 0;
+    QTest::qWait(MafwGstRendererHaltState::DECAY_TIME * 1000 + 1000);
+
+    global_worker_stop_called = 1;
+    QCOMPARE(stopSpy.size(), 1);
+    stopSpy.clear();
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 0);
+
+    QVERIFY(!m_renderer->m_haltState.isSet());
+
+    global_worker_seek_request = 0;
+    global_worker_stop_called = 0;
+    NetworkStubHelper::currentCreatedConfigIsValid = true;
+    QNetworkConfiguration config2;
+    networkStub.emitConfigurationChange(config2, QNetworkConfiguration::Active);
+
+    QCOMPARE(stopSpy.size(), 0);
+    QCOMPARE(pauseSpy.size(), 0);
+    QCOMPARE(playSpy.size(), 0);
+    QCOMPARE(resumeSpy.size(), 0);
+
+    QVERIFY(!global_worker_playing);
+
+    global_worker_stop_called = 0;
+    QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::UnknownUri);
+    QVERIFY(!m_renderer->m_haltState.isSet());
+
+    QCOMPARE(global_worker_seek_request, 0);
+}
+
+void Ut_MafwGstRenderer::testMmc()
+{
+    QVERIFY(!global_worker_playing);
+
+    MafwGstRenderer *rnd = new MafwGstRenderer("renderer_uuid", "renderer-plugin", "rendere_name");
+    m_stubHelper->expect("initialize", true);
+    QVERIFY(rnd->initialize(0) == true);
+
+    // MMC not mounted at first case
+
+    QSignalSpy errorSpy( rnd, SIGNAL( rendererError(const MafwError&) ) );
+    stubMmcMounted = false;
+    MafwMediaInfo content("test_uuid_xyz");
+    QMap<QString,QList<QVariant> > map;
+    map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file:///home/user/MyDocs/rock.mp3";
+    content.setMetaData(map);
+
+    rnd->doPlay(content);
+    QVERIFY(!global_worker_playing);
+    QCOMPARE( errorSpy.size(), 1 );
+    MafwError err=errorSpy[0][0].value<MafwError>();
+    QVERIFY( err.code()==MafwError::RendererError_MmcNotAvailable );
+
+    // MMC unmounted during play
+
+    stubMmcMounted = true;
+    errorSpy.clear();
+
+    rnd->doPlay(content);
+    QVERIFY(global_worker_playing);
+
+    Q_EMIT stubMmcMonitor->preUnmountEvent("pre-unmount");
+    QTest::qWait(100);
+    QVERIFY(!global_worker_playing);
+    QVERIFY( errorSpy.size()==1 );
+
+    // Playlist first not available
+
+    stubPlaylistFileUtilityUris.clear();
+    stubPlaylistFileUtilityUris << "file:///home/user/MyDocs/rock.mp3";
+    stubPlaylistFileUtilityUris << "file:///home/user/MyDocs/rock2.mp3";
+    errorSpy.clear();
+    stubMmcMounted = false;
+
+    MafwMediaInfo mediaInfo;
+    QMap<QString, QVariant> testUri;
+    QMap<QString, QVariant> testMimeType;
+    testUri.insert(MAFW_METADATA_KEY_URI, "file:///var/tmp/tunein-station.pls");
+    testMimeType.insert(MAFW_METADATA_KEY_MIME, "audio/x-scpls");
+    mediaInfo.setMetaData(testUri);
+    mediaInfo.setMetaData(testMimeType);
+
+    rnd->doPlay(mediaInfo);
+    QTest::qWait(10);
+    QVERIFY(!global_worker_playing);
+    QCOMPARE( errorSpy.size(), 1 );
+    err=errorSpy[0][0].value<MafwError>();
+    QVERIFY( err.code()==MafwError::RendererError_MmcNotAvailable );
+
+    // Playlist play first, second not available
+
+    errorSpy.clear();
+    stubMmcMounted = true;
+
+    rnd->doPlay(mediaInfo);
+    QTest::qWait(10);
+    QVERIFY(global_worker_playing);
+
+    stubMmcMounted = false;
+    // cause next
+    GError* error = g_error_new_literal(1, 2, "Playlist uri playback error");
+    m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, rnd, error);
+    errorSpy.clear();
+
+    QTest::qWait(10);
+    QCOMPARE( errorSpy.size(), 1 );
+    err=errorSpy[0][0].value<MafwError>();
+    QVERIFY( err.code()==MafwError::RendererError_MmcNotAvailable );
+    QVERIFY(!global_worker_playing);
+
+    g_error_free(error);
+
+    delete rnd;
+}
+
+void Ut_MafwGstRenderer::play_result(const MafwError& /*error*/, MafwRenderer& /*rndr*/)
+{
+    qDebug() << "Ut_MafwGstRenderer::play_result";
+
+}
+
+void Ut_MafwGstRenderer::positionChanged(uint position)
+{
+    m_position = position;
+}
+
+void Ut_MafwGstRenderer::positionError(const MafwError& error)
+{
+    m_error = error;
+}
+
+void Ut_MafwGstRenderer::propertyChanged(const QString& name, const QVariant& value)
+{
+    m_name = name;
+    m_value = value;
+}
+
+void Ut_MafwGstRenderer::media_info_result(const MafwMediaInfo& mediaInfo)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+    qDebug() << "m_name:" << m_name;
+
+    m_media_values.clear();
+
+    if(m_name == "all")
+    {
+        m_media_values = mediaInfo.metaData(MAFW_METADATA_KEY_URI);
+    }
+    else
+    {
+        m_media_values = mediaInfo.metaData(m_name);
+    }
+
+    qDebug() << "m_media_values.size():" << m_media_values.size();
+    Q_FOREACH(QVariant v, m_media_values)
+    {
+        qDebug() << "value:" << v;
+    }
+}
+
+void gst_init(int *argc, char **argv[])
+{
+    Q_UNUSED(argc);
+    Q_UNUSED(argv);
+}
+
+QTEST_MAIN(Ut_MafwGstRenderer)
+
+//Volume stub
+MafwGstRendererVolume::MafwGstRendererVolume()
+{
+    qDebug() << "Volume stub ctor";
+}
+
+void MafwGstRendererVolume::connectToPulseAudio()
+{
+}
+
+MafwGstRendererVolume::~MafwGstRendererVolume()
+{
+}
+
+uint MafwGstRendererVolume::getVolume()
+{
+    qDebug(__PRETTY_FUNCTION__);
+    return (uint)1;
+}
+
+bool MafwGstRendererVolume::setVolume (uint value)
+{
+    Q_UNUSED(value);
+    return true;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/Ut_MafwGstRenderer.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/Ut_MafwGstRenderer.h
new file mode 100644 (file)
index 0000000..f464304
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERER_H_
+#define UT_MAFWGSTRENDERER_H_
+
+#include <QtTest/QtTest>
+#include <MafwError.h>
+#include <contextsubscriber/contextproperty.h>
+
+class MafwInternalRegistry;
+class MafwGstRenderer;
+class MafwRenderer;
+class MafwStubHelper;
+class MafwRendererPolicyStub;
+class MafwMediaInfo;
+
+Q_DECLARE_METATYPE(QVariant)
+Q_DECLARE_METATYPE(MafwError::Code)
+
+class Ut_MafwGstRenderer: public QObject
+{
+    Q_OBJECT
+
+private Q_SLOTS:
+    void initTestCase();
+    void cleanupTestCase();
+
+    void testPlayURI();
+    void testPlayPlaylistFile();
+    void testStop();
+    void testPause();
+    void testResume();
+    void testSeek();
+    void testErrorCodeScenarios();
+    void testErrorCodeScenarios_data();
+    void testNextHint();
+    void testPosition();
+    void testProperty();
+    void testProperty_data();
+    void testPlaybackSpeedProperty();
+    void testCallbacks();
+    void testDefaultConfiguration();
+    void testConfiguration();
+    void testGetCurrentMediaInfo();
+    void testGetCurrentMediaInfo_data();
+    void testBlankingPreventer();
+    void testPolicyPropertyHandler();
+    void testMediaRouting();
+    void testStamping();
+    void testNetworkChangesWhenPlaying();
+    void testNetworkChangesWithNoPlaylistFileUtil();
+    void testNetworkChangesWhenPaused();
+    void testNetworkChangesWhenPausedAndRendererStopped();
+    void testNetworkChangesToInactiveAndPauseResumeRequested();
+    void testNetworkChangesToInactiveAndPauseResumeRequested_data();
+    void testNetworkChangesHaltStateDecay();
+    void testNetworkChangesWithPlaylistURI();
+    void testMmc();
+
+    /**
+     * @param error The status of the completed request.
+     * @param rndr Reference to instance of MafwRenderer invoked the callback slot
+     */
+    void play_result(const MafwError& error, MafwRenderer& rndr);
+
+    void positionChanged(uint position);
+    void positionError(const MafwError& error);
+    void media_info_result(const MafwMediaInfo& mediaInfo);
+
+protected Q_SLOTS:
+    void propertyChanged(const QString& name, const QVariant& value);
+
+private:
+
+    MafwGstRenderer* m_renderer;
+    MafwStubHelper* m_stubHelper;
+    MafwRendererPolicyStub* m_rendererPolicy;
+    MafwError m_error;
+    uint m_position;
+    QVariant m_value;
+    QString m_name;
+    QList<QVariant> m_media_values;
+    int m_metadataCount;
+    ContextProperty *m_videoRoute;
+};
+
+#endif /*UT_MAFWGSTRENDERER_H_*/
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/ut_MafwGstRenderer.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRenderer/ut_MafwGstRenderer.pro
new file mode 100644 (file)
index 0000000..e5f2342
--- /dev/null
@@ -0,0 +1,63 @@
+TEMPLATE = app
+TARGET = 
+INCLUDEPATH += .
+QT += network
+QT -= gui
+
+CONFIG = console
+
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR \
+               $$UT_COMMONDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG += qtestlib no_keywords
+CONFIG += qt link_pkgconfig debug
+
+PKGCONFIG += qmafw glib-2.0 gobject-2.0
+PKGCONFIG += contextprovider-1.0 x11 gq-gconf gstreamer-tag-0.10 libpulse-mainloop-glib
+PKGCONFIG += qmsystem2 contextsubscriber-1.0
+
+LIBS += -lgcov
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror $$system(pkg-config --cflags-only-I QtSparql)
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += Ut_MafwGstRenderer.h \
+    MafwGstRenderer.h \
+    MafwGstRendererVolume.h \
+    MafwGstRendererDolby.h \
+    MafwBlankingPreventer.h \
+    MafwGstRendererNetworkMonitor.h \
+    mafw-gst-renderer-worker.h \
+    mafw-gst-renderer-utils.h \
+    MafwGstRendererPlaylistFileUtility.h \
+    $$UT_COMMONDIR/MafwStubHelper.h \
+    $$UT_COMMONDIR/MafwRendererPolicyStub.h \
+    $$UT_COMMONDIR/QNetworkStubs.h \
+    /usr/include/qt4/QtNetwork/qnetworkconfigmanager.h \
+    MafwMmcMonitor.h \
+    MafwGstScreenshot.h \
+    MafwGstRendererHaltState.h
+
+SOURCES += QmSystemStub.cpp \
+    QSettingsStub.cpp \
+    Ut_MafwGstRenderer.cpp \
+    MafwGstRenderer.cpp \
+    MafwGstRendererDolbyStub.cpp \
+    MafwBlankingPreventer.cpp \
+    MafwGstRendererNetworkMonitor.cpp \
+    mafw-gst-renderer-utils.c \
+    $$UT_COMMONDIR/MafwStubHelper.cpp \
+    $$UT_COMMONDIR/renderer-worker-stub.c \
+    $$UT_COMMONDIR/MafwBasicRendererStub.cpp \
+    $$UT_COMMONDIR/MafwRendererPolicyStub.cpp \
+    $$UT_COMMONDIR/LibCredsStub.cpp \
+    $$UT_COMMONDIR/MafwPlaylistFileUtilityStub.cpp \
+    ContextFWStub.cpp \
+    $$UT_COMMONDIR/QNetworkStubs.cpp \
+    MafwMmcMonitorStub.cpp \
+    MafwGstScreenshot.cpp \
+    MafwGstRendererHaltState.cpp
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.cpp
new file mode 100644 (file)
index 0000000..1038e43
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include "ut_MafwGstRendererDolby.h"
+
+#include <QDebug>
+#include <QVariant>
+
+#include "MafwGstRendererDolby.h"
+
+void Ut_MafwGstRendererDolby::initTestCase()
+{
+    m_dolby = new MafwGstRendererDolby(this);
+    m_dolby->initialize();
+    delete m_dolby;
+    m_dolby = new MafwGstRendererDolby(this);
+    m_dolby->initialize();
+}
+
+void Ut_MafwGstRendererDolby::cleanupTestCase()
+{
+    delete m_dolby;
+}
+
+void Ut_MafwGstRendererDolby::testDolby()
+{
+    m_dolby->setMusicDolbyState(0);
+    QCOMPARE(m_dolby->getMusicDolbyState(), (uint)0);
+    m_dolby->setMusicDolbyState(1);
+    QCOMPARE(m_dolby->getMusicDolbyState(), (uint)1);
+    m_dolby->setMusicDolbyState(2);
+    QCOMPARE(m_dolby->getMusicDolbyState(), (uint)2);
+    m_dolby->setMusicDolbyState(3);
+    QCOMPARE(m_dolby->getMusicDolbyState(), (uint)0);
+
+    m_dolby->setMusicDolbyRoom(-1);
+    QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)0);
+    m_dolby->setMusicDolbyRoom(0);
+    QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)0);
+    m_dolby->setMusicDolbyRoom(1);
+    QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)1);
+    m_dolby->setMusicDolbyRoom(2);
+    QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)2);
+    m_dolby->setMusicDolbyRoom(3);
+    QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)3);
+    m_dolby->setMusicDolbyRoom(4);
+    QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)4);
+    m_dolby->setMusicDolbyRoom(5);
+    QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)4);
+
+    m_dolby->setMusicDolbyColor(-1);
+    QCOMPARE(m_dolby->getMusicDolbyColor(), (int)0);
+    m_dolby->setMusicDolbyColor(0);
+    QCOMPARE(m_dolby->getMusicDolbyColor(), (int)0);
+    m_dolby->setMusicDolbyColor(1);
+    QCOMPARE(m_dolby->getMusicDolbyColor(), (int)1);
+    m_dolby->setMusicDolbyColor(2);
+    QCOMPARE(m_dolby->getMusicDolbyColor(), (int)2);
+    m_dolby->setMusicDolbyColor(3);
+    QCOMPARE(m_dolby->getMusicDolbyColor(), (int)3);
+    m_dolby->setMusicDolbyColor(4);
+    QCOMPARE(m_dolby->getMusicDolbyColor(), (int)4);
+    m_dolby->setMusicDolbyColor(5);
+    QCOMPARE(m_dolby->getMusicDolbyColor(), (int)4);
+
+    m_dolby->setVideoDolbyState(0);
+    QCOMPARE(m_dolby->getVideoDolbyState(), (uint)0);
+    m_dolby->setVideoDolbyState(1);
+    QCOMPARE(m_dolby->getVideoDolbyState(), (uint)1);
+    m_dolby->setVideoDolbyState(2);
+    QCOMPARE(m_dolby->getVideoDolbyState(), (uint)2);
+    m_dolby->setVideoDolbyState(3);
+    QCOMPARE(m_dolby->getVideoDolbyState(), (uint)0);
+
+    m_dolby->setVideoDolbyRoom(-1);
+    QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)0);
+    m_dolby->setVideoDolbyRoom(0);
+    QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)0);
+    m_dolby->setVideoDolbyRoom(1);
+    QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)1);
+    m_dolby->setVideoDolbyRoom(2);
+    QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)2);
+    m_dolby->setVideoDolbyRoom(3);
+    QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)3);
+    m_dolby->setVideoDolbyRoom(4);
+    QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)4);
+    m_dolby->setVideoDolbyRoom(5);
+    QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)4);
+
+    m_dolby->setVideoDolbyColor(-1);
+    QCOMPARE(m_dolby->getVideoDolbyColor(), (int)0);
+    m_dolby->setVideoDolbyColor(0);
+    QCOMPARE(m_dolby->getVideoDolbyColor(), (int)0);
+    m_dolby->setVideoDolbyColor(1);
+    QCOMPARE(m_dolby->getVideoDolbyColor(), (int)1);
+    m_dolby->setVideoDolbyColor(2);
+    QCOMPARE(m_dolby->getVideoDolbyColor(), (int)2);
+    m_dolby->setVideoDolbyColor(3);
+    QCOMPARE(m_dolby->getVideoDolbyColor(), (int)3);
+    m_dolby->setVideoDolbyColor(4);
+    QCOMPARE(m_dolby->getVideoDolbyColor(), (int)4);
+    m_dolby->setVideoDolbyColor(5);
+    QCOMPARE(m_dolby->getVideoDolbyColor(), (int)4);
+}
+
+QTEST_MAIN(Ut_MafwGstRendererDolby)
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.h
new file mode 100644 (file)
index 0000000..3071730
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERDOLBY_H_
+#define UT_MAFWGSTRENDERERDOLBY_H_
+
+#include <QtTest/QtTest>
+
+class MafwGstRendererDolby;
+
+class Ut_MafwGstRendererDolby: public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void initTestCase();
+    void cleanupTestCase();
+    void testDolby();
+
+private:
+
+    MafwGstRendererDolby* m_dolby;
+};
+
+#endif /*UT_MAFWGSTRENDERERDOLBY_H_*/
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererDolby/ut_MafwGstRendererDolby.pro
new file mode 100644 (file)
index 0000000..b01065c
--- /dev/null
@@ -0,0 +1,33 @@
+TEMPLATE = app
+TARGET = 
+QT -= gui
+CONFIG = console
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+INCLUDEPATH += $$MAFW_GST_INCDIR \
+    $$UT_COMMONDIR
+DEPENDPATH += . \
+    ../../inc \
+    ../../src
+CONFIG += qtestlib \
+    qt \
+    link_pkgconfig \
+    debug
+PKGCONFIG += qmafw \
+    gq-gconf \
+    libpulse-mainloop-glib
+LIBS += -lgcov \
+    -ldbus-qeventloop
+QMAKE_CXXFLAGS += -fprofile-arcs \
+    -ftest-coverage \
+    -O0 -Werror
+QMAKE_CFLAGS += -fprofile-arcs \
+    -ftest-coverage \
+    -O0 -Werror
+
+# Input
+HEADERS += ut_MafwGstRendererDolby.h \
+    MafwGstRendererDolby.h
+SOURCES += ut_MafwGstRendererDolby.cpp \
+    MafwGstRendererDolby.cpp
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.cpp
new file mode 100644 (file)
index 0000000..6686401
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include "ut_MafwGstRendererNetworkMonitor.h"
+#include "MafwGstRendererNetworkMonitor.h"
+#include "QNetworkStubs.h"
+
+#include <QSignalSpy>
+#include <QDebug>
+
+extern NetworkStubHelper networkStub;
+
+void Ut_MafwGstRendererNetworkMonitor::initTestCase()
+{
+
+}
+
+void Ut_MafwGstRendererNetworkMonitor::cleanupTestCase()
+{
+
+}
+
+void Ut_MafwGstRendererNetworkMonitor::testPrepareNetworkChangeSignal()
+{
+    MafwGstRendererNetworkMonitor monitor;
+    QNetworkConfiguration config;
+
+    QSignalSpy networkChangeFinished(&monitor, SIGNAL(networkChangeFinished()));
+
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+
+    QCOMPARE(networkChangeFinished.size(), 1);
+}
+
+void Ut_MafwGstRendererNetworkMonitor::testOfflineSignal()
+{
+    networkStub.currentCreatedConfigIsValid = false;
+    MafwGstRendererNetworkMonitor monitor;
+    networkStub.currentCreatedConfigIsValid = true;
+
+    QSignalSpy prepareNetworkChangeSpy(&monitor, SIGNAL(prepareNetworkChange()));
+
+    QNetworkConfiguration config;
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+    QCOMPARE(prepareNetworkChangeSpy.size(), 1);
+
+    //first activate
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+    //then set it not active
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+    QCOMPARE(prepareNetworkChangeSpy.size(), 2);
+
+}
+
+void Ut_MafwGstRendererNetworkMonitor::testConfigChanges()
+{
+    MafwGstRendererNetworkMonitor monitor;
+    QSignalSpy networkChangeSpy(&monitor, SIGNAL(prepareNetworkChange()));
+    QSignalSpy networkChangeFinished(&monitor, SIGNAL(networkChangeFinished()));
+
+    QNetworkConfiguration config;
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+    QNetworkConfiguration config2;
+    networkStub.emitConfigurationChange(config2, QNetworkConfiguration::Active);
+    networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+    QCOMPARE(networkChangeFinished.size(), 2);
+    QCOMPARE(networkChangeSpy.size(), 0);
+
+    networkStub.emitConfigurationChange(config2, QNetworkConfiguration::Discovered);
+    QCOMPARE(networkChangeSpy.size(), 1);
+}
+
+QTEST_MAIN(Ut_MafwGstRendererNetworkMonitor)
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.h
new file mode 100644 (file)
index 0000000..86dabaa
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERNETWORKMONITOR_H_
+#define UT_MAFWGSTRENDERERNETWORKMONITOR_H_
+
+#include <QtTest/QtTest>
+
+
+class Ut_MafwGstRendererNetworkMonitor: public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void initTestCase();
+    void cleanupTestCase();
+
+    void testPrepareNetworkChangeSignal();
+    void testOfflineSignal();
+    void testConfigChanges();
+};
+
+#endif /*UT_MAFWGSTRENDERERNETWORKMONITOR_H_*/
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererNetworkMonitor/ut_MafwGstRendererNetworkMonitor.pro
new file mode 100644 (file)
index 0000000..4204b01
--- /dev/null
@@ -0,0 +1,28 @@
+TEMPLATE = app
+TARGET = 
+CONFIG = console
+QT -= gui
+
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR $$UT_COMMONDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG          += qtestlib qt link_pkgconfig debug
+PKGCONFIG       += qmafw
+LIBS            += -lgcov
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+
+# Input
+HEADERS += ut_MafwGstRendererNetworkMonitor.h \
+           MafwGstRendererNetworkMonitor.h \
+           /usr/include/qt4/QtNetwork/qnetworkconfigmanager.h \
+           $$UT_COMMONDIR/QNetworkStubs.h
+           
+SOURCES += ut_MafwGstRendererNetworkMonitor.cpp \
+           MafwGstRendererNetworkMonitor.cpp \
+           $$UT_COMMONDIR/QNetworkStubs.cpp
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/Ut_MafwGstRendererPlugin.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/Ut_MafwGstRendererPlugin.cpp
new file mode 100644 (file)
index 0000000..f6d7174
--- /dev/null
@@ -0,0 +1,285 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <MafwInternalRegistry.h>
+#include <MafwRenderer.h>
+#include <QVariant>
+#include <QtTest/QtTest>
+#include <glib-object.h>
+#include <QSettings>
+
+#include "Ut_MafwGstRendererPlugin.h"
+#include "MafwGstRendererPlugin.h"
+#include "MafwGstRenderer.h"
+#include "MafwGstRendererVolume.h"
+#include "MafwGstRendererDolby.h"
+#include "../common/MafwStubHelper.h"
+
+Q_DECLARE_METATYPE(MafwRenderer*)
+
+extern void setStubHelper(MafwStubHelper* stubHlp);
+QMap<QString,QString> renderers;
+int renderer_index = 0;
+
+void Ut_MafwGstRendererPlugin::initTestCase()
+{
+    qRegisterMetaType<MafwRenderer*>();
+    m_stubHelper = new MafwStubHelper;
+    setStubHelper(m_stubHelper);
+
+    m_plugin = new MafwGstRendererPlugin();    
+}
+
+void Ut_MafwGstRendererPlugin::testInProcess()
+{
+    QSignalSpy addedSpy( MafwRegistry::instance(), SIGNAL(rendererAdded(const QString&, const QString&)) );
+    QSignalSpy removedSpy( MafwRegistry::instance(), SIGNAL(rendererRemoved(const QString&, const QString&)) );
+    //MafwBasicRenderer::initialize is called twice:
+    //from its own constructor and from MafwGstRenderer::initialize
+
+    //Basic renderer initialize fails
+    m_stubHelper->expect("initialize", false);
+    m_stubHelper->expect("initialize", false);
+    m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+    QCOMPARE( addedSpy.size(), 0 );
+    addedSpy.clear();
+    removedSpy.clear();
+
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("initialize", true);
+    m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+    QCOMPARE( addedSpy.size(), 1 );
+    QCOMPARE( removedSpy.size(), 0 );
+    QVariantList arguments = addedSpy.takeFirst();
+
+    QString uuid = arguments.at(0).toString();
+    QCOMPARE(uuid, QString("mafw_gst_renderer"));
+    QCOMPARE(arguments.at(1).toString(), QString("QMAFW GStreamer Renderer"));
+
+    MafwRenderer* rnd = MafwRegistry::instance()->renderer(uuid);
+    QVERIFY(rnd != 0);
+    QCOMPARE(rnd->pluginName(), m_plugin->name());
+
+    MafwInternalRegistry::internalInstance()->removeExtension(uuid);
+    QCOMPARE( removedSpy.size(), 1 );
+}
+
+void Ut_MafwGstRendererPlugin::testOutProcess()
+{
+    QCoreApplication::setApplicationName("qmafw-dbus-wrapper");    
+    //TODO empty settings case
+
+    renderers.insert("mafw-gst-renderer", "Mafw-GStreamer-Renderer");
+    renderers.insert("mafw-gst-video-suite-renderer", "Mafw-GStreamer-Renderer-For-Video");
+
+    QSignalSpy addedSpy( MafwRegistry::instance(), SIGNAL(rendererAdded(const QString&, const QString&)) );
+    QSignalSpy removedSpy( MafwRegistry::instance(), SIGNAL(rendererRemoved(const QString&, const QString&)) );
+    //MafwBasicRenderer::initialize is called twice:
+    //from its own constructor and from MafwGstRenderer::initialize
+
+    //Basic renderer initialize fails
+    m_stubHelper->expect("initialize", false);
+    m_stubHelper->expect("initialize", false);
+    m_stubHelper->expect("initialize", false);
+    m_stubHelper->expect("initialize", false);
+    m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+    QCOMPARE( addedSpy.size(), 0 );
+    addedSpy.clear();
+    removedSpy.clear();
+
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("initialize", true);
+    m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+    QCOMPARE( addedSpy.size(), 2 );
+    QCOMPARE( removedSpy.size(), 0 );
+
+    QVariantList arguments = addedSpy.takeFirst();
+    QString uuid1 = arguments.at(0).toString();
+    QString name1 = arguments.at(1).toString();
+    arguments = addedSpy.takeFirst();
+    QString uuid2 = arguments.at(0).toString();
+    QString name2 = arguments.at(1).toString();
+
+    MafwRenderer* rnd1 = MafwRegistry::instance()->renderer(uuid1);
+    QVERIFY(rnd1 != 0);
+    QCOMPARE(rnd1->pluginName(), m_plugin->name());
+    MafwRenderer* rnd2 = MafwRegistry::instance()->renderer(uuid2);
+    QVERIFY(rnd2 != 0);
+    QCOMPARE(rnd2->pluginName(), m_plugin->name());
+
+    QCOMPARE(uuid1, rnd1->uuid());
+    QCOMPARE(name1, rnd1->name());
+    QCOMPARE(uuid2, rnd2->uuid());
+    QCOMPARE(name2, rnd2->name());
+
+    MafwInternalRegistry::internalInstance()->removeExtension(uuid1);
+    MafwInternalRegistry::internalInstance()->removeExtension(uuid2);
+
+    // Test huge amount of renderers
+    renderers.clear();
+    addedSpy.clear();
+    removedSpy.clear();
+    for(int i = 0; i < 100; i++)
+    {
+        QString rndId = QString("rndId %1").arg(i);
+        QString rndName = QString("rndName %1").arg(i);
+        renderers.insert(rndId, rndName);
+        m_stubHelper->expect("initialize", true);
+        m_stubHelper->expect("initialize", true);
+    }
+    m_plugin->initialize( MafwInternalRegistry::internalInstance());
+    QCOMPARE(removedSpy.size(), 0);
+    QCOMPARE(addedSpy.size(), 100);
+
+    // Let's only remove 99 renderers
+    for(int i = 0; i < 99; i++)
+    {
+        QString rndId = QString("rndId %1").arg(i);
+        MafwInternalRegistry::internalInstance()->removeExtension(rndId);
+    }
+    QCOMPARE(removedSpy.size(), 99);
+    // Check that there is still one renderer left
+    MafwRenderer* rnd99 = MafwRegistry::instance()->renderer("rndId 99");
+    QVERIFY(rnd99 != 0);
+    MafwInternalRegistry::internalInstance()->removeExtension("rndId 99");
+
+    addedSpy.clear();
+    removedSpy.clear();
+
+    //Test no renderers
+    renderers.clear();
+    m_plugin->initialize(MafwInternalRegistry::internalInstance());
+    QCOMPARE(addedSpy.size(), 0);
+
+    //Test 2 renderers with same uuid and name
+    renderers.insert("rndId1", "rndName1");
+    renderers.insert("rndId1", "rndName1");
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("initialize", true);
+    m_stubHelper->expect("initialize", false);
+    m_stubHelper->expect("initialize", false);
+    m_plugin->initialize( MafwInternalRegistry::internalInstance());
+    QCOMPARE(addedSpy.size(), 1);
+
+}
+
+void Ut_MafwGstRendererPlugin::cleanupTestCase()
+{
+    delete m_plugin;
+    while(QCoreApplication::hasPendingEvents())
+    {
+        QCoreApplication::sendPostedEvents();
+        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+        QCoreApplication::processEvents();
+    }
+}
+
+void gst_init(int *argc, char **argv[])
+{
+    Q_UNUSED(argc);
+    Q_UNUSED(argv);
+}
+
+QTEST_MAIN(Ut_MafwGstRendererPlugin)
+
+//Volume stub
+MafwGstRendererVolume::MafwGstRendererVolume()
+{
+    qDebug() << "Volume stub ctor";
+}
+
+void MafwGstRendererVolume::connectToPulseAudio()
+{
+}
+
+MafwGstRendererVolume::~MafwGstRendererVolume()
+{
+}
+
+uint MafwGstRendererVolume::getVolume()
+{
+    qDebug(__PRETTY_FUNCTION__);
+    return (uint)1;
+}
+
+bool MafwGstRendererVolume::setVolume (uint value)
+{
+    Q_UNUSED(value);
+    return true;
+}
+
+//QSettings stub
+QSettings::QSettings( const QString&, const QString&, QObject* ){}
+//Hope we will never need below ctor stub, because it is used somehow by unit test framework.
+//QSettings::QSettings(QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(QSettings::Format, QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(const QString&, QSettings::Format, QObject*){}
+QSettings::QSettings(QObject*){}
+QSettings::~QSettings(){}
+
+QVariant QSettings::value(const QString& key, const QVariant& ) const
+{
+    if(renderers.size() == 0)
+    {
+        return QString();
+    }
+    QMap<QString, QString>::const_iterator renderers_iterator = renderers.constBegin();
+    for(int i = 0; i < renderer_index; i++)
+    {
+        renderers_iterator++;
+    }
+
+    if(key == "Id")
+    {
+        return renderers_iterator.key();
+    }
+    else
+    {
+        return renderers_iterator.value();
+    }
+}
+
+int QSettings::beginReadArray(const QString&)
+{
+    return renderers.count();
+}
+
+void QSettings::setArrayIndex(int i)
+{
+    renderer_index = i;
+}
+
+void QSettings::endArray()
+{
+}
+
+void QSettings::beginGroup(const QString &prefix)
+{
+    Q_UNUSED(prefix);
+}
+
+void QSettings::endGroup()
+{
+
+}
+
+bool QSettings::contains(const QString &key) const
+{
+    return true;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/Ut_MafwGstRendererPlugin.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/Ut_MafwGstRendererPlugin.h
new file mode 100644 (file)
index 0000000..3a04214
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERPLUGIN_H
+#define UT_MAFWGSTRENDERERPLUGIN_H
+
+#include <QObject>
+
+class MafwBasicRenderer;
+class MafwGstRendererPlugin;
+class MafwRenderer;
+class MafwStubHelper;
+
+class Ut_MafwGstRendererPlugin: public QObject
+{
+    Q_OBJECT
+    
+private Q_SLOTS: // tests
+
+    void initTestCase();
+    void testInProcess();
+    void testOutProcess();
+    void cleanupTestCase();
+
+private:
+    MafwGstRendererPlugin* m_plugin;
+    MafwStubHelper* m_stubHelper;
+
+};
+
+#endif // UT_MAFWGSTRENDERERPLUGIN_H
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/ut_MafwGstRendererPlugin.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererPlugin/ut_MafwGstRendererPlugin.pro
new file mode 100644 (file)
index 0000000..b736c3e
--- /dev/null
@@ -0,0 +1,57 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Thu Nov 19 11:32:17 2009
+######################################################################
+
+TEMPLATE = app
+QT += network
+QT -=gui
+
+CONFIG = console
+
+TARGET = 
+MAFW_GST_INCDIR = ../../inc
+DEPENDPATH += . $$MAFW_GST_INCDIR ../../src
+INCLUDEPATH += . $$MAFW_GST_INCDIR /usr/include/qmafw
+
+CONFIG          += qtestlib no_keywords
+CONFIG          += qt link_pkgconfig debug
+PKGCONFIG       += qmafw glib-2.0 gobject-2.0 gio-2.0 gio-unix-2.0 usb_moded QtSparql
+PKGCONFIG       += contextprovider-1.0 x11 gstreamer-tag-0.10 gq-gconf libpulse-mainloop-glib qmsystem2 contextsubscriber-1.0
+LIBS            += -lgcov
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += Ut_MafwGstRendererPlugin.h \
+           MafwGstRendererPlugin.h \
+           MafwGstRenderer.h \
+           MafwGstRendererVolume.h \
+           MafwGstRendererDolby.h \
+           MafwBlankingPreventer.h \
+           MafwGstRendererNetworkMonitor.h \
+           MafwGstRendererPlaylistFileUtility.h \
+           MafwMmcMonitor.h \
+          MafwGstScreenshot.h \
+           MafwGstRendererHaltState.h \
+           mafw-gst-renderer-worker.h \
+           mafw-gst-renderer-utils.h \
+           ../common/MafwStubHelper.h \
+           ../common/MafwRendererPolicyStub.h
+           
+SOURCES += Ut_MafwGstRendererPlugin.cpp \
+           MafwGstRendererPlugin.cpp \
+           MafwGstRenderer.cpp \
+           MafwGstRendererDolby.cpp \
+           MafwGstRendererNetworkMonitor.cpp \
+           MafwBlankingPreventer.cpp \
+           MafwMmcMonitor.cpp \
+          MafwGstScreenshot.cpp \
+           MafwGstRendererHaltState.cpp \
+           mafw-gst-renderer-utils.c \
+           ../common/renderer-worker-stub.c \
+           ../common/MafwStubHelper.cpp \
+           ../common/MafwBasicRendererStub.cpp \
+           ../common/MafwRendererPolicyStub.cpp \
+           ../common/MafwPlaylistFileUtilityStub.cpp
+           
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.cpp
new file mode 100644 (file)
index 0000000..8d34d64
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "ut_MafwGstRendererSeeker.h"
+
+#include <QDebug>
+
+Q_DECLARE_METATYPE(QList<qint64>);
+
+extern gint64 g_currentPosition;
+extern gint64 g_duration;
+extern gint64 g_seekRequested;
+extern gint g_seeksCalled;
+
+void Ut_MafwGstRendererSeeker::initTestCase()
+{
+    g_type_init();
+}
+
+void Ut_MafwGstRendererSeeker::cleanupTestCase()
+{
+}
+
+void Ut_MafwGstRendererSeeker::init()
+{
+    m_seeker = mafw_gst_renderer_seeker_new();
+    mafw_gst_renderer_seeker_set_pipeline(m_seeker, (GstElement*)(313));
+}
+
+void Ut_MafwGstRendererSeeker::cleanup()
+{
+    mafw_gst_renderer_seeker_free(m_seeker);
+
+    g_currentPosition = -1;
+    g_duration = -1;
+    g_seekRequested = -1;
+    g_seeksCalled = 0;
+}
+
+
+
+void Ut_MafwGstRendererSeeker::testSeekSuccess()
+{
+    QFETCH(qint64, startPosition);
+    QFETCH(qint64, seekTo);
+    QFETCH(qint64, seekGoesTo);
+    QFETCH(qint64, mediaDuration);
+
+    g_duration = mediaDuration;
+    g_currentPosition = startPosition;
+
+    mafw_gst_renderer_seeker_seek_to(m_seeker, seekTo);
+    QCOMPARE(g_seekRequested, seekTo);
+
+    g_currentPosition = seekGoesTo;
+
+    gint64 newSeekPos = mafw_gst_renderer_seeker_process(m_seeker);
+
+    // only one seek operation should be called when successful
+    QCOMPARE(g_seeksCalled, 1);
+    QCOMPARE(newSeekPos, -1ll);
+}
+
+void Ut_MafwGstRendererSeeker::testSeekSuccess_data()
+{
+    QTest::addColumn<qint64>("startPosition");
+    QTest::addColumn<qint64>("seekTo");
+    QTest::addColumn<qint64>("seekGoesTo");
+    QTest::addColumn<qint64>("mediaDuration");
+
+    QTest::newRow("1") << 0ll << 20ll << 21ll << 30ll;
+    QTest::newRow("1a") << 0ll << 19ll << 21ll << 30ll;
+    QTest::newRow("2") << 5ll << 1ll << 2ll << 10ll;
+    QTest::newRow("3") << 100ll << 150ll << 119ll << 120ll;
+
+    //intentionally messed values
+    QTest::newRow("weird1") << 4ll <<  1ll << 1ll << 2ll;
+    QTest::newRow("weird2") << -13ll << 13ll <<  12ll << 0ll;
+    QTest::newRow("weird2") << 10ll << 5ll << 4ll << 1ll;
+}
+
+
+void Ut_MafwGstRendererSeeker::testSeekFails()
+{
+    QFETCH(qint64, startPosition);
+    QFETCH(qint64, seekTo);
+    QFETCH(QList<qint64>, processedSeekRequests);
+    QFETCH(QList<qint64>, seekGoesTo);
+    QFETCH(qint64, mediaDuration);
+
+    g_duration = mediaDuration;
+    g_currentPosition = startPosition;
+
+    mafw_gst_renderer_seeker_seek_to(m_seeker, seekTo);
+    QCOMPARE(g_seekRequested, seekTo);
+
+    qint64 newSeekPos = 0;
+    int i = 0;
+
+    while( true )
+    {
+        g_currentPosition = seekGoesTo.at(i);
+        newSeekPos = mafw_gst_renderer_seeker_process(m_seeker);
+
+        if( newSeekPos == -1 )
+        {
+            break;
+        }
+
+        QCOMPARE(newSeekPos, processedSeekRequests.at(i));
+        QCOMPARE(g_seekRequested, processedSeekRequests.at(i));
+        ++i;
+    }
+
+    qint64 lastSeekPos = mafw_gst_renderer_seeker_process(m_seeker);
+    QCOMPARE( lastSeekPos, -1ll);
+    QCOMPARE( g_seeksCalled, seekGoesTo.size());
+}
+
+void Ut_MafwGstRendererSeeker::testSeekFails_data()
+{
+    QTest::addColumn<qint64>("startPosition");
+    QTest::addColumn<qint64>("seekTo");
+    QTest::addColumn<QList<qint64> >("processedSeekRequests");
+    QTest::addColumn<QList<qint64> >("seekGoesTo");
+    QTest::addColumn<qint64>("mediaDuration");
+
+    QTest::newRow("Second seek is close enough")
+                       << 0ll // position where seeking start
+                       << 20ll // the seek request
+                       << (QList<qint64>() << 30 ) // list of processed seek request affected by the seekGoesTo list
+                       << (QList<qint64>() << 1 << 31 ) // list of resulting seeks to gst_element_seek()
+                       << 35ll; //affects when seek processing should stop
+
+    QTest::newRow("Fourth seek forward required")
+                       << 5ll // position where seeking start
+                       << 20ll // the seek request
+                       << (QList<qint64>() << 30 << 40 << 50 ) // list of processed seek request affected by the seekGoesTo list
+                       << (QList<qint64>() << 1 << 2 << 6 << 15 ) // list of resulting positions after calling gst_element_seek()
+                       << 70ll; //affects when seek processing should stop
+
+    // backward seeks assume that key_frame seeks will always seek at least to the requested position most likely earlier
+    // such backward seeks that would not reach at least the required position succeed anyway
+    QTest::newRow("backward seek fails")
+                       << 20ll // position where seeking start
+                       << 10ll // the seek request
+                       << (QList<qint64>() ) // list of processed seek request affected by the seekGoesTo list
+                       << (QList<qint64>() << 0 ) // list of resulting positions after calling gst_element_seek()
+                       << 70ll; //affects when seek processing should stop
+
+    QTest::newRow("backward seek fails 2")
+                       << 20ll // position where seeking start
+                       << 10ll // the seek request
+                       << (QList<qint64>() ) // list of processed seek request affected by the seekGoesTo list
+                       << (QList<qint64>() << 15 ) // list of resulting positions after calling gst_element_seek()
+                       << 70ll; //affects when seek processing should stop
+
+    QTest::newRow("Seek over media duration cancelled when processing")
+                       << 5ll // position where seeking start
+                       << 20ll // the seek request
+                       << (QList<qint64>()) // list of processed seek request affected by the seekGoesTo list
+                       << (QList<qint64>() << 5 ) // list of resulting positions after calling gst_element_seek()
+                       << 25ll; //affects when seek processing should stop
+
+    QTest::newRow("Test accuracy, first fails just by an inch")
+                       << 5ll // position where seeking start
+                       << 20ll // the seek request
+                       << (QList<qint64>() << 30) // list of processed seek request affected by the seekGoesTo list
+                       << (QList<qint64>() << 6 << 7) // list of resulting positions after calling gst_element_seek()
+                       << 35ll; //affects when seek processing should stop
+
+    QTest::newRow("Test accuracy 1, first fails just by an inch")
+                       << 5ll // position where seeking start
+                       << 20ll // the seek request
+                       << (QList<qint64>() << 30) // list of processed seek request affected by the seekGoesTo list
+                       << (QList<qint64>() << 6 << 7) // list of resulting seeks to gst_element_seek()
+                       << 35ll; //affects when seek processing should stop
+
+}
+
+
+QTEST_MAIN(Ut_MafwGstRendererSeeker)
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.h
new file mode 100644 (file)
index 0000000..93eb2c8
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERSEEKER_H_
+#define UT_MAFWGSTRENDERERSEEKER_H_
+
+#include <QtTest/QtTest>
+
+#include "mafw-gst-renderer-seeker.h"
+
+class Ut_MafwGstRendererSeeker : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void initTestCase();
+    void cleanupTestCase();
+    void init();
+    void cleanup();
+
+    void testSeekSuccess();
+    void testSeekSuccess_data();
+    void testSeekFails();
+    void testSeekFails_data();
+
+
+private:
+    MafwGstRendererSeeker *m_seeker;
+};
+
+#endif /*UT_MAFWGSTRENDERERSEEKER_H_*/
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker.pro
new file mode 100644 (file)
index 0000000..f56967a
--- /dev/null
@@ -0,0 +1,28 @@
+TEMPLATE = app
+QT -= gui
+CONFIG = console
+
+isEmpty(PREFIX) {
+    PREFIX=/usr
+}
+
+CONFIG          += qt link_pkgconfig debug
+CONFIG          += qtestlib
+PKGCONFIG       += glib-2.0 gobject-2.0
+
+LIBS += -lgcov
+
+DEPENDPATH      += . ../../src ../../inc
+INCLUDEPATH     += . ../../inc $$system(pkg-config --variable=includedir gstreamer-0.10)
+
+QMAKE_CXXFLAGS  += -fprofile-arcs -ftest-coverage -Wall -Werror -g $$system(pkg-config --cflags gstreamer-0.10)
+QMAKE_CFLAGS    += -fprofile-arcs -ftest-coverage -Wall -Werror -g $$system(pkg-config --cflags gstreamer-0.10)
+
+QMAKE_CLEAN     += *.gcda *.gcno *.gcov ut_MafwGstRendererSeeker *.vg.xml vgcore.*
+
+HEADERS         += mafw-gst-renderer-seeker.h \
+                   ut_MafwGstRendererSeeker.h
+
+SOURCES         += mafw-gst-renderer-seeker.c \
+                   ut_MafwGstRendererSeeker_stubs.c \
+                   ut_MafwGstRendererSeeker.cpp
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker_stubs.c b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererSeeker/ut_MafwGstRendererSeeker_stubs.c
new file mode 100644 (file)
index 0000000..04d3cde
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <glib.h>
+
+#include <gst/gstelement.h>
+
+gint64 g_currentPosition;
+gint64 g_duration;
+gint64 g_seekRequested;
+gint g_seeksCalled;
+
+gboolean gst_element_query_position(GstElement *element,
+                                    GstFormat *format,
+                                    gint64 *value)
+{
+    *value = g_currentPosition * GST_SECOND;
+    return TRUE;
+}
+
+gboolean gst_element_query_duration(GstElement *element,
+                                    GstFormat *format,
+                                    gint64 *value)
+{
+    *value = g_duration * GST_SECOND;
+    return TRUE;
+}
+
+gboolean gst_element_seek(GstElement *element,
+                          gdouble rate,
+                          GstFormat format,
+                          GstSeekFlags flags,
+                          GstSeekType cur_type,
+                          gint64 cur,
+                          GstSeekType stop_type,
+                          gint64 stop)
+{
+    g_seekRequested = cur / GST_SECOND;
+    ++g_seeksCalled;
+    return TRUE;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/MafwVolumeStubs.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/MafwVolumeStubs.cpp
new file mode 100644 (file)
index 0000000..6715ea9
--- /dev/null
@@ -0,0 +1,271 @@
+#include <QDebug>
+#include <QVariant>
+#include <dbus/dbus.h>
+#include <dbusconnectioneventloop.h>
+#include "MafwStubHelper.h"
+
+char obj_path[] = "/org/pulseaudio/stream_restore1/entry7";
+
+MafwStubHelper* m_stubHelper = 0;
+void* m_user_data;
+DBusHandleMessageFunction m_signalCb;
+DBusPendingCallNotifyFunction m_restoreObjectCb = 0;
+DBusPendingCallNotifyFunction m_volumeCb = 0;
+DBusMessage* m_getVolumeMethodCall = 0;
+DBusMessage* m_setVolumeMethod = 0;
+
+QMap<uint, uint> m_volumes;
+
+void setStubHelper(MafwStubHelper* stubHlp)
+{
+    m_stubHelper = stubHlp;
+}
+
+dbus_bool_t dbus_error_is_set(const DBusError* error)
+{
+    Q_UNUSED(error);
+    return m_stubHelper->getReturn("dbus_error_is_set").toBool();
+}
+
+struct DBusConnection
+{
+  int aField; 
+};
+
+DBusConnection*        dbus_connection_open(const char *address, DBusError *error)
+{
+    DBusConnection* conn = 0;
+
+    if (m_stubHelper->getReturn("dbus_connection_open").toBool())
+    {
+        conn = static_cast<DBusConnection*>( malloc(sizeof(DBusConnection)) );
+    }
+    Q_UNUSED(address);
+    Q_UNUSED(error);
+    return conn;
+}
+
+void dbus_connection_unref(DBusConnection* conn)
+{
+    if (conn)
+    {
+        free(conn);
+    }
+}
+
+bool DBUSConnectionEventLoop::addConnection(DBusConnection* conn)
+{
+    Q_UNUSED(conn);
+
+    return m_stubHelper->getReturn("addConnection").toBool();
+}
+
+void DBUSConnectionEventLoop::removeConnection(DBusConnection* conn)
+{
+    Q_UNUSED(conn);
+
+    m_stubHelper->getReturn("removeConnection");
+}
+
+dbus_bool_t dbus_connection_add_filter(DBusConnection* connection,
+                                       DBusHandleMessageFunction function,
+                                       void* user_data,
+                                       DBusFreeFunction free_data_function)
+{
+    Q_UNUSED(connection);
+    Q_UNUSED(free_data_function);
+    m_signalCb = function;
+    m_user_data = user_data;
+    return true;
+}
+
+void dbus_pending_call_cancel(DBusPendingCall* pending)
+{
+    Q_UNUSED(pending);
+}
+
+dbus_bool_t dbus_set_error_from_message(DBusError* error, DBusMessage* message)
+{
+    Q_UNUSED(error);
+    Q_UNUSED(message);
+    return m_stubHelper->getReturn("dbus_set_error_from_message").toBool();
+}
+
+void signalVolumeUpdated(uint channel, uint value)
+{
+    DBusMessage* message = dbus_message_new_signal(obj_path, "org.PulseAudio.Ext.StreamRestore1.RestoreEntry", "VolumeUpdated");
+
+    DBusMessageIter argument_iterator, variant_iterator, struct_iterator;
+    dbus_message_iter_init_append (message, &argument_iterator);
+    dbus_message_iter_open_container (&argument_iterator,
+                                      DBUS_TYPE_VARIANT,
+                                      "(uu)",
+                                      &variant_iterator);
+    dbus_message_iter_open_container (&variant_iterator,
+                                      DBUS_TYPE_STRUCT,
+                                      NULL,
+                                      &struct_iterator);
+
+    dbus_message_iter_append_basic (&struct_iterator, DBUS_TYPE_UINT32, &channel);
+    dbus_message_iter_append_basic (&struct_iterator, DBUS_TYPE_UINT32, &value);
+
+    dbus_message_iter_close_container (&variant_iterator, &struct_iterator);
+    dbus_message_iter_close_container (&argument_iterator, &variant_iterator);
+
+    DBusConnection* conn = 0;
+    (*m_signalCb)(conn, message, m_user_data);
+    dbus_message_unref(message);
+}
+
+struct DBusPendingCall
+{
+    uint a;
+};
+
+dbus_bool_t dbus_connection_send_with_reply(DBusConnection* connection,
+                                            DBusMessage* message,
+                                            DBusPendingCall ** pending_return,
+                                            int timeout_milliseconds)
+{
+    DBusPendingCall pending;
+    *pending_return = &pending;
+    Q_UNUSED(connection);
+    m_getVolumeMethodCall = message;
+    Q_UNUSED(pending_return);
+    Q_UNUSED(timeout_milliseconds);
+    return true;
+}
+
+// Saves callback function pointer. Assumes that first call gives callback for
+// GetEntryByName and the second one gives callback for Get Volume
+dbus_bool_t dbus_pending_call_set_notify( DBusPendingCall* pending,
+                                          DBusPendingCallNotifyFunction function,
+                                          void* user_data,
+                                          DBusFreeFunction free_user_data)
+{
+    if (!m_restoreObjectCb)
+    {
+        m_restoreObjectCb = function;
+    }
+    else
+    {
+        m_volumeCb = function;
+    }
+
+    Q_UNUSED(pending);
+    Q_UNUSED(user_data);
+    Q_UNUSED(free_user_data);
+    return true;
+}
+
+void giveRestoreEntryReply()
+{
+    DBusPendingCall pending;
+    (*m_restoreObjectCb) (&pending, m_user_data);
+}
+
+void giveVolumeReply(QMap<uint, uint> volumes)
+{
+    DBusPendingCall pending;
+    m_volumes = volumes;
+    (*m_volumeCb) (&pending, m_user_data);
+}
+
+DBusMessage* dbus_pending_call_steal_reply(DBusPendingCall* pending)
+{
+    Q_UNUSED(pending);
+    bool replyForGetVolume = dbus_message_has_member (m_getVolumeMethodCall, "Get");
+    DBusMessage* message = dbus_message_new_method_return(m_getVolumeMethodCall);
+
+    qDebug() << "replyForGetVolume= " << replyForGetVolume;
+    qDebug() << "m_volumes.count()= " << m_volumes.count();
+    if (replyForGetVolume)
+    {
+        qDebug() << "Jee";
+        DBusMessageIter argument_iterator, variant_iterator, array_iterator;
+        dbus_message_iter_init_append (message, &argument_iterator);
+        dbus_message_iter_open_container (&argument_iterator,
+                                          DBUS_TYPE_VARIANT,
+                                          "a(uu)",
+                                          &variant_iterator);
+        dbus_message_iter_open_container (&variant_iterator,
+                                          DBUS_TYPE_ARRAY,
+                                          "(uu)",
+                                          &array_iterator);
+        if (m_volumes.isEmpty())
+        {
+            qDebug() << "Stub is giving an invalid reply";
+        }
+        else
+        {
+            QMapIterator<uint, uint> i(m_volumes);
+            i.toBack();
+            while (i.hasPrevious())
+            {
+                DBusMessageIter iterator;
+                dbus_message_iter_open_container (&array_iterator,
+                                                  DBUS_TYPE_STRUCT,
+                                                  NULL,
+                                                  &iterator);
+                i.previous();
+                dbus_message_iter_append_basic (&iterator, DBUS_TYPE_UINT32, &i.key());
+                dbus_message_iter_append_basic (&iterator, DBUS_TYPE_UINT32, &i.value());
+                dbus_message_iter_close_container (&array_iterator, &iterator);
+            }
+        }
+        dbus_message_iter_close_container (&variant_iterator, &array_iterator);
+        dbus_message_iter_close_container (&argument_iterator, &variant_iterator);
+    }
+    return message;
+}
+
+dbus_uint32_t dbus_message_get_serial(DBusMessage* message)
+{
+    Q_UNUSED(message);
+    return 1;
+}
+
+dbus_bool_t dbus_message_get_args (DBusMessage* message,
+                                   DBusError* error,
+                                   int first_arg_type,
+                                   ...)
+{    
+    qDebug() << "dbus_message_get_args";
+    va_list var_args;
+    va_start (var_args, first_arg_type);
+
+    while (first_arg_type != DBUS_TYPE_INVALID)
+    {        
+        if (first_arg_type == DBUS_TYPE_OBJECT_PATH)
+        {
+            char** str_p;
+            str_p = va_arg (var_args, char**);
+            *str_p = obj_path;
+        }
+        first_arg_type = va_arg(var_args, int);
+    }
+    va_end(var_args);
+    Q_UNUSED(error);
+    Q_UNUSED(message);
+    return true;
+}
+
+dbus_bool_t dbus_connection_send( DBusConnection* connection,
+                                  DBusMessage* message,
+                                  dbus_uint32_t* serial)
+{
+    Q_UNUSED(connection);
+    Q_UNUSED(serial);
+
+    if (dbus_message_has_member (m_getVolumeMethodCall, "Set"))
+    {
+        m_setVolumeMethod = message;
+    }
+
+    return true;
+}
+
+void dbus_connection_flush( DBusConnection* connection)
+{
+    Q_UNUSED(connection);
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.cpp
new file mode 100644 (file)
index 0000000..1558361
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include "ut_MafwGstRendererVolume.h"
+
+#include <QDebug>
+#include <QVariant>
+#include <dbus/dbus.h>
+
+#include "MafwGstRendererVolume.h"
+#include "MafwStubHelper.h"
+
+extern void setStubHelper(MafwStubHelper* stubHlp);
+extern void signalVolumeUpdated(uint channel, uint value);
+extern void giveRestoreEntryReply();
+extern void giveVolumeReply(QMap<uint, uint> volumes);
+extern DBusMessage* m_setVolumeMethod;
+
+void Ut_MafwGstRendererVolume::initTestCase()
+{
+    m_stubHelper = new MafwStubHelper;
+    setStubHelper(m_stubHelper);
+
+    //Tests the case where first pulseaudio connect fails and
+    //DBUSConnectionEventLoop::addConnection fails.
+    m_stubHelper->expect("dbus_connection_open", false);
+    m_stubHelper->expect("dbus_error_is_set", true);
+    m_volume = new MafwGstRendererVolume();
+    QVERIFY(m_stubHelper->allCallsConsumed());
+    //Wait that connecting to pulseaudio is retried
+
+    m_stubHelper->expect("dbus_connection_open", true);
+    m_stubHelper->expect("dbus_error_is_set", false);
+    m_stubHelper->expect("addConnection", false);
+    QTest::qWait(3000);
+    QVERIFY(m_stubHelper->allCallsConsumed());
+
+    delete m_volume;
+    //Tests the successfull case
+    m_stubHelper->expect("dbus_connection_open", true);
+    m_stubHelper->expect("dbus_error_is_set", false);
+    m_stubHelper->expect("addConnection", true);
+    m_volume = new MafwGstRendererVolume();
+    QVERIFY(m_stubHelper->allCallsConsumed());
+}
+
+void Ut_MafwGstRendererVolume::cleanupTestCase()
+{
+    m_stubHelper->expect("removeConnection", false);
+    delete m_volume;
+    QVERIFY(m_stubHelper->allCallsConsumed());
+    delete m_stubHelper;
+}
+
+void Ut_MafwGstRendererVolume::testVolumeReply()
+{
+    QMap<uint, uint> map;
+//Error reply for "GetEntryByName"
+    m_stubHelper->expect("dbus_set_error_from_message", true);
+    
+    //Pulseaudio reconnect is done
+    m_stubHelper->expect("removeConnection", false);
+    m_stubHelper->expect("dbus_connection_open", true);
+    m_stubHelper->expect("dbus_error_is_set", false);
+    m_stubHelper->expect("addConnection", true);
+    giveRestoreEntryReply();    
+    QTest::qWait(500);
+    QVERIFY(m_stubHelper->allCallsConsumed());    
+    QCOMPARE(m_volume->getVolume(), (uint)0);
+//Error reply for "Get Volume"
+    m_stubHelper->expect("dbus_set_error_from_message", false);
+    m_stubHelper->expect("dbus_set_error_from_message", true);
+    giveRestoreEntryReply();
+    giveVolumeReply(map);
+    QVERIFY(m_stubHelper->allCallsConsumed());
+    QCOMPARE(m_volume->getVolume(), (uint)0);
+//Invalid reply for "Get Volume"
+    m_stubHelper->expect("dbus_set_error_from_message", false);
+    m_stubHelper->expect("dbus_set_error_from_message", false);
+    giveRestoreEntryReply();
+    giveVolumeReply(map);
+    QVERIFY(m_stubHelper->allCallsConsumed());
+    QCOMPARE(m_volume->getVolume(), (uint)0);
+
+//Maximum value
+    giveRestoreEntryReply();
+    map[0] = 0x10000;
+    giveVolumeReply(map);
+    QCOMPARE(m_volume->getVolume(), (uint)100);
+//Maximum value-1
+    giveRestoreEntryReply();
+    map[0] = 0x10000;
+    giveVolumeReply(map);
+    QCOMPARE(m_volume->getVolume(), (uint)100);
+//Value above range
+    giveRestoreEntryReply();
+    map[0] = 0x10001;
+    giveVolumeReply(map);
+    QCOMPARE(m_volume->getVolume(), (uint)100);
+//Huge value
+    map[0] = 0xFF000;
+    giveRestoreEntryReply();
+    giveVolumeReply(map);
+    QCOMPARE(m_volume->getVolume(), (uint)100);
+//Zero
+    map[0] = 0;
+    giveRestoreEntryReply();
+    giveVolumeReply(map);
+    QCOMPARE(m_volume->getVolume(), (uint)0);
+//Many channels, containing mono channel
+    map[0] = 0x10000/2;
+    map[1] = 20;
+    map[2] = 30;
+    map[3] = 40;
+    giveRestoreEntryReply();
+    giveVolumeReply(map);
+    QCOMPARE(m_volume->getVolume(), (uint)50);
+//Many channels, without mono channel
+    map.remove(0);
+    map[1] = 0x10000/3;
+    map[2] = 0x10000/4;
+    map[3] = 0x10000/5;
+    giveRestoreEntryReply();
+    giveVolumeReply(map);
+    QCOMPARE(m_volume->getVolume(), (uint)(100/3));
+}
+
+void Ut_MafwGstRendererVolume::testSignal()
+{    
+    QSignalSpy spy(m_volume, SIGNAL(volumeChanged(uint)));
+    QFETCH(uint, volume);
+    QFETCH(uint, channel);
+    // Volume updated signal gives volume level as pulse audio's native value
+    // Which has range 0 - 0x10000
+    signalVolumeUpdated(channel, 0x10000*volume/100);
+
+    QCOMPARE(spy.count(), 1);
+    QList<QVariant> arguments = spy.takeFirst();
+
+    if (volume > 100) //Volume must not be set out of range
+    {
+        volume = 100;
+    }
+    QCOMPARE(arguments.at(0).toUInt(), volume);
+    QCOMPARE(m_volume->getVolume(), volume);
+}
+
+void Ut_MafwGstRendererVolume::testSignal_data()
+{
+    QTest::addColumn<uint>("volume");
+    QTest::addColumn<uint>("channel");
+
+    QTest::newRow("Maximum value") << (uint)100 << (uint)0;
+    QTest::newRow("Maximum value -1") << (uint)99 << (uint)0;
+    QTest::newRow("Value above range") << (uint)101 << (uint)0;
+    QTest::newRow("Huge value") << (uint)-1 << (uint)0;
+    QTest::newRow("Zero") << (uint)0 << (uint)0;
+    QTest::newRow("One") << (uint)1 << (uint)0;
+    QTest::newRow("Another channel") << (uint)2 << (uint)1;
+}
+
+//one MAFW volume step is 0x10000/100 = 655,36 native volume steps
+void Ut_MafwGstRendererVolume::testSetVolume()
+{    
+    QFETCH(uint, volume);
+    quint32 value = 1;
+
+    m_volume->setVolume(volume);
+    QVERIFY(m_setVolumeMethod != 0);
+    DBusMessageIter iter, array_iterator, struct_iterator, value_iterator;
+    dbus_message_iter_init (m_setVolumeMethod, &iter);
+    QCOMPARE(dbus_message_iter_get_arg_type(&iter), DBUS_TYPE_STRING);//interface
+    dbus_message_iter_next(&iter);
+    QCOMPARE(dbus_message_iter_get_arg_type(&iter), DBUS_TYPE_STRING);//property
+    dbus_message_iter_next(&iter);
+    dbus_message_iter_recurse (&iter, &array_iterator);
+    QCOMPARE(dbus_message_iter_get_arg_type(&array_iterator), DBUS_TYPE_ARRAY);
+    dbus_message_iter_recurse (&array_iterator, &struct_iterator);
+    QCOMPARE(dbus_message_iter_get_arg_type(&struct_iterator), DBUS_TYPE_STRUCT);
+
+    dbus_message_iter_recurse (&struct_iterator, &value_iterator);
+    QCOMPARE(dbus_message_iter_get_arg_type (&value_iterator), DBUS_TYPE_UINT32);
+    dbus_message_iter_get_basic (&value_iterator, &value);
+    QCOMPARE(value, (quint32)0); //mono channel
+    dbus_message_iter_next (&value_iterator);
+    QCOMPARE(dbus_message_iter_get_arg_type (&value_iterator), DBUS_TYPE_UINT32);
+    dbus_message_iter_get_basic (&value_iterator, &value);
+
+    if (volume > 100) //Volume must not be set out of range
+    {
+        volume = 100;
+    }
+
+    QCOMPARE(value, (quint32)(volume*0x10000/100));
+}
+
+
+void Ut_MafwGstRendererVolume::testSetVolume_data()
+{        
+    QTest::addColumn<uint>("volume");
+
+    QTest::newRow("Set volume to 0") << (uint)0;
+    QTest::newRow("Set volume to 1") << (uint)1;
+    QTest::newRow("Set volume to 99") << (uint)99;
+    QTest::newRow("Set volume to 100") << (uint)100;
+    QTest::newRow("Set volume to huge value") << (uint)-1;
+}
+
+QTEST_MAIN(Ut_MafwGstRendererVolume)
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.h
new file mode 100644 (file)
index 0000000..7ad1de6
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERVOLUME_H_
+#define UT_MAFWGSTRENDERERVOLUME_H_
+
+#include <QtTest/QtTest>
+
+class MafwGstRendererVolume;
+class MafwStubHelper;
+
+class Ut_MafwGstRendererVolume: public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void initTestCase();
+    void cleanupTestCase();
+
+    void testVolumeReply();
+    void testSignal();
+    void testSignal_data();
+    void testSetVolume();
+    void testSetVolume_data();
+
+private:
+
+    MafwGstRendererVolume* m_volume;
+    MafwStubHelper* m_stubHelper;
+};
+
+#endif /*UT_MAFWGSTRENDERERVOLUME_H_*/
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererVolume/ut_MafwGstRendererVolume.pro
new file mode 100644 (file)
index 0000000..f6f5a81
--- /dev/null
@@ -0,0 +1,29 @@
+TEMPLATE = app
+TARGET = 
+QT -= gui
+CONFIG = console
+
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR $$UT_COMMONDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG          += qtestlib qt link_pkgconfig debug qdbus
+PKGCONFIG       += qmafw dbus-1 libpulse-mainloop-glib
+LIBS            += -lgcov -ldbus-qeventloop
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += ut_MafwGstRendererVolume.h \
+           MafwGstRendererVolume.h \
+           $$UT_COMMONDIR/MafwStubHelper.h
+           
+SOURCES += ut_MafwGstRendererVolume.cpp \
+           MafwVolumeStubs.cpp \
+           MafwGstRendererVolume.cpp \
+           $$UT_COMMONDIR/MafwStubHelper.cpp \
+           
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.avi b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.avi
new file mode 100644 (file)
index 0000000..f868c62
Binary files /dev/null and b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.avi differ
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.wav b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.wav
new file mode 100644 (file)
index 0000000..943b040
Binary files /dev/null and b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/test.wav differ
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/testframe.png b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/testframe.png
new file mode 100644 (file)
index 0000000..a0db335
Binary files /dev/null and b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/media/testframe.png differ
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.cpp
new file mode 100644 (file)
index 0000000..b881ef7
--- /dev/null
@@ -0,0 +1,1432 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QDir>
+#include <QUrl>
+#include <QTimer>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/tag/tag.h>
+#include <context_provider.h>
+
+#include "ut_MafwGstRendererWorker.h"
+#include "mafw-gst-renderer-worker.h"
+#include "mafw-gst-renderer-utils.h"
+
+static QUrl AUDIO_URI(QDir::currentPath() + QDir::separator() +
+                      QString("media") + QDir::separator() +
+                      QString("test.wav"));
+
+static QUrl VIDEO_URI(QDir::currentPath() + QDir::separator() +
+                      QString("media") + QDir::separator() +
+                      QString("test.avi"));
+
+static QUrl IMAGE_URI(QDir::currentPath() + QDir::separator() +
+                      QString("media") + QDir::separator() +
+                      QString("testframe.png"));
+
+static int WAIT_TIMEOUT = 3500;
+static int EOS_TIMEOUT = 7000;
+static int READY_DELAY = 65000;
+
+static bool NEVER_HAPPENING_EVENT = false;
+
+static int global_context_duration = 0;
+
+static QStringList globalGstFactoryRequests;
+static GstElement *globalGstPipeline;
+
+
+const gchar* g_getenv(const gchar *variable)
+{
+    Q_UNUSED(variable);
+    return NULL;
+}
+
+gboolean convert_utf8(const gchar *src, gchar **dst)
+{
+    *dst = g_strdup(src);
+    return TRUE;
+}
+
+gboolean uri_is_playlist(const gchar *uri)
+{
+    Q_UNUSED(uri);
+    return FALSE;
+}
+
+gboolean uri_is_stream(const gchar *uri)
+{
+    Q_UNUSED(uri);
+    return FALSE;
+}
+
+gint remap_gst_error_code(const GError *error)
+{
+    return error->code;
+}
+
+void context_provider_set_map(const char* key, void* map, int free_map)
+{
+    Q_UNUSED(key);
+    Q_UNUSED(map);
+    Q_UNUSED(free_map);
+}
+
+void *context_provider_map_new(void)
+{
+
+    return NULL;
+}
+
+void context_provider_map_free(void* map)
+{
+    Q_UNUSED(map);
+}
+
+void context_provider_map_set_integer(void* map, const char* key, int value)
+{
+    Q_UNUSED(map);
+
+    if( strcmp( key, "duration" )==0 )
+    {
+        global_context_duration = value;
+    }
+}
+
+void context_provider_map_set_double(void* map, const char* key, double value)
+{
+    Q_UNUSED(map);
+    Q_UNUSED(key);
+    Q_UNUSED(value);
+}
+
+void context_provider_map_set_boolean(void* map, const char* key, int value)
+{
+    Q_UNUSED(map);
+    Q_UNUSED(key);
+    Q_UNUSED(value);
+}
+
+void context_provider_map_set_string(void* map, const char* key, const char* value)
+{
+    Q_UNUSED(map);
+    Q_UNUSED(key);
+    Q_UNUSED(value);
+}
+
+void context_provider_map_set_map(void* map, const char* key, void* value)
+{
+    Q_UNUSED(map);
+    Q_UNUSED(key);
+    Q_UNUSED(value);
+}
+
+void context_provider_set_null(const char* key)
+{
+    Q_UNUSED(key);
+}
+
+gboolean context_provider_init(DBusBusType bus_type, const char* bus_name)
+{
+
+    Q_UNUSED(bus_type);
+    Q_UNUSED(bus_name);
+
+    return TRUE;
+
+}
+
+void context_provider_stop(void)
+{
+}
+
+void context_provider_install_key(
+    const char* key,
+    gboolean clear_values_on_subscribe,
+    ContextProviderSubscriptionChangedCallback subscription_changed_cb,
+    void* subscription_changed_cb_target)
+{
+    Q_UNUSED(key);
+    Q_UNUSED(clear_values_on_subscribe);
+    Q_UNUSED(subscription_changed_cb);
+    Q_UNUSED(subscription_changed_cb_target);
+}
+
+GstElement *gst_element_factory_make(const gchar *factoryname, const gchar *name)
+{
+    GstElementFactory *factory;
+    GstElement *element;
+    const gchar *use_factoryname;
+
+    g_return_val_if_fail(factoryname != NULL, NULL);
+
+    globalGstFactoryRequests.append(factoryname);
+
+    /* For testing, use playbin instead of playbin2 */
+    if (g_str_equal(factoryname, "playbin2"))
+    {
+        use_factoryname = "playbin";
+    }
+    else
+    {
+        use_factoryname = factoryname;
+    }
+
+    GST_LOG("gstelementfactory: make \"%s\" \"%s\"",
+            use_factoryname, GST_STR_NULL (name));
+
+    factory = gst_element_factory_find(use_factoryname);
+    if (factory == NULL)
+    {
+        /* No factory */
+        GST_INFO("no such element factory \"%s\"!", use_factoryname);
+        return NULL;
+    }
+
+    GST_LOG_OBJECT(factory, "found factory %p", factory);
+    if (g_str_equal(use_factoryname, "pulsesink"))
+    {
+        element = gst_element_factory_make("fakesink", "pulsesink");
+        g_object_set(G_OBJECT(element), "sync", TRUE, NULL);
+    }
+    else if (g_str_equal(use_factoryname, "alsasink"))
+    {
+        element = gst_element_factory_make("fakesink", "alsasink");
+        g_object_set(G_OBJECT(element), "sync", TRUE, NULL);
+    }
+    else if (g_str_equal(use_factoryname, "xvimagesink")
+        || g_str_equal(use_factoryname, "omapxvsink"))
+    {
+        element = gst_element_factory_make("fakesink", "xvimagesink");
+        g_object_set(G_OBJECT(element), "sync", TRUE, NULL);
+    }
+    else
+    {
+        element = gst_element_factory_create(factory, name);
+        if( !g_strcmp0(use_factoryname, "playbin") )
+        {
+            globalGstPipeline = element;
+        }
+    }
+    gst_object_unref(factory);
+
+    if (element == NULL)
+    {
+        /* Create failed */
+        GST_INFO_OBJECT(factory, "couldn't create instance!");
+        return NULL;
+    }
+
+    GST_LOG("gstelementfactory: make \"%s\" \"%s\"",use_factoryname,
+            GST_STR_NULL(name));
+
+    /* Playbin will use fake renderer */
+    if (g_str_equal(use_factoryname, "playbin"))
+    {
+        GstElement *audiorenderer = gst_element_factory_make("fakesink",
+                                                             "audiorenderer");
+        g_object_set(G_OBJECT(audiorenderer), "sync", TRUE, NULL);
+        g_object_set(G_OBJECT(element), "audio-sink", audiorenderer, NULL);
+        g_object_set(G_OBJECT(element), "video-sink", audiorenderer, NULL);
+    }
+
+    return element;
+
+}
+/* END OF STUB DEFINITIONS */
+
+void ut_MafwGstRendererWorker::playCallback(MafwGstRendererWorker *worker,
+                                            gpointer owner)
+{
+
+    Q_UNUSED(worker);
+    Q_UNUSED(owner);
+    qDebug() << __PRETTY_FUNCTION__;
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_gotPlayCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::pauseCallback(MafwGstRendererWorker *worker,
+                                             gpointer owner)
+{
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_gotPauseCallback = true;
+}
+
+void ut_MafwGstRendererWorker::bufferingCallback(MafwGstRendererWorker *worker,
+                                                 gpointer owner,
+                                                 gdouble percent)
+{
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_receivedBufferStatus = percent;
+    self->m_gotBufferStatusCallback = true;
+}
+
+void ut_MafwGstRendererWorker::eosCallback(MafwGstRendererWorker *worker,
+                                           gpointer owner)
+{
+
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_gotEosCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::seekCallback(MafwGstRendererWorker *worker,
+                                            gpointer owner)
+{
+
+    Q_UNUSED(worker);
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_gotSeekCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::errorCallback(MafwGstRendererWorker *worker,
+                                             gpointer owner,
+                                             const GError *error)
+{
+
+    Q_UNUSED(worker);
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_receivedErrorCode = error->code;
+
+    if (error)
+    {
+        qCritical() << "error code: " << error->code << " message: " <<
+            error->message;
+    }
+    self->m_gotErrorCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::propertyCallback(MafwGstRendererWorker *worker,
+                                                gpointer owner,
+                                                gint id,
+                                                GValue *value)
+{
+
+    Q_UNUSED(worker);
+    Q_UNUSED(value);
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_receivedPropertyId = id;
+    self->m_gotPropertyCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::metadataCallback(MafwGstRendererWorker *worker,
+                                                gpointer owner,
+                                                gint key,
+                                                GType type,
+                                                gpointer value)
+{
+
+    Q_UNUSED(worker);
+    Q_UNUSED(type);
+    Q_UNUSED(value);
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_receivedMetadata.append(key);
+    self->m_gotMetadataCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::blankingControlCallback(MafwGstRendererWorker *worker,
+                                   gpointer owner, gboolean prohibit)
+{
+    Q_UNUSED(worker);
+
+    ut_MafwGstRendererWorker* self =
+        static_cast<ut_MafwGstRendererWorker*>(owner);
+    self->m_blankingProhibited = prohibit;
+}
+
+void ut_MafwGstRendererWorker::screenshotCallback(MafwGstRendererWorker *worker,
+                                                  gpointer owner, GstBuffer *buffer,
+                                                  const char *filename, gboolean cancel)
+{
+    Q_UNUSED(worker);
+    Q_UNUSED(buffer);
+    Q_UNUSED(filename);
+    if(!cancel)
+    {
+        ut_MafwGstRendererWorker* self =
+            static_cast<ut_MafwGstRendererWorker*>(owner);
+        self->m_receivedMetadata.append(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI);
+        self->m_gotMetadataCallback = true;
+    }
+}
+
+void ut_MafwGstRendererWorker::basicPlaybackTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QCOMPARE( global_context_duration, 3 ); // 2.5 seconds is duration of test.wav
+    QVERIFY(m_blankingProhibited == false);
+
+    //video-sink should not be created unless XID has been set
+    QVERIFY(!m_worker->vsink);
+}
+
+void ut_MafwGstRendererWorker::basicVideoPlaybackTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+
+    QVERIFY(!m_worker->vsink);
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+    QVERIFY(m_worker->vsink);
+
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+    m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(m_blankingProhibited == true);
+}
+
+void ut_MafwGstRendererWorker::pauseFrameTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->notify_metadata_handler = &metadataCallback;
+    m_worker->notify_property_handler = &propertyCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    m_worker->screenshot_handler = screenshotCallback;
+
+    mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+    QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+            TRUE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+    QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+
+    /* post xwindow-id on bus since we are using fakesink instead of
+     * xvimagesink */
+    GstBus *bus;
+    GstStructure *structure;
+    GstMessage *message;
+    structure = gst_structure_new("prepare-xwindow-id", "width",
+                                  G_TYPE_INT, 64, "height", G_TYPE_INT, 32,
+                                  NULL);
+    message = gst_message_new_element(NULL, structure);
+    bus = m_worker->bus;
+    gst_bus_post(bus, message);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, NEVER_HAPPENING_EVENT);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotMetadataCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+}
+
+void ut_MafwGstRendererWorker::pauseFrameCancelTestCase()
+{
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->notify_metadata_handler = &metadataCallback;
+    m_worker->notify_property_handler = &propertyCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    m_worker->screenshot_handler = screenshotCallback;
+
+    mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+    QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+            TRUE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+    QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+
+    /* post xwindow-id on bus since we are using fakesink instead of
+     * xvimagesink */
+    GstBus *bus;
+    GstStructure *structure;
+    GstMessage *message;
+    structure = gst_structure_new("prepare-xwindow-id", "width",
+                                  G_TYPE_INT, 64, "height", G_TYPE_INT, 32,
+                                  NULL);
+    message = gst_message_new_element(NULL, structure);
+    bus = m_worker->bus;
+    gst_bus_post(bus, message);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+    mafw_gst_renderer_worker_resume(m_worker);
+    QTest::qWait(10);
+
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotMetadataCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(!m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+
+}
+
+void ut_MafwGstRendererWorker::redirectMessageTestCase()
+{
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+
+    /* We just give random uri to renderer, because we ignore the error */
+    /* We don't have to test with real RTSP stream, we just use local content */
+    char *control = qstrdup(VIDEO_URI.toString().toAscii());
+
+    GstStructure *structure;
+    GstMessage *message;
+    structure = gst_structure_new("redirect", "new-location",
+                                  G_TYPE_STRING, control, NULL);
+
+       // reset and construct the pipeline
+    mafw_gst_renderer_worker_stop(m_worker);
+
+       // when worker receives "redirect" message, it should start playing the uri contained in the message.
+    message = gst_message_new_element(GST_OBJECT_CAST(m_worker->pipeline), structure);
+    gst_element_post_message(m_worker->pipeline, message);
+
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(strcmp(control, m_worker->media.location) == 0);
+    QVERIFY(m_gotErrorCallback == false);
+
+    delete[] control;
+}
+
+void ut_MafwGstRendererWorker::slotTimeOut()
+{
+    qDebug() << "TIMEOUT!";
+}
+
+void ut_MafwGstRendererWorker::waitForEvent(gint ms, bool &hasEventOccurred)
+
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (hasEventOccurred)
+    {
+        return;
+    }
+
+    QTimer timer(this);
+    QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));
+    timer.setSingleShot(true);
+    timer.start(ms);
+
+    while (!hasEventOccurred && timer.isActive())
+    {
+        g_main_context_iteration(NULL, TRUE);
+    }
+}
+
+void ut_MafwGstRendererWorker::bufferingTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_buffer_status_handler = &bufferingCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    /* post the buffering msg on bus */
+    GstBus *bus = 0;
+    GstMessage *message = 0;
+
+    message = gst_message_new_buffering(NULL, 50);
+    bus = m_worker->bus;
+    gst_bus_post(bus, message);
+
+    waitForEvent(WAIT_TIMEOUT, m_gotBufferStatusCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_receivedBufferStatus == 50);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::rendererArtTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->notify_metadata_handler = &metadataCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+    /* post the renderer art tag on bus */
+    gsize image_length = 0;
+    gchar *image = 0;
+    GstCaps *caps = 0;
+    GstBuffer *buffer = 0;
+    GstMessage *message = 0;
+    GstTagList *list = 0;
+
+    QVERIFY(g_file_get_contents(IMAGE_URI.toLocalFile().toAscii(),
+                                &image,
+                                &image_length,
+                                NULL));
+    buffer = gst_buffer_new();
+    gst_buffer_set_data(buffer, (guint8*)image, image_length);
+    caps = gst_caps_new_simple("image/png", "image-type",
+                               GST_TYPE_TAG_IMAGE_TYPE,
+                               GST_TAG_IMAGE_TYPE_FRONT_COVER, NULL);
+    gst_buffer_set_caps(buffer, caps);
+
+    list = gst_tag_list_new();
+    gst_tag_list_add(list, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, buffer, NULL);
+
+    message = gst_message_new_tag(NULL, list);
+    gst_bus_post(m_worker->bus, message);
+    mafw_gst_renderer_worker_resume(m_worker);
+
+    waitForEvent(WAIT_TIMEOUT, NEVER_HAPPENING_EVENT);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotMetadataCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(m_receivedMetadata.contains(WORKER_METADATA_KEY_RENDERER_ART_URI));
+
+    gst_buffer_unref(buffer);
+    gst_caps_unref(caps);
+    g_free(image);
+
+}
+
+void ut_MafwGstRendererWorker::eosTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_eos_handler = &eosCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+    waitForEvent(EOS_TIMEOUT, m_gotEosCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotEosCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::seekTestCase()
+{
+
+    GError *error = 0;
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_seek_handler = &seekCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+    mafw_gst_renderer_worker_set_position(m_worker,
+                                          GST_SEEK_TYPE_SET,
+                                          1,
+                                          &error);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotSeekCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(error == 0);
+    QVERIFY(mafw_gst_renderer_worker_get_position(m_worker) == 1);
+
+}
+
+void ut_MafwGstRendererWorker::invalidUriTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, "vjmksbhdfghrejggv");
+
+    waitForEvent(WAIT_TIMEOUT, m_gotErrorCallback);
+
+    QVERIFY(m_gotPlayCallback == false);
+    QVERIFY(m_gotErrorCallback == true);
+    /* FIXME: new code for Gst errors? */
+    /*QVERIFY(m_receivedErrorCode == WORKER_ERROR_UNABLE_TO_PERFORM);*/
+
+}
+
+void ut_MafwGstRendererWorker::playAndStopTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+
+    mafw_gst_renderer_worker_stop(m_worker);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::playAndPauseTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+    m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == false);
+    QVERIFY(m_blankingProhibited == true);
+
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(m_blankingProhibited == false);
+}
+
+void ut_MafwGstRendererWorker::pauseQuicklyAfterPlayTestCase()
+{
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+    m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+    mafw_gst_renderer_worker_pause(m_worker);
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+    QVERIFY(m_gotPlayCallback == false);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_blankingProhibited == false);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+
+    mafw_gst_renderer_worker_resume(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    waitForEvent(WAIT_TIMEOUT, m_blankingProhibited);
+    QCOMPARE(m_gotPlayCallback, true);
+    QCOMPARE(m_blankingProhibited, true);
+}
+
+void ut_MafwGstRendererWorker::pauseAtTestCase()
+{
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+    m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+    //the video is only two seconds long
+    mafw_gst_renderer_worker_pause_at(m_worker, 1);
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+    QVERIFY(m_gotPlayCallback == false);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_blankingProhibited == false);
+
+    QVERIFY(mafw_gst_renderer_worker_get_position(m_worker) == 1);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+
+    mafw_gst_renderer_worker_resume(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    waitForEvent(WAIT_TIMEOUT, m_blankingProhibited);
+    QCOMPARE(m_gotPlayCallback, true);
+    QCOMPARE(m_blankingProhibited, true);
+}
+
+void ut_MafwGstRendererWorker::playAndPauseAndResumeTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == false);
+
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+    m_gotPlayCallback = false;
+    mafw_gst_renderer_worker_resume(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+
+void ut_MafwGstRendererWorker::resumeDelayedTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == false);
+
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+    /* pipeline goes to ready after 60 seconds */
+    waitForEvent(READY_DELAY, NEVER_HAPPENING_EVENT);
+
+    m_gotPlayCallback = false;
+    mafw_gst_renderer_worker_resume(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::getCurrentMetadataTestCase()
+{
+
+    GHashTable *metadata = 0;
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == false);
+
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+    metadata = mafw_gst_renderer_worker_get_current_metadata(m_worker);
+    QVERIFY(metadata);
+    QVERIFY(g_hash_table_size(metadata));
+
+    mafw_gst_renderer_worker_stop(m_worker);
+    metadata = mafw_gst_renderer_worker_get_current_metadata(m_worker);
+    QVERIFY(!metadata);
+
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::defaultConfigurationTestCase()
+{
+    QVERIFY2(sizeof(configuration) == 64, "You've (or somebody else) most likely changed the configuration struct! Update the unittests also!");
+
+    configuration * current_worker_conf = mafw_gst_renderer_worker_create_default_configuration(m_worker);
+
+    QCOMPARE(current_worker_conf->asink, "pulsesink");
+    QCOMPARE(current_worker_conf->vsink, "omapxvsink");
+    QCOMPARE(current_worker_conf->buffer_time, 600000LL);
+    QCOMPARE(current_worker_conf->latency_time, 100000LL);
+    QCOMPARE(current_worker_conf->flags, 67);
+
+    QCOMPARE(current_worker_conf->mobile_surround_music.state, 0U);
+    QCOMPARE(current_worker_conf->mobile_surround_music.color, 2);
+    QCOMPARE(current_worker_conf->mobile_surround_music.room, 2);
+    QCOMPARE(current_worker_conf->mobile_surround_video.state, 0U);
+    QCOMPARE(current_worker_conf->mobile_surround_video.color, 2);
+    QCOMPARE(current_worker_conf->mobile_surround_video.room, 2);
+
+    QCOMPARE(current_worker_conf->milliseconds_to_pause_frame, 700U);
+    QCOMPARE(current_worker_conf->seconds_to_pause_to_ready, 3U);
+    QCOMPARE(current_worker_conf->use_dhmmixer, 1);
+
+    //this well make valgrind happy. i.e. worker will handle memory cleanupping
+    mafw_gst_renderer_worker_set_configuration(m_worker, current_worker_conf);
+}
+
+void ut_MafwGstRendererWorker::configurabilityTestCase()
+{
+    MafwGstRendererWorker *configWorker = mafw_gst_renderer_worker_new(this);
+
+    configuration *config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+
+    g_free(config->asink);
+    config->asink = g_strdup("test-sink");
+
+    //audio sink
+    QVERIFY(!globalGstFactoryRequests.contains("test-sink"));
+    mafw_gst_renderer_worker_set_configuration(configWorker, config);
+    mafw_gst_renderer_worker_stop(configWorker);
+    QVERIFY(globalGstFactoryRequests.contains("test-sink"));
+    globalGstFactoryRequests.clear();
+
+    mafw_gst_renderer_worker_exit(configWorker);
+    g_free(configWorker);
+
+
+    //video sink
+    configWorker = mafw_gst_renderer_worker_new(this);
+    config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+    g_free(config->vsink);
+    config->vsink = g_strdup("test-video-sink");
+
+    QVERIFY(!globalGstFactoryRequests.contains("test-video-sink"));
+
+    mafw_gst_renderer_worker_set_configuration(configWorker, config);
+    //video-sink is not created unless xid has been set
+    mafw_gst_renderer_worker_set_xid(configWorker, 0xffff);
+
+    mafw_gst_renderer_worker_stop(configWorker);
+    QVERIFY(globalGstFactoryRequests.contains("test-video-sink"));
+
+    globalGstFactoryRequests.clear();
+    mafw_gst_renderer_worker_exit(configWorker);
+    g_free(configWorker);
+
+
+    //NO dhmmixer
+    configWorker = mafw_gst_renderer_worker_new(this);
+    config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+    config->use_dhmmixer = 0;
+
+    QVERIFY(!globalGstFactoryRequests.contains("nokiadhmmix"));
+    mafw_gst_renderer_worker_set_configuration(configWorker, config);
+    mafw_gst_renderer_worker_stop(configWorker);
+    QVERIFY(!globalGstFactoryRequests.contains("nokiadhmmix"));
+
+    globalGstFactoryRequests.clear();
+    mafw_gst_renderer_worker_exit(configWorker);
+    g_free(configWorker);
+
+    //YES dhmmixer
+    configWorker = mafw_gst_renderer_worker_new(this);
+    config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+    config->use_dhmmixer = 1;
+
+    QVERIFY(!globalGstFactoryRequests.contains("nokiadhmmix"));
+    mafw_gst_renderer_worker_set_configuration(configWorker, config);
+    mafw_gst_renderer_worker_stop(configWorker);
+    QVERIFY(globalGstFactoryRequests.contains("nokiadhmmix"));
+
+    globalGstFactoryRequests.clear();
+    mafw_gst_renderer_worker_exit(configWorker);
+    g_free(configWorker);
+}
+
+void ut_MafwGstRendererWorker::pauseFrameConfigurabilityTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->notify_metadata_handler = &metadataCallback;
+    m_worker->notify_property_handler = &propertyCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    m_worker->screenshot_handler = screenshotCallback;
+
+    //let's change timeout values
+    configuration *config = mafw_gst_renderer_worker_create_default_configuration(m_worker);
+    config->milliseconds_to_pause_frame = 3000;
+    config->seconds_to_pause_to_ready = 6;
+    mafw_gst_renderer_worker_set_configuration(m_worker, config);
+
+
+    mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+    QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+            TRUE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+    QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+
+    /* post xwindow-id on bus since we are using fakesink instead of
+     * xvimagesink */
+    GstBus *bus;
+    GstStructure *structure;
+    GstMessage *message;
+    structure = gst_structure_new("prepare-xwindow-id", "width",
+                                  G_TYPE_INT, 64, "height", G_TYPE_INT, 32,
+                                  NULL);
+    message = gst_message_new_element(NULL, structure);
+    bus = m_worker->bus;
+    gst_bus_post(bus, message);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+    mafw_gst_renderer_worker_pause(m_worker);
+    QTest::qWait(2000);
+
+    //no pause frame yet, let's make sure
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == true);
+    QVERIFY(m_gotMetadataCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(!m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+    waitForEvent(WAIT_TIMEOUT, NEVER_HAPPENING_EVENT);
+    QVERIFY(m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+    mafw_gst_renderer_worker_stop(m_worker);
+    QTest::qWait(100);
+    config = mafw_gst_renderer_worker_create_default_configuration(m_worker);
+    mafw_gst_renderer_worker_set_configuration(m_worker, config);
+
+}
+
+void ut_MafwGstRendererWorker::setAndGetPropertiesTestCase()
+{
+
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_property_handler = &propertyCallback;
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+    QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    mafw_gst_renderer_worker_set_force_aspect_ratio(m_worker, FALSE);
+    QVERIFY(mafw_gst_renderer_worker_get_force_aspect_ratio(m_worker) == FALSE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_FORCE_ASPECT_RATIO);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+    mafw_gst_renderer_worker_set_force_aspect_ratio(m_worker, TRUE);
+    QVERIFY(mafw_gst_renderer_worker_get_force_aspect_ratio(m_worker) == TRUE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_FORCE_ASPECT_RATIO);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+    QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+            TRUE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+    mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, FALSE);
+    QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+            FALSE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    mafw_gst_renderer_worker_set_autopaint(m_worker, TRUE);
+    QVERIFY(mafw_gst_renderer_worker_get_autopaint(m_worker) == TRUE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_AUTOPAINT);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+    mafw_gst_renderer_worker_set_autopaint(m_worker, FALSE);
+    QVERIFY(mafw_gst_renderer_worker_get_autopaint(m_worker) == FALSE);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_AUTOPAINT);
+
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotPauseCallback == false);
+
+    mafw_gst_renderer_worker_set_playback_speed(m_worker, 2);
+    QVERIFY(mafw_gst_renderer_worker_get_playback_speed(m_worker) == 2);
+    QVERIFY(m_gotPropertyCallback == true);
+    QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_PLAYBACK_SPEED);
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+    mafw_gst_renderer_worker_set_playback_speed(m_worker, float(-1));
+    QCOMPARE(mafw_gst_renderer_worker_get_playback_speed(m_worker), float(-1));
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+    mafw_gst_renderer_worker_set_playback_speed(m_worker, float(2.5));
+    QCOMPARE(mafw_gst_renderer_worker_get_playback_speed(m_worker), float(2.5));
+
+    render_rectangle rect = {1,2,3,4};
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    mafw_gst_renderer_worker_set_render_rectangle(m_worker, &rect);
+    QVERIFY(m_gotPropertyCallback);
+    QVERIFY(m_receivedPropertyId != -1);
+    const render_rectangle *storedRect = mafw_gst_renderer_worker_get_render_rectangle(m_worker);
+    //the pointer value should not be used, copy must be made
+    QVERIFY(&rect != storedRect );
+    QCOMPARE(rect.x, storedRect->x);
+    QCOMPARE(rect.y, storedRect->y);
+    QCOMPARE(rect.width, storedRect->width);
+    QCOMPARE(rect.height, storedRect->height);
+
+    m_gotPropertyCallback = false;
+    m_receivedPropertyId = -1;
+
+    QVERIFY(m_gotErrorCallback == false);
+}
+
+void ut_MafwGstRendererWorker::gettersTestCase()
+{
+
+    m_worker->notify_error_handler = &errorCallback;
+
+    QVERIFY(mafw_gst_renderer_worker_get_colorkey(m_worker) == -1);
+    QVERIFY(mafw_gst_renderer_worker_get_seekable(m_worker) == TRUE);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::mediaRouteTestCase()
+{
+
+    GSList *list = NULL;
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_eos_handler = &eosCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+    mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+    /* normal audio playback */
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+    list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS));
+    list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY));
+    mafw_gst_renderer_worker_notify_media_destination(m_worker, list);
+    g_slist_free(list);
+    list = NULL;
+    QVERIFY(g_slist_length(m_worker->destinations) == 2);
+    QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+    QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+    waitForEvent(EOS_TIMEOUT, m_gotEosCallback);
+
+    QVERIFY(m_gotEosCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+    /* normal video playback */
+    m_gotPlayCallback = false;
+    m_gotEosCallback = false;
+    m_gotErrorCallback = false;
+    QVERIFY(m_blankingProhibited == false);
+    mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+    m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    QVERIFY(m_blankingProhibited == true);
+
+    list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK));
+    list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY));
+    mafw_gst_renderer_worker_notify_media_destination(m_worker, list);
+    g_slist_free(list);
+    list = NULL;
+    QVERIFY(g_slist_length(m_worker->destinations) == 2);
+    QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+    QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+    waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+    QVERIFY(m_gotEosCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::setReadyTimeoutTestCase()
+{
+
+    m_worker->notify_play_handler = &playCallback;
+    m_worker->notify_error_handler = &errorCallback;
+    m_worker->notify_pause_handler = &pauseCallback;
+    m_worker->notify_eos_handler = &eosCallback;
+    m_worker->blanking__control_handler = &blankingControlCallback;
+
+    /* do some basic set calls first */
+    mafw_gst_renderer_worker_set_ready_timeout(m_worker, 0);
+    QVERIFY(m_worker->config->seconds_to_pause_to_ready == 0);
+    mafw_gst_renderer_worker_set_ready_timeout(m_worker, 60);
+    QVERIFY(m_worker->config->seconds_to_pause_to_ready == 60);
+
+    /* set timeout to 0, pause in the middle of the playback */
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+    mafw_gst_renderer_worker_set_ready_timeout(m_worker, 0);
+    QVERIFY(m_worker->config->seconds_to_pause_to_ready == 0);
+    QTest::qWait(1500);
+    QVERIFY(m_worker->state == GST_STATE_PLAYING);
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+    QVERIFY(m_worker->state == GST_STATE_PAUSED);
+    QTest::qWait(500);
+    QVERIFY(m_worker->state == GST_STATE_READY);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+
+    mafw_gst_renderer_worker_resume(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_worker->state == GST_STATE_PLAYING);
+    waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+    QVERIFY(m_gotEosCallback == true);
+
+    /* set timeout to 3, pause in the middle of the playback */
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+    mafw_gst_renderer_worker_set_ready_timeout(m_worker, 3);
+    QVERIFY(m_worker->config->seconds_to_pause_to_ready == 3);
+    QTest::qWait(1500);
+    QVERIFY(m_worker->state == GST_STATE_PLAYING);
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+    QVERIFY(m_worker->state == GST_STATE_PAUSED);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+    QTest::qWait(4000);
+    QVERIFY(m_worker->state == GST_STATE_READY);
+
+    mafw_gst_renderer_worker_resume(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_worker->state == GST_STATE_PLAYING);
+    waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+    QVERIFY(m_gotEosCallback == true);
+
+    /* set timeout to 0, pause in the middle of the playback after setting the
+     * timeout value --> we should go to ready immediately */
+    mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_gotErrorCallback == false);
+    mafw_gst_renderer_worker_set_ready_timeout(m_worker, 60);
+    QVERIFY(m_worker->config->seconds_to_pause_to_ready == 60);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+    QTest::qWait(1500);
+    QVERIFY(m_worker->state == GST_STATE_PLAYING);
+    mafw_gst_renderer_worker_pause(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+    QVERIFY(m_worker->state == GST_STATE_PAUSED);
+    mafw_gst_renderer_worker_set_ready_timeout(m_worker, 0);
+    QVERIFY(m_worker->config->seconds_to_pause_to_ready == 0);
+    QTest::qWait(500);
+    QVERIFY(m_worker->state == GST_STATE_READY);
+
+    m_gotPlayCallback = false;
+    m_gotPauseCallback = false;
+
+    mafw_gst_renderer_worker_resume(m_worker);
+    waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+    QVERIFY(m_gotPlayCallback == true);
+    QVERIFY(m_worker->state == GST_STATE_PLAYING);
+    waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+    QVERIFY(m_gotEosCallback == true);
+
+}
+
+void ut_MafwGstRendererWorker::initTestCase()
+{
+    gst_init(0,0);
+}
+
+void ut_MafwGstRendererWorker::init()
+{
+
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_worker = 0;
+    m_receivedErrorCode = -1;
+    m_receivedPropertyId = -1;
+    m_receivedBufferStatus = -1.0;
+    m_receivedMetadata.clear();
+    m_gotPlayCallback = false;
+    m_gotEosCallback = false;
+    m_gotErrorCallback = false;
+    m_gotPauseCallback = false;
+    m_gotSeekCallback = false;
+    m_gotMetadataCallback = false;
+    m_gotPropertyCallback = false;
+    m_gotBufferStatusCallback = false;
+    m_blankingProhibited = false;
+
+    global_context_duration = 0;
+
+    bool ok;
+    QByteArray tmo = qgetenv("WAIT_TIMEOUT");
+    int val = tmo.toInt(&ok, 10);
+    if (ok)
+    {
+        WAIT_TIMEOUT = val;
+        qDebug() << "WAIT_TIMEOUT is set to" << WAIT_TIMEOUT;
+    }
+    else
+    {
+        qDebug() << "Using default WAIT_TIMEOUT" << WAIT_TIMEOUT;
+    }
+
+    const QString scheme("file");
+    AUDIO_URI.setScheme(scheme);
+    VIDEO_URI.setScheme(scheme);
+    IMAGE_URI.setScheme(scheme);
+
+    m_worker = mafw_gst_renderer_worker_new(this);
+
+    QVERIFY(m_worker != 0);
+
+    globalGstFactoryRequests.clear();
+}
+
+void ut_MafwGstRendererWorker::cleanup()
+{
+    QVERIFY(m_worker != 0);
+
+    mafw_gst_renderer_worker_exit(m_worker);
+    g_free(m_worker);
+
+    QVERIFY(m_blankingProhibited == false);
+
+    m_gotPlayCallback = false;
+    m_gotErrorCallback = false;
+}
+
+QTEST_MAIN(ut_MafwGstRendererWorker)
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.h
new file mode 100644 (file)
index 0000000..df7e87d
--- /dev/null
@@ -0,0 +1,111 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#ifndef UT_MAFW_GST_RENDERER_WORKER_H_
+#define UT_MAFW_GST_RENDERER_WORKER_H_
+
+#include <QObject>
+#include <QtTest/QtTest>
+
+#include "mafw-gst-renderer-worker.h"
+
+class ut_MafwGstRendererWorker: public QObject
+{
+    Q_OBJECT
+
+private slots: // tests
+
+    void basicPlaybackTestCase();
+    void basicVideoPlaybackTestCase();
+    void eosTestCase();
+    void playAndPauseTestCase();
+    void playAndStopTestCase();
+    void setAndGetPropertiesTestCase();
+    void gettersTestCase();
+    void playAndPauseAndResumeTestCase();
+    void pauseQuicklyAfterPlayTestCase();
+    void pauseAtTestCase();
+    void resumeDelayedTestCase();
+    void getCurrentMetadataTestCase();
+    void invalidUriTestCase();
+    void seekTestCase();
+    void defaultConfigurationTestCase();
+    void configurabilityTestCase();
+    void pauseFrameTestCase();
+    void pauseFrameConfigurabilityTestCase();
+    void pauseFrameCancelTestCase();
+    void rendererArtTestCase();
+    void bufferingTestCase();
+    void mediaRouteTestCase();
+    void setReadyTimeoutTestCase();
+    void redirectMessageTestCase();
+
+    void initTestCase();
+    void init();
+    void cleanup();
+
+protected slots:
+    void slotTimeOut();
+    
+protected:
+    static void playCallback(MafwGstRendererWorker *worker, gpointer owner);
+    static void eosCallback(MafwGstRendererWorker *worker, gpointer owner);
+    static void errorCallback(MafwGstRendererWorker *worker,
+                              gpointer owner,
+                              const GError *error);
+    static void pauseCallback(MafwGstRendererWorker *worker, gpointer owner);
+    static void propertyCallback(MafwGstRendererWorker *worker,
+                                 gpointer owner,
+                                 gint id,
+                                 GValue *value);
+    static void seekCallback(MafwGstRendererWorker *worker, gpointer owner);
+    static void metadataCallback(MafwGstRendererWorker *worker,
+                                 gpointer owner,
+                                 gint key,
+                                 GType type,
+                                 gpointer value);
+    static void bufferingCallback(MafwGstRendererWorker *worker,
+                                  gpointer owner,
+                                  gdouble percent);
+    static void blankingControlCallback(MafwGstRendererWorker *worker,
+                                        gpointer owner, gboolean prohibit);
+    static void screenshotCallback(MafwGstRendererWorker *worker,
+                                   gpointer owner,
+                                   GstBuffer *buffer,
+                                   const char *filename,
+                                   gboolean cancel);
+
+    void waitForEvent(gint ms, bool &hasEventOccurred);
+
+private: //data
+    MafwGstRendererWorker *m_worker;
+    bool m_gotPlayCallback;
+    bool m_gotEosCallback;
+    bool m_gotErrorCallback;
+    bool m_gotPauseCallback;
+    bool m_gotSeekCallback;
+    bool m_gotMetadataCallback;
+    bool m_gotPropertyCallback;
+    bool m_gotBufferStatusCallback;
+    bool m_blankingProhibited;
+    int m_receivedErrorCode;
+    int m_receivedPropertyId;
+    gdouble m_receivedBufferStatus;
+    QList<int> m_receivedMetadata;
+};
+
+#endif
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwGstRendererWorker/ut_MafwGstRendererWorker.pro
new file mode 100644 (file)
index 0000000..8e4a2ac
--- /dev/null
@@ -0,0 +1,31 @@
+TEMPLATE        = app
+QT -= gui
+CONFIG = console
+
+isEmpty(PREFIX) {
+    PREFIX=/usr
+}
+
+CONFIG          += qt link_pkgconfig debug
+CONFIG          += qtestlib
+PKGCONFIG       += glib-2.0 gobject-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10
+PKGCONFIG       += contextprovider-1.0 x11 gstreamer-tag-0.10
+
+LIBS +=  -lgstinterfaces-0.10 -lgstpbutils-0.10 -lgcov
+
+DEPENDPATH      += . ../../inc ../../src
+INCLUDEPATH     += . ../../inc
+
+QMAKE_CXXFLAGS  += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+QMAKE_CFLAGS    += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+
+QMAKE_CLEAN     += *.gcda *.gcno *.gcov ut_MafwGstRendererWorker *.vg.xml vgcore.*
+
+HEADERS         += ut_MafwGstRendererWorker.h \
+                   mafw-gst-renderer-worker.h \
+                   mafw-gst-renderer-seeker.c
+
+SOURCES         += ut_MafwGstRendererWorker.cpp \
+                   mafw-gst-renderer-worker.c \
+                   mafw-gst-renderer-seeker.c
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.cpp
new file mode 100644 (file)
index 0000000..80fb7f3
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "ut_MafwMmcMonitor.h"
+
+#include <usb_moded-dbus.h>
+
+#include <QDebug>
+#include <QSignalSpy>
+
+#define private public // access private slots
+#include "MafwMmcMonitor.h"
+
+extern QStringList stubMounts;
+extern QStringList g_dbusConnectionParams;
+
+void Ut_MafwMmcMonitor::initTestCase()
+{
+}
+
+void Ut_MafwMmcMonitor::cleanupTestCase()
+{
+}
+
+void Ut_MafwMmcMonitor::testConstruction()
+{
+    QFETCH(QStringList, mounts);
+    QFETCH(bool, mmcMounted);
+
+    stubMounts = mounts;
+
+    MafwMmcMonitor monitor(this);
+
+    QVERIFY( monitor.isMounted()==mmcMounted );
+
+    QCOMPARE(g_dbusConnectionParams.at(0), QString(USB_MODE_SERVICE));
+    QCOMPARE(g_dbusConnectionParams.at(1), QString(USB_MODE_OBJECT));
+    QCOMPARE(g_dbusConnectionParams.at(2), QString(USB_MODE_INTERFACE));
+    QCOMPARE(g_dbusConnectionParams.at(3), QString(USB_MODE_SIGNAL_NAME));
+    QVERIFY(g_dbusConnectionParams.at(4).toUInt() > static_cast<uint>(0));
+    QVERIFY(g_dbusConnectionParams.at(5).length() > 0);
+
+}
+
+void Ut_MafwMmcMonitor::testConstruction_data()
+{
+    QTest::addColumn<QStringList>("mounts");
+    QTest::addColumn<bool>("mmcMounted");
+
+    QTest::newRow("none") << (QStringList()) << false;
+    QTest::newRow("nommc") << (QStringList() << "file:///home/user/.mms/private" << "file:///home/user/.nokiamessaging/IM") << false;
+    QTest::newRow("mmc") << (QStringList() << "file:///home/user/MyDocs" << "file:///home/user/.nokiamessaging/IM") << true;
+}
+
+void Ut_MafwMmcMonitor::testMounts()
+{
+    stubMounts.clear();
+    MafwMmcMonitor monitor(this);
+
+    QVERIFY( !monitor.isMounted() );
+
+    stubMounts << "file:///home/user/.mms/private"  << "file:///home/user/MyDocs";
+    monitor.mountEvent( 0, (GMount*)1, &monitor );
+    QVERIFY( !monitor.isMounted() );
+    monitor.mountEvent( 0, (GMount*)2, &monitor );
+    QVERIFY( monitor.isMounted() );
+
+    monitor.unmountEvent( 0, (GMount*)1, &monitor );
+    QVERIFY( monitor.isMounted() );
+    monitor.unmountEvent( 0, (GMount*)2, &monitor );
+    QVERIFY( !monitor.isMounted() );
+}
+
+void Ut_MafwMmcMonitor::testPreUnmount()
+{
+    MafwMmcMonitor monitor(this);
+    QSignalSpy spy( &monitor, SIGNAL( preUnmount() ) );
+
+    monitor.preUnmountEvent("pre-unmount");
+    QVERIFY( spy.size()==1 );
+}
+
+QTEST_MAIN(Ut_MafwMmcMonitor)
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.h b/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.h
new file mode 100644 (file)
index 0000000..9b840db
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWMMCMONITOR_H_
+#define UT_MAFWMMCMONITOR_H_
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+
+#include <QtTest/QtTest>
+
+
+class Ut_MafwMmcMonitor : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void initTestCase();
+    void cleanupTestCase();
+
+    void testConstruction();
+    void testConstruction_data();
+
+    void testMounts();
+    void testPreUnmount();
+
+};
+
+#endif /*UT_MAFWMMCMONITOR_H_*/
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.pro b/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitor.pro
new file mode 100644 (file)
index 0000000..ccc537f
--- /dev/null
@@ -0,0 +1,28 @@
+TEMPLATE = app
+TARGET =
+QT -= gui
+CONFIG = console
+
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+#UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG += qtestlib
+CONFIG += qt qdbus link_pkgconfig debug
+
+PKGCONFIG += glib-2.0 gio-2.0 gio-unix-2.0 usb_moded dbus-1
+
+LIBS += -lgcov
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += MafwMmcMonitor.h \
+    ut_MafwMmcMonitor.h
+
+SOURCES += MafwMmcMonitor.cpp \
+    ut_MafwMmcMonitor.cpp \
+    ut_MafwMmcMonitorStubs.cpp
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitorStubs.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_MafwMmcMonitor/ut_MafwMmcMonitorStubs.cpp
new file mode 100644 (file)
index 0000000..507b144
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <gio/gio.h>
+#include <QStringList>
+#include <QDBusConnection>
+
+QStringList stubMounts;
+
+QStringList g_dbusConnectionParams;
+
+// GVolumeMonitor
+
+GVolumeMonitor *g_volume_monitor_get(void)
+{
+    return (GVolumeMonitor*)1;
+}
+
+GList * g_volume_monitor_get_mounts(GVolumeMonitor *volume_monitor)
+{
+    return (GList*)1;
+}
+
+// GObject
+
+gulong  g_signal_connect_data                (gpointer           instance,
+                           const gchar  *detailed_signal,
+                           GCallback     c_handler,
+                           gpointer              data,
+                           GClosureNotify        destroy_data,
+                           GConnectFlags         connect_flags)
+{
+    return 0;
+}
+
+void g_object_unref(gpointer object)
+{
+}
+
+// GList
+
+guint g_list_length(GList *list)
+{
+    return stubMounts.size();
+}
+
+gpointer g_list_nth_data(GList *list, guint n)
+{
+    return (void*)(n+1);
+}
+
+void g_list_free(GList *list)
+{
+}
+
+// GMount
+
+GFile * g_mount_get_root(GMount *mount)
+{
+    return (GFile*)mount;
+}
+
+// GFile
+
+char* g_file_get_uri(GFile *file)
+{
+    return g_strdup(stubMounts[(int)file-1].toAscii().constData());
+}
+
+
+//QDBusConnection
+
+QDBusConnection::QDBusConnection(const QString& /*name*/)
+{
+}
+
+QDBusConnection QDBusConnection::sessionBus()
+{
+    return QDBusConnection("...");
+}
+
+bool QDBusConnection::connect(const QString &service,
+                              const QString &path,
+                              const QString &interface,
+                              const QString &name,
+                              QObject *receiver,
+                              const char *slot)
+{
+    g_dbusConnectionParams << service;
+    g_dbusConnectionParams << path;
+    g_dbusConnectionParams << interface;
+    g_dbusConnectionParams << name;
+    g_dbusConnectionParams << QString::number(reinterpret_cast<uint>(receiver));
+    g_dbusConnectionParams << slot;
+
+    return true;
+}
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.cpp
new file mode 100644 (file)
index 0000000..a820cc1
--- /dev/null
@@ -0,0 +1,150 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include <QTimer>
+
+#include <string.h>
+#include <glib.h>
+#include <gst/gst.h>
+
+#include "ut_Others.h"
+#include "mafw-gst-renderer-utils.h"
+#include "mafw-gst-renderer-worker.h"
+
+#define UNUSED(x) (void)(x)
+
+/* START OF STUB DEFINITIONS */
+gboolean g_utf8_validate(const gchar *str,
+                         gssize max_len,
+                         const gchar **end)
+{
+
+    UNUSED(max_len);
+    UNUSED(end);
+
+    if (g_str_equal("valid", str))
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+
+}
+
+gchar* g_locale_to_utf8(const gchar *opsysstring,
+                        gssize len,
+                        gsize *bytes_read,
+                        gsize *bytes_written,
+                        GError **error)
+{
+
+    UNUSED(len);
+    UNUSED(bytes_read);
+    UNUSED(bytes_written);
+
+    if (g_str_equal("non-valid", opsysstring))
+    {
+        return g_strdup(opsysstring);
+    }
+    else
+    {
+        g_set_error(error,
+                    g_quark_from_string("test"),
+                    100,
+                    "%s", "SIMULATED ERROR");
+        return NULL;
+    }
+}
+
+
+/* END OF STUB DEFINITIONS */
+
+void ut_Others::testUtils()
+{
+    QVERIFY(uri_is_stream("file:///file.m3u") == FALSE);
+    QVERIFY(uri_is_stream("http:///joojoo.com") == TRUE);
+    QVERIFY(uri_is_stream(NULL) == FALSE);
+
+    gchar *dst = NULL;
+    QVERIFY(convert_utf8(NULL, NULL) == FALSE);
+    QVERIFY(convert_utf8("valid", NULL) == FALSE);
+    QVERIFY(convert_utf8(NULL, &dst) == FALSE);
+    QVERIFY(convert_utf8("valid", &dst) == TRUE);
+    g_free(dst);
+    QVERIFY(convert_utf8("non-valid", &dst) == TRUE);
+    QVERIFY(dst);
+    QVERIFY(g_str_equal(dst, "non-valid") == TRUE);
+    g_free(dst);
+    QVERIFY(convert_utf8("error", &dst) == FALSE);
+
+}
+
+void ut_Others::testGstErrorRemapping()
+{
+
+    GQuark domain = g_quark_from_string("test_error_domain");
+
+    GError* error = g_error_new_literal(domain, 999, "error_message");
+    QVERIFY(remap_gst_error_code(error) == 999);
+
+    error->domain = GST_RESOURCE_ERROR;
+    error->code = GST_RESOURCE_ERROR_READ;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_STREAM_DISCONNECTED);
+    error->code = GST_RESOURCE_ERROR_NOT_FOUND;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_MEDIA_NOT_FOUND);
+    error->code = GST_RESOURCE_ERROR_OPEN_READ_WRITE;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_MEDIA_NOT_FOUND);
+    error->code = GST_RESOURCE_ERROR_NO_SPACE_LEFT;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNABLE_TO_PERFORM);
+    error->code = GST_RESOURCE_ERROR_WRITE;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CORRUPTED_FILE);
+    error->code = GST_RESOURCE_ERROR_SEEK;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CANNOT_SET_POSITION);
+    error->code = 999999;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNABLE_TO_PERFORM);
+
+    error->domain = GST_STREAM_ERROR;
+    error->code = GST_STREAM_ERROR_TYPE_NOT_FOUND;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_TYPE_NOT_AVAILABLE);
+    error->code = GST_STREAM_ERROR_FORMAT;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNSUPPORTED_TYPE);
+    error->code = GST_STREAM_ERROR_DECODE;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CORRUPTED_FILE);
+    error->code = GST_STREAM_ERROR_CODEC_NOT_FOUND;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CODEC_NOT_FOUND);
+    error->code = GST_STREAM_ERROR_DECRYPT;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_DRM_NOT_ALLOWED);
+    error->code = 999999;
+    QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNABLE_TO_PERFORM);
+
+    g_error_free(error);
+
+}
+
+void ut_Others::init()
+{
+
+}
+
+void ut_Others::cleanup()
+{
+
+}
+
+QTEST_APPLESS_MAIN(ut_Others)
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.h b/qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.h
new file mode 100644 (file)
index 0000000..1b42c02
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#ifndef UT_OTHERS_H_
+#define UT_OTHERS_H_
+
+#include <QObject>
+#include <QtTest/QtTest>
+
+class ut_Others: public QObject
+{
+    Q_OBJECT
+
+private slots: // tests
+
+    void testUtils();
+    void testGstErrorRemapping();
+
+    void init();
+    void cleanup();
+
+protected slots:
+    
+protected:
+
+private: //data
+
+};
+
+#endif
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.pro b/qmafw-gst-subtitles-renderer/unittests/ut_Others/ut_Others.pro
new file mode 100644 (file)
index 0000000..e204160
--- /dev/null
@@ -0,0 +1,26 @@
+TEMPLATE        = app
+
+isEmpty(PREFIX) {
+    PREFIX=/usr
+}
+
+CONFIG          += qt link_pkgconfig release
+CONFIG          += qtestlib
+PKGCONFIG       += glib-2.0 gobject-2.0 gstreamer-0.10
+
+LIBS            +=  -lgcov
+
+DEPENDPATH      += . ../../inc ../../src
+INCLUDEPATH     += . ../../inc
+
+QMAKE_CXXFLAGS  += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+QMAKE_CFLAGS    += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+
+QMAKE_CLEAN     += *.gcda *.gcno *.gcov ut_Others *.vg.xml vgcore.*
+
+HEADERS         += ut_Others.h \
+                   mafw-gst-renderer-utils.h
+
+SOURCES         += ut_Others.cpp \
+                   mafw-gst-renderer-utils.c
+
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.cpp b/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.cpp
new file mode 100644 (file)
index 0000000..46029c2
--- /dev/null
@@ -0,0 +1,149 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <QSignalSpy>
+
+#include "Ut_PlaylistFileUtility.h"
+#include "../common/MafwStubHelper.h"
+#include "MafwGstRendererPlaylistFileUtility.h"
+
+void Ut_PlaylistFileUtility::initTestCase()
+{
+    m_stubHelper = new MafwStubHelper;
+    m_utility = new MafwGstRendererPlaylistFileUtility(this);
+}
+
+void Ut_PlaylistFileUtility::testParsing()
+{
+    QString file("/test-station.pls");
+    file.prepend(QDir::currentPath());
+    file.prepend("file://");
+
+    QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+    QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+    m_utility->parsePlaylistFile(QUrl(file));
+    QTest::qWait(1000);
+
+    QCOMPARE(readySpy.count(), 1);
+    QList<QVariant> arguments = readySpy.takeFirst();
+    QVERIFY(arguments.at(0).toBool() == true);
+    QCOMPARE(parsingSpy.count(), 1);
+
+    //There is 19 entries in test-station.pls file
+    for (int i=0; i<19; i++)
+    {
+        QVERIFY(m_utility->takeFirstUri().length() > 0);
+    }
+
+    QVERIFY(m_utility->takeFirstUri().length() == 0);
+}
+
+void Ut_PlaylistFileUtility::testParsingForNotExistingFile()
+{
+    QString file("/not-existing.pls");
+    file.prepend(QDir::currentPath());
+    file.prepend("file://");
+    QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+    QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+
+    m_utility->parsePlaylistFile(QUrl(file));
+    QTest::qWait(1000);
+    QCOMPARE(readySpy.count(), 1);
+    QCOMPARE(parsingSpy.count(), 0);
+    QList<QVariant> arguments = readySpy.takeFirst();
+    QVERIFY(arguments.at(0).toBool() == false);
+}
+
+void Ut_PlaylistFileUtility::testParsingInvalidFileUri()
+{
+//No scheme
+    QString file("/test-station.pls");
+    file.prepend(QDir::currentPath());
+    QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+    QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+    m_utility->parsePlaylistFile(QUrl(file));
+    QTest::qWait(1000);
+    QCOMPARE(parsingSpy.count(), 0);
+    QCOMPARE(readySpy.count(), 1);
+    QList<QVariant> arguments = readySpy.takeFirst();
+    QVERIFY(arguments.at(0).toBool() == false);
+
+//Contains only path
+    QString file2(QDir::currentPath());
+    file2.prepend("file://");
+    m_utility->parsePlaylistFile(file2);
+    QTest::qWait(1000);
+    QCOMPARE(parsingSpy.count(), 0);
+    QCOMPARE(readySpy.count(), 1);
+    arguments = readySpy.takeFirst();
+    QVERIFY(arguments.at(0).toBool() == false);
+}
+
+void Ut_PlaylistFileUtility::testParsingInvalidFile()
+{
+    QString file("/test-station_invalid.pls");
+    file.prepend(QDir::currentPath());
+    file.prepend("file://");
+
+    QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+    QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+    m_utility->parsePlaylistFile(QUrl(file));
+    QTest::qWait(1000);
+
+    QCOMPARE(readySpy.count(), 1);
+    QList<QVariant> arguments = readySpy.takeFirst();
+    QVERIFY(arguments.at(0).toBool() == true);
+    QCOMPARE(parsingSpy.count(), 0);
+
+    QVERIFY(m_utility->takeFirstUri().length() == 0);
+}
+
+void Ut_PlaylistFileUtility::testParsingASFFile()
+{
+    QString file("/test.asf");
+    file.prepend(QDir::currentPath());
+    file.prepend("file://");
+
+    QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+    QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+    m_utility->parsePlaylistFile(QUrl(file));
+    QTest::qWait(1000);
+
+    QCOMPARE(readySpy.count(), 1);
+    QList<QVariant> arguments = readySpy.takeFirst();
+    QVERIFY(arguments.at(0).toBool() == true);
+    QCOMPARE(parsingSpy.count(), 1);
+
+    for (int i=0; i < 1; i++)
+    {
+        QString test = m_utility->takeFirstUri();
+        QVERIFY(test.length() > 0);
+        QVERIFY(test.startsWith("mmsh://195"));
+        QVERIFY(test.endsWith(".asf"));
+    }
+
+    QVERIFY(m_utility->takeFirstUri().length() == 0);
+}
+
+void Ut_PlaylistFileUtility::cleanupTestCase()
+{
+    delete m_stubHelper;
+}
+
+QTEST_MAIN(Ut_PlaylistFileUtility)
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.h b/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.h
new file mode 100644 (file)
index 0000000..eeaea93
--- /dev/null
@@ -0,0 +1,46 @@
+/* 
+ * This file is part of QMAFW 
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_PLAYLISTFILEUTILITY_H
+#define UT_PLAYLISTFILEUTILITY_H
+
+#include <QObject>
+
+class MafwStubHelper;
+class MafwGstRendererPlaylistFileUtility;
+
+class Ut_PlaylistFileUtility: public QObject
+{
+    Q_OBJECT
+    
+private Q_SLOTS: // tests
+
+    void initTestCase();
+    void testParsing();
+    void testParsingForNotExistingFile();
+    void testParsingInvalidFileUri();
+    void testParsingInvalidFile();
+    void testParsingASFFile();
+    void cleanupTestCase();
+
+private:
+    MafwStubHelper* m_stubHelper;
+    MafwGstRendererPlaylistFileUtility* m_utility;
+
+};
+
+#endif // UT_PLAYLISTFILEUTILITY_H
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.pro b/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/Ut_PlaylistFileUtility.pro
new file mode 100644 (file)
index 0000000..c75d957
--- /dev/null
@@ -0,0 +1,31 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Mon Aug 23 09:32:17 2010
+######################################################################
+TEMPLATE = app
+TARGET = 
+QT -= gui
+CONFIG = console
+
+MAFW_GST_INCDIR = ../../inc
+DEPENDPATH += . $$MAFW_GST_INCDIR ../../src
+INCLUDEPATH += . $$MAFW_GST_INCDIR /usr/include/qmafw
+
+CONFIG          += qtestlib no_keywords
+CONFIG          += qt link_pkgconfig debug
+PKGCONFIG       += qmafw glib-2.0 gobject-2.0 
+PKGCONFIG       += contextprovider-1.0 x11 libpulse-mainloop-glib contextsubscriber-1.0
+LIBS            += -lgcov -ltotem-plparser
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+
+# Input
+HEADERS += Ut_PlaylistFileUtility.h \
+           ../common/MafwStubHelper.h \
+           MafwGstRendererPlaylistFileUtility.h
+           
+SOURCES += Ut_PlaylistFileUtility.cpp \
+           ../common/MafwStubHelper.cpp \
+           MafwGstRendererPlaylistFileUtility.cpp \
+           #totemParserStub.c
+           
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test-station.pls b/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test-station.pls
new file mode 100644 (file)
index 0000000..572e215
--- /dev/null
@@ -0,0 +1,60 @@
+[playlist]
+numberofentries=19
+File1=http://188.165.211.147:8002
+Title1=(#1 - 7/19) RMF FM
+Length1=-1
+File2=http://188.165.12.66:8006
+Title2=(#2 - 524/950) RMF FM
+Length1=-1
+File3=http://91.121.124.91:8002
+Title3=(#3 - 543/950) RMF FM
+Length1=-1
+File4=http://188.165.12.67:8004
+Title4=(#4 - 547/950) RMF FM
+Length1=-1
+File5=http://188.165.12.67:8000
+Title5=(#5 - 554/950) RMF FM
+Length1=-1
+File6=http://188.165.12.66:8002
+Title6=(#6 - 562/950) RMF FM
+Length1=-1
+File7=http://188.165.12.66:8000
+Title7=(#7 - 573/950) RMF FM
+Length1=-1
+File8=http://188.165.12.66:8004
+Title8=(#8 - 596/950) RMF FM
+Length1=-1
+File9=http://91.121.125.91:8000
+Title9=(#9 - 614/950) RMF FM
+Length1=-1
+File10=http://188.165.12.67:8002
+Title10=(#10 - 647/950) RMF FM
+Length1=-1
+File11=http://188.165.12.66:8008
+Title11=(#11 - 655/950) RMF FM
+Length1=-1
+File12=http://188.165.12.67:8006
+Title12=(#12 - 658/950) RMF FM
+Length1=-1
+File13=http://91.121.125.91:8002
+Title13=(#13 - 670/950) RMF FM
+Length1=-1
+File14=http://91.121.124.91:8000
+Title14=(#14 - 714/950) RMF FM
+Length1=-1
+File15=http://87.98.222.167:8000
+Title15=(#15 - 779/950) RMF FM
+Length1=-1
+File16=http://87.98.223.167:8000
+Title16=(#16 - 869/950) RMF FM
+Length1=-1
+File17=http://188.165.12.67:8008
+Title17=(#17 - 887/950) RMF FM
+Length1=-1
+File18=http://87.98.222.167:8002
+Title18=(#18 - 896/950) RMF FM
+Length1=-1
+File19=http://87.98.223.167:8002
+Title19=(#19 - 901/950) RMF FM
+Length1=-1
+Version=2
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test-station_invalid.pls b/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test-station_invalid.pls
new file mode 100644 (file)
index 0000000..ae759ad
--- /dev/null
@@ -0,0 +1,3 @@
+[playlist]
+numberofentries=19
+Version=2
diff --git a/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test.asf b/qmafw-gst-subtitles-renderer/unittests/ut_PlaylistFileUtility/test.asf
new file mode 100644 (file)
index 0000000..3d20a2c
--- /dev/null
@@ -0,0 +1,3 @@
+[Reference]\r
+Ref1=http://195.134.228.177:443/data/ByContainer/Video/ASF/VC1/CIF/WMA/ASF_VC-1_CIF_29.7FPS_356Kbps_WMA8_44.1KHz_64Kbps_60sec(3Mb)_BBB.asf\r
+Ref2=http://195.134.228.177:443/data/ByContainer/Video/ASF/VC1/CIF/WMA/ASF_VC-1_CIF_29.7FPS_356Kbps_WMA8_44.1KHz_64Kbps_60sec(3Mb)_BBB.asf\r
diff --git a/qmafw-gst-subtitles-renderer/unittests/valgrind.xsl b/qmafw-gst-subtitles-renderer/unittests/valgrind.xsl
new file mode 100644 (file)
index 0000000..543816f
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+
+<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+xmlns:check="http://check.sourceforge.net/ns">
+
+<xsl:template match="/">
+  <h2>Executed Test Programs</h2>
+  <xsl:for-each select="valgrindresults/valgrindoutput">
+        <xsl:sort select="args/argv/exe"/>
+        <a href="#{generate-id()}"><xsl:value-of select="args/argv/exe"/></a><br/>
+  </xsl:for-each>
+
+  <h2>Errors</h2>
+  <xsl:for-each select="valgrindresults/valgrindoutput">
+        <xsl:sort select="args/argv/exe"/>
+        <a name="{generate-id()}"/>
+       <table border="1">
+       <tr bgcolor="#9acd32">
+               <th align="left"><xsl:value-of select="args/argv/exe"/></th>
+       </tr>
+       <xsl:for-each select="error">
+               <tr>
+               <td><a href="#{generate-id()}">
+                       <xsl:choose>
+                               <xsl:when test="kind='InvalidRead'">
+                                       <span style="color:#ff0000"><xsl:value-of select="what"/></span>
+                               </xsl:when>
+                               <xsl:when test="kind='InvalidWrite'">
+                                       <span style="color:#ff0000"><xsl:value-of select="what"/></span>
+                               </xsl:when>
+                               <xsl:when test="kind='InvalidFree'">
+                                       <span style="color:#ff0000"><xsl:value-of select="what"/></span>
+                               </xsl:when>
+                               <xsl:otherwise>
+                                       <xsl:value-of select="xwhat"/>
+                               </xsl:otherwise>
+                       </xsl:choose>
+               </a></td>
+               </tr>
+       </xsl:for-each>
+       </table>
+       <p/>
+  </xsl:for-each>
+  <h2>Stack frames</h2>
+  <xsl:for-each select="valgrindresults/valgrindoutput/error">
+    <a name="{generate-id()}"/>
+    <b>call stack (<xsl:value-of select="../args/argv/exe"/>): <span style="color:#ff0000"><xsl:value-of select="what"/></span></b>
+    <table border="1" >
+    <tr bgcolor="#9acd32">
+      <th align="left">function</th>
+      <th align="left">file</th>
+      <th align="left">line</th>
+      <th align="left">directory</th>
+    </tr>
+    <xsl:for-each select="stack[1]/frame">
+      <tr>
+        <td><xsl:value-of select="fn"/></td>
+        <td><xsl:value-of select="file"/></td>
+        <td><xsl:value-of select="line"/></td>
+        <td><xsl:value-of select="dir"/></td>
+      </tr>
+    </xsl:for-each>
+    <xsl:apply-templates select="auxwhat"/>
+    <xsl:for-each select="stack[2]/frame">
+      <tr>
+        <td><xsl:value-of select="fn"/></td>
+        <td><xsl:value-of select="file"/></td>
+        <td><xsl:value-of select="line"/></td>
+        <td><xsl:value-of select="dir"/></td>
+      </tr>      
+    </xsl:for-each>
+    </table>
+    <p/>
+  </xsl:for-each>
+</xsl:template>
+<xsl:template match="auxwhat">
+<span style="color:#ff0000"><xsl:value-of select="."/> (call stack):</span>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/qmafw-gst-subtitles-renderer/unittests/valgrind_report.sh b/qmafw-gst-subtitles-renderer/unittests/valgrind_report.sh
new file mode 100755 (executable)
index 0000000..9f71d00
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+valgrind_results_file=valgrind.results
+
+files=`find . -name "*.vg.xml"`
+
+rm -f $valgrind_results_file
+
+if [ -z "$files" ]
+then
+    echo "Valgrind results not generated."
+    exit 0
+fi
+
+echo '<?xml version="1.0"?>' > $valgrind_results_file
+echo '<valgrindresults>'  >> $valgrind_results_file
+for file in $files; do
+    grep -v \<\/\valgrindoutput\> $file | tail --quiet --lines=+2 >> $valgrind_results_file;
+    echo '</valgrindoutput>' >> $valgrind_results_file;
+done
+echo '</valgrindresults>' >> $valgrind_results_file