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
+