--- /dev/null
+<?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>
--- /dev/null
+[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
--- /dev/null
+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
+
--- /dev/null
+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.
--- /dev/null
+Copyright (C) 2009 Nokia Corporation. All rights reserved.
+
+Contact: Visa Smolander <visa.smolander@nokia.com>
--- /dev/null
+usr/lib/qmafw-plugin/*
+usr/share/dbus-1/services/*
+usr/share/contextkit/providers/*
+usr/share/qmafw/*
--- /dev/null
+#!/bin/sh
+
+set -e
+
+chmod 444 /usr/share/qmafw/mafw-gst-renderer-plugin.conf
--- /dev/null
+#!/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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+;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
--- /dev/null
+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
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+
+}
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+#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;
+}
--- /dev/null
+/*
+ * 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)
--- /dev/null
+#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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * This file is a part of MAFW
+ *
+ * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/pbutils/missing-plugins.h>
+#include <gst/base/gstbasesink.h>
+#include <context_provider.h>
+
+#include "mafw-gst-renderer-worker.h"
+#include "mafw-gst-renderer-utils.h"
+
+#define UNUSED(x) (void)(x)
+
+/* context provider DBus name must be the same as the .context file name without
+ * the .context suffix, service name in the .context file must be the same too */
+#define CONTEXT_PROVIDER_BUS_NAME "com.nokia.mafw.context_provider.libqmafw_gst_renderer"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING "Media.NowPlaying"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_TITLE "title"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_ALBUM "album"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_ARTIST "artist"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_GENRE "genre"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_RESOURCE "resource"
+#define CONTEXT_PROVIDER_KEY_NOWPLAYING_DURATION "duration"
+
+#define WORKER_ERROR g_quark_from_static_string("com.nokia.mafw.error.renderer")
+
+#define MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LAZY_TIMEOUT 4000
+#define MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_FAST_TIMEOUT 200
+#define MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LOOP_LIMIT 10
+#define MAFW_GST_MISSING_TYPE_DECODER "decoder"
+#define MAFW_GST_MISSING_TYPE_ENCODER "encoder"
+
+#define MAFW_TMP_URI_LEN 2048
+
+#define STREAM_TYPE_MMS "mms://"
+#define STREAM_TYPE_MMSH "mmsh://"
+#define MAFW_GST_MMSH_CONNECTION_SPEED "2000" /* kbit/s */
+#define MAFW_GST_MMSH_TCP_TIMEOUT "30000000" /* microseconds */
+
+/* struct needed when emitting renderer art/frames as image files */
+typedef struct {
+ MafwGstRendererWorker *worker;
+ gint metadata_key;
+ const gchar *filename;
+} SaveGraphicData;
+
+/* Forward declarations. */
+static void _do_play(MafwGstRendererWorker *worker);
+
+static void _do_seek(MafwGstRendererWorker *worker,
+ GstSeekType seek_type,
+ gint position,
+ gboolean key_frame_seek,
+ GError **error);
+
+static gboolean _set_value(GValue *v, GType type, gconstpointer value);
+
+static void _emit_metadatas(MafwGstRendererWorker *worker);
+
+static gboolean _current_metadata_add(MafwGstRendererWorker *worker,
+ const gint key,
+ GType type,
+ const gpointer value);
+
+static gpointer _set_context_map_value(gpointer map,
+ const gchar *tag,
+ const gchar *value);
+
+/*
+ * Is used to prevent a critical log from context fw in case of multiple initialisations.
+ * Common to all renderers in the process.
+ */
+static gboolean _context_fw_initialised = FALSE;
+
+/*
+ * Sends @error to MafwGstRenderer. Only call this from the glib main thread,
+ * or face the consequences. @err is free'd.
+ */
+static void _send_error(MafwGstRendererWorker *worker, GError *err)
+{
+ worker->is_error = TRUE;
+ if (worker->notify_error_handler)
+ {
+ /* remap a possible gst ecode to worker ecode */
+ err->code = remap_gst_error_code(err);
+ worker->notify_error_handler(worker, worker->owner, err);
+ }
+ g_error_free(err);
+}
+
+configuration* _create_default_configuration()
+{
+ configuration *config = g_malloc0(sizeof(configuration));
+ config->asink = g_strdup("pulsesink");
+ config->vsink = g_strdup("omapxvsink");
+ config->flags = 71;
+ config->buffer_time = 600000; /* microseconds */
+ config->latency_time = 100000; /* microseconds */
+ config->autoload_subtitles = TRUE;
+ config->subtitle_encoding = NULL;
+ config->subtitle_font = g_strdup("Sans Bold 18");
+
+ /* timers */
+ config->milliseconds_to_pause_frame = 700; /* milliseconds */
+ config->seconds_to_pause_to_ready = 3; /* seconds */
+
+ /* dhmmixer */
+ config->use_dhmmixer = TRUE;
+
+ config->mobile_surround_music.state = 0;
+ config->mobile_surround_music.room = 2;
+ config->mobile_surround_music.color = 2;
+ config->mobile_surround_video.state = 0;
+ config->mobile_surround_video.room = 2;
+ config->mobile_surround_video.color = 2;
+
+ return config;
+}
+
+void _free_configuration(configuration* config)
+{
+ g_free(config->asink);
+ g_free(config->vsink);
+
+ g_free(config);
+}
+
+/*
+ * Posts an @error on the gst bus. _async_bus_handler will then pick it up and
+ * forward to MafwGstRenderer. @err is free'd.
+ */
+static void _post_error(MafwGstRendererWorker *worker, GError *err)
+{
+ gst_bus_post(worker->bus,
+ gst_message_new_error(GST_OBJECT(worker->pipeline),
+ err,
+ NULL));
+ g_error_free(err);
+}
+
+static gboolean _set_value(GValue *v, GType type, gconstpointer value)
+{
+
+ gboolean ret = TRUE;
+
+ if (v && value)
+ {
+ memset(v, 0, sizeof(GValue));
+ g_value_init(v, type);
+
+ if (type == G_TYPE_STRING) {
+ g_value_set_string(v, (const gchar*)value);
+ }
+ else if (type == G_TYPE_INT) {
+ g_value_set_int(v, *(gint*)value);
+ }
+ else if (type == G_TYPE_UINT) {
+ g_value_set_uint(v, *(uint*)value);
+ }
+ else if (type == G_TYPE_DOUBLE) {
+ g_value_set_double(v, *(gdouble*)value);
+ }
+ else if (type == G_TYPE_BOOLEAN) {
+ g_value_set_boolean(v, *(gboolean*)value);
+ }
+ else if (type == G_TYPE_INT64) {
+ g_value_set_int64(v, *(gint64*)value);
+ }
+ else if (type == G_TYPE_FLOAT) {
+ g_value_set_float(v, *(gfloat*)value);
+ }
+ else if (type == G_TYPE_VALUE_ARRAY) {
+ g_value_copy((GValue*)value,v);
+ }
+ else {
+ g_warning("%s: unknown g_type", G_STRFUNC);
+ ret = FALSE;
+ }
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ return ret;
+
+}
+
+static void _emit_metadata(MafwGstRendererWorker *worker,
+ gint metadata_key,
+ GType type,
+ gconstpointer value)
+{
+
+ GValue v;
+
+ if (worker && worker->notify_metadata_handler &&
+ _set_value(&v, type, value))
+ {
+ GValueArray *array = g_value_array_new(0);
+ g_value_array_append(array, &v);
+ worker->notify_metadata_handler(worker,
+ worker->owner,
+ metadata_key,
+ G_TYPE_VALUE_ARRAY,
+ array);
+ g_value_array_free(array);
+ g_value_unset(&v);
+ }
+
+}
+
+static void _emit_property(MafwGstRendererWorker *worker,
+ gint property,
+ GType type,
+ gconstpointer value)
+{
+
+ GValue v;
+
+ if (worker && worker->notify_property_handler &&
+ _set_value(&v, type, value))
+ {
+ worker->notify_property_handler(worker, worker->owner, property, &v);
+ g_value_unset(&v);
+ }
+
+}
+
+static gchar *_init_tmp_file(void)
+{
+ gint fd;
+ gchar *path = NULL;
+
+ fd = g_file_open_tmp("mafw-gst-renderer-XXXXXX.picture", &path, NULL);
+ if (fd >= 0 )
+ {
+ close(fd);
+ }
+
+ return path;
+}
+
+static void _destroy_tmp_file(MafwGstRendererWorker *worker, guint index)
+{
+ g_unlink(worker->tmp_files_pool[index]);
+ g_free(worker->tmp_files_pool[index]);
+ worker->tmp_files_pool[index] = NULL;
+}
+
+static void _init_tmp_files_pool(MafwGstRendererWorker *worker)
+{
+ guint8 i;
+
+ worker->tmp_files_pool_index = 0;
+
+ for (i = 0; i < MAFW_GST_RENDERER_MAX_TMP_FILES; i++) {
+ worker->tmp_files_pool[i] = NULL;
+ }
+}
+
+static void _destroy_tmp_files_pool(MafwGstRendererWorker *worker)
+{
+ guint8 i;
+
+ for (i = 0; (i < MAFW_GST_RENDERER_MAX_TMP_FILES) &&
+ (worker->tmp_files_pool[i] != NULL); i++) {
+ g_unlink(worker->tmp_files_pool[i]);
+ g_free(worker->tmp_files_pool[i]);
+ }
+}
+
+static const gchar *_get_tmp_file_from_pool(MafwGstRendererWorker *worker)
+{
+ gchar *path = worker->tmp_files_pool[worker->tmp_files_pool_index];
+
+ if (path == NULL) {
+ path = _init_tmp_file();
+ worker->tmp_files_pool[worker->tmp_files_pool_index] = path;
+ }
+ else
+ {
+ _destroy_tmp_file(worker, worker->tmp_files_pool_index);
+ path = _init_tmp_file();
+ worker->tmp_files_pool[worker->tmp_files_pool_index] = path;
+ }
+
+ if (++(worker->tmp_files_pool_index) >= MAFW_GST_RENDERER_MAX_TMP_FILES) {
+ worker->tmp_files_pool_index = 0;
+ }
+
+ return path;
+}
+
+static void _emit_gst_buffer_as_graphic_file_cb(GError *error,
+ gpointer user_data)
+{
+ SaveGraphicData *sgd = user_data;
+
+ if (error == NULL) {
+ /* Add the info to the current metadata. */
+ _current_metadata_add(sgd->worker,
+ sgd->metadata_key,
+ G_TYPE_STRING,
+ (const gpointer)sgd->filename);
+
+ /* Emit the metadata. */
+ _emit_metadata(sgd->worker,
+ sgd->metadata_key,
+ G_TYPE_STRING,
+ sgd->filename);
+ }
+ else
+ {
+ g_warning("could not emit graphic file: %s", error->message);
+ }
+
+ g_free(sgd);
+}
+
+static void _emit_gst_buffer_as_graphic_file(MafwGstRendererWorker *worker,
+ GstBuffer *buffer,
+ const gint metadata_key)
+{
+ GstStructure *structure;
+ const gchar *mime = NULL;
+ GError *error = NULL;
+ SaveGraphicData *sgd;
+
+ g_return_if_fail((buffer != NULL) && GST_IS_BUFFER(buffer));
+
+ structure = gst_caps_get_structure(GST_BUFFER_CAPS(buffer), 0);
+ mime = gst_structure_get_name(structure);
+
+ /* video pause frame related branch */
+ if (g_str_has_prefix(mime, "video/x-raw")) {
+ const gchar *filename = _get_tmp_file_from_pool(worker);
+
+ if(worker->taking_screenshot)
+ {
+ worker->screenshot_handler(worker, worker->owner, NULL, NULL, TRUE);
+ }
+ worker->taking_screenshot = TRUE;
+ worker->screenshot_handler(worker, worker->owner, buffer, filename, FALSE);
+
+ /* gst image tag related branch */
+ } else if (g_str_has_prefix(mime, "image/")) {
+
+ sgd = g_new0(SaveGraphicData, 1);
+ sgd->worker = worker;
+ sgd->metadata_key = metadata_key;
+ sgd->filename = _get_tmp_file_from_pool(worker);
+
+ g_debug("dumping gst image %s directly to a file", mime);
+ g_file_set_contents(sgd->filename,
+ (const gchar*)GST_BUFFER_DATA(buffer),
+ GST_BUFFER_SIZE(buffer),
+ &error);
+ _emit_gst_buffer_as_graphic_file_cb(error, sgd);
+ if (error) {
+ g_error_free(error);
+ }
+ } else {
+ g_warning("Mime type not supported, will not create a thumbnail");
+ gst_buffer_unref(buffer);
+ }
+}
+
+static gboolean _go_to_gst_ready(gpointer user_data)
+{
+ g_debug("_go_to_gst_ready");
+ MafwGstRendererWorker *worker = user_data;
+
+ g_return_val_if_fail(worker->state == GST_STATE_PAUSED ||
+ worker->prerolling, FALSE);
+
+ worker->seek_position = mafw_gst_renderer_worker_get_position(worker);
+
+ g_debug("going to GST_STATE_READY");
+ gst_element_set_state(worker->pipeline, GST_STATE_READY);
+ worker->in_ready = TRUE;
+ return FALSE;
+}
+
+static void _add_ready_timeout(MafwGstRendererWorker *worker)
+{
+ if( worker->ready_timeout == 0 )
+ {
+ g_debug("Adding timeout to go to GST_STATE_READY");
+ worker->ready_timeout =
+ g_timeout_add_seconds(
+ worker->config->seconds_to_pause_to_ready,
+ _go_to_gst_ready,
+ worker);
+ }
+}
+
+static void _remove_ready_timeout(MafwGstRendererWorker *worker)
+{
+ if( worker->ready_timeout != 0 )
+ {
+ g_debug("removing timeout for READY");
+ g_source_remove(worker->ready_timeout);
+ worker->ready_timeout = 0;
+ }
+}
+
+static gboolean _take_pause_frame(gpointer user_data)
+{
+ MafwGstRendererWorker *worker = user_data;
+
+ if( worker->pause_frame_taken && worker->pause_frame_buffer )
+ {
+ gst_buffer_unref(worker->pause_frame_buffer);
+ worker->pause_frame_buffer = NULL;
+ return FALSE;
+ }
+
+ if (worker->pause_frame_buffer != NULL) {
+ worker->pause_frame_taken = TRUE;
+ _emit_gst_buffer_as_graphic_file(
+ worker,
+ worker->pause_frame_buffer,
+ WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI);
+ worker->pause_frame_buffer = NULL;
+ }
+ return FALSE;
+}
+
+static void _add_pause_frame_timeout(MafwGstRendererWorker *worker)
+{
+ if (worker->media.has_visual_content && worker->current_frame_on_pause && worker->seek_position == -1)
+ {
+ if (!worker->pause_frame_timeout)
+ {
+ GstBuffer *buffer = NULL;
+ g_object_get(worker->pipeline, "frame", &buffer, NULL);
+ if( buffer )
+ {
+ GstBuffer *copy = gst_buffer_copy(buffer);
+ gst_buffer_copy_metadata(copy, buffer, GST_BUFFER_COPY_ALL);
+ worker->pause_frame_buffer = copy;
+ gst_buffer_unref(buffer);
+
+ g_debug("Adding timeout to go to current frame capture");
+ worker->pause_frame_timeout =
+ g_timeout_add_full(
+ G_PRIORITY_DEFAULT,
+ worker->config->milliseconds_to_pause_frame,
+ _take_pause_frame,
+ worker, NULL);
+ }
+ else
+ {
+ g_warning("MafwGstRenderer Worker: Could not get buffer from pipeline! Maybe at EOS?");
+ }
+ }
+ } else {
+ g_debug("Not adding timeout to take pause frame.");
+ worker->pause_frame_timeout = 0;
+ }
+}
+
+static void _remove_pause_frame_timeout(MafwGstRendererWorker *worker)
+{
+ if (worker->pause_frame_timeout != 0) {
+ g_debug("removing timeout for pause frame!");
+ g_source_remove(worker->pause_frame_timeout);
+ worker->pause_frame_timeout = 0;
+ }
+
+ if(worker->taking_screenshot)
+ {
+ worker->screenshot_handler(worker, worker->owner, NULL, NULL, TRUE);
+ worker->taking_screenshot = FALSE;
+ }
+ else
+ {
+ /* in this case the buffer has not been given to the
+ * screenshot component to be processed */
+ if(worker->pause_frame_buffer)
+ {
+ gst_buffer_unref(worker->pause_frame_buffer);
+ worker->pause_frame_buffer = NULL;
+ }
+ }
+}
+
+static gboolean _emit_video_info(MafwGstRendererWorker *worker)
+{
+
+ _emit_metadata(worker,
+ WORKER_METADATA_KEY_RES_X,
+ G_TYPE_INT,
+ &worker->media.video_width);
+
+ _emit_metadata(worker,
+ WORKER_METADATA_KEY_RES_Y,
+ G_TYPE_INT,
+ &worker->media.video_height);
+
+ _emit_metadata(worker,
+ WORKER_METADATA_KEY_VIDEO_FRAMERATE,
+ G_TYPE_DOUBLE,
+ &worker->media.fps);
+
+ return FALSE;
+
+}
+
+/*
+ * Checks if the video details are supported. It also extracts other useful
+ * information (such as PAR and framerate) from the caps, if available. NOTE:
+ * this will be called from a different thread than glib's mainloop (when
+ * invoked via _stream_info_cb); don't call MafwGstRenderer directly.
+ *
+ * Returns: TRUE if video details are acceptable.
+ */
+static gboolean _handle_video_info(MafwGstRendererWorker *worker,
+ const GstStructure *structure)
+{
+ gint width, height;
+ gdouble fps;
+
+ width = height = 0;
+ gst_structure_get_int(structure, "width", &width);
+ gst_structure_get_int(structure, "height", &height);
+ g_debug("video size: %d x %d", width, height);
+ if (gst_structure_has_field(structure, "pixel-aspect-ratio"))
+ {
+ gst_structure_get_fraction(structure,
+ "pixel-aspect-ratio",
+ &worker->media.par_n,
+ &worker->media.par_d);
+ g_debug("video PAR: %d:%d", worker->media.par_n, worker->media.par_d);
+ width = width * worker->media.par_n / worker->media.par_d;
+ }
+
+ fps = 1.0;
+ if (gst_structure_has_field(structure, "framerate"))
+ {
+ gint fps_n, fps_d;
+
+ gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d);
+ if (fps_d > 0) {
+ fps = (gdouble)fps_n / (gdouble)fps_d;
+ }
+ g_debug("video fps: %f", fps);
+ }
+
+ worker->media.video_width = width;
+ worker->media.video_height = height;
+ worker->media.fps = fps;
+
+ _current_metadata_add(worker, WORKER_METADATA_KEY_RES_X, G_TYPE_INT,
+ (const gpointer)&width);
+ _current_metadata_add(worker, WORKER_METADATA_KEY_RES_Y, G_TYPE_INT,
+ (const gpointer)&height);
+ _current_metadata_add(worker, WORKER_METADATA_KEY_VIDEO_FRAMERATE,
+ G_TYPE_DOUBLE, (const gpointer)&fps);
+
+ /* Emit the metadata.*/
+ g_idle_add((GSourceFunc)_emit_video_info, worker);
+ return TRUE;
+}
+
+static void _parse_stream_info_item(MafwGstRendererWorker *worker, GObject *obj)
+{
+ GParamSpec *pspec;
+ GEnumValue *val;
+ gint type;
+
+ g_object_get(obj, "type", &type, NULL);
+ pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), "type");
+ if(!pspec)
+ return;
+ val = g_enum_get_value(G_PARAM_SPEC_ENUM(pspec)->enum_class, type);
+ if (!val)
+ return;
+ if (!g_ascii_strcasecmp(val->value_nick, "video") ||
+ !g_ascii_strcasecmp(val->value_name, "video"))
+ {
+ GstCaps *vcaps;
+ GstObject *object;
+
+ object = NULL;
+ g_object_get(obj, "object", &object, NULL);
+ vcaps = NULL;
+ if (object) {
+ vcaps = gst_pad_get_caps(GST_PAD_CAST(object));
+ } else {
+ g_object_get(obj, "caps", &vcaps, NULL);
+ gst_caps_ref(vcaps);
+ }
+ if (vcaps) {
+ if (gst_caps_is_fixed(vcaps))
+ {
+ _handle_video_info(worker, gst_caps_get_structure(vcaps, 0));
+ }
+ gst_caps_unref(vcaps);
+ }
+ }
+}
+
+/* It always returns FALSE, because it is used as an idle callback as well. */
+static gboolean _parse_stream_info(MafwGstRendererWorker *worker)
+{
+ GList *stream_info, *s;
+
+ stream_info = NULL;
+ if (g_object_class_find_property(G_OBJECT_GET_CLASS(worker->pipeline),
+ "stream-info"))
+ {
+ g_object_get(worker->pipeline, "stream-info", &stream_info, NULL);
+ }
+ for (s = stream_info; s; s = g_list_next(s))
+ _parse_stream_info_item(worker, G_OBJECT(s->data));
+ return FALSE;
+}
+
+static void mafw_gst_renderer_worker_apply_xid(MafwGstRendererWorker *worker)
+{
+ /* Set sink to render on the provided XID if we have do have
+ a XID a valid video sink and we are rendering video content */
+ if (worker->xid &&
+ worker->vsink &&
+ worker->media.has_visual_content)
+ {
+ g_debug ("Setting overlay, window id: %x", (gint) worker->xid);
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(worker->vsink), worker->xid);
+
+
+ /* Ask the gst to redraw the frame if we are paused */
+ /* TODO: in MTG this works only in non-fs -> fs way. */
+ if (worker->state == GST_STATE_PAUSED)
+ {
+ gst_x_overlay_expose(GST_X_OVERLAY(worker->vsink));
+ }
+ } else {
+ g_debug("Not setting overlay for window id: %x", (gint) worker->xid);
+ }
+}
+
+static void mafw_gst_renderer_worker_apply_render_rectangle(MafwGstRendererWorker *worker)
+{
+ /* Set sink to render on the provided XID if we have do have
+ a XID a valid video sink and we are rendering video content */
+ if (worker->xid &&
+ worker->vsink &&
+ worker->media.has_visual_content
+ &&
+ (worker->x_overlay_rectangle.x >= 0 &&
+ worker->x_overlay_rectangle.y >= 0 &&
+ worker->x_overlay_rectangle.width >= 0 &&
+ worker->x_overlay_rectangle.height >= 0) )
+ {
+ g_debug("Applying render rectangle: X:%d,Y:%d Width:%d, Height:%d",
+ worker->x_overlay_rectangle.x,
+ worker->x_overlay_rectangle.y,
+ worker->x_overlay_rectangle.width,
+ worker->x_overlay_rectangle.height);
+
+ gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(worker->vsink),
+ worker->x_overlay_rectangle.x,
+ worker->x_overlay_rectangle.y,
+ worker->x_overlay_rectangle.width,
+ worker->x_overlay_rectangle.height);
+ /* Ask the gst to redraw the frame if we are paused */
+ /* TODO: in MTG this works only in non-fs -> fs way. */
+ if (worker->state == GST_STATE_PAUSED)
+ {
+ gst_x_overlay_expose(GST_X_OVERLAY(worker->vsink));
+ }
+
+ } else {
+ g_debug("Not setting render rectangle for window id: %x", (gint) worker->xid);
+ }
+}
+
+/*
+ * GstBus synchronous message handler. NOTE that this handler is NOT invoked
+ * from the glib thread, so be careful what you do here.
+ */
+static GstBusSyncReply _sync_bus_handler(GstBus *bus,
+ GstMessage *msg,
+ MafwGstRendererWorker *worker)
+{
+
+ UNUSED(bus);
+
+ if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ELEMENT &&
+ gst_structure_has_name(msg->structure, "prepare-xwindow-id"))
+ {
+ g_debug("got prepare-xwindow-id");
+ worker->media.has_visual_content = TRUE;
+ set_dolby_video_property(worker, worker->config->mobile_surround_video.state);
+ set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.room, TRUE);
+ set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.color, FALSE);
+ /* The user has to preset the XID, we don't create windows by
+ * ourselves. */
+ if (!worker->xid || !worker->vsink) {
+ /* We must post an error message to the bus that will be picked up
+ * by _async_bus_handler. Calling the notification function
+ * directly from here (different thread) is not healthy. */
+ g_warning("No video window or video-sink set!");
+ _post_error(worker,
+ g_error_new_literal(WORKER_ERROR,
+ WORKER_ERROR_PLAYBACK,
+ "No video window XID or video-sink set"));
+ gst_message_unref (msg);
+ return GST_BUS_DROP;
+ } else {
+ g_debug ("Video window to use is: %x", (gint)worker->xid);
+ }
+
+ /* Instruct vsink to use the client-provided window */
+ mafw_gst_renderer_worker_apply_xid(worker);
+ /* Instruct vsink to use the required render rectangle */
+ mafw_gst_renderer_worker_apply_render_rectangle(worker);
+
+ /* Handle colorkey and autopaint */
+ mafw_gst_renderer_worker_set_autopaint(worker, worker->autopaint);
+ g_object_get(worker->vsink, "colorkey", &worker->colorkey, NULL);
+ /* Defer the signal emission to the thread running the mainloop. */
+ if (worker->colorkey != -1) {
+ gst_bus_post(worker->bus,
+ gst_message_new_application(
+ GST_OBJECT(worker->vsink),
+ gst_structure_empty_new("ckey")));
+ }
+ gst_message_unref (msg);
+ return GST_BUS_DROP;
+ }
+ /* do not unref message when returning PASS */
+ return GST_BUS_PASS;
+}
+
+static void _free_taglist_item(GstMessage *msg, gpointer data)
+{
+ UNUSED(data);
+
+ gst_message_unref(msg);
+}
+
+static void _free_taglist(MafwGstRendererWorker *worker)
+{
+ if (worker->tag_list != NULL)
+ {
+ g_ptr_array_foreach(worker->tag_list, (GFunc)_free_taglist_item, NULL);
+ g_ptr_array_free(worker->tag_list, TRUE);
+ worker->tag_list = NULL;
+ }
+}
+
+static gboolean _seconds_duration_equal(gint64 duration1, gint64 duration2)
+{
+ gint64 duration1_seconds, duration2_seconds;
+
+ duration1_seconds = duration1 / GST_SECOND;
+ duration2_seconds = duration2 / GST_SECOND;
+
+ return duration1_seconds == duration2_seconds;
+}
+
+static void _check_duration(MafwGstRendererWorker *worker, gint64 value)
+{
+ gboolean right_query = TRUE;
+
+ if (value == -1) {
+ GstFormat format = GST_FORMAT_TIME;
+ right_query =
+ gst_element_query_duration(worker->pipeline, &format, &value);
+ }
+
+ if (right_query && value > 0
+ && !_seconds_duration_equal(worker->media.length_nanos, value))
+ {
+ gint64 duration = (value + (GST_SECOND/2)) / GST_SECOND;
+
+ /* Add the duration to the current metadata. */
+ if( _current_metadata_add(worker,
+ WORKER_METADATA_KEY_DURATION,
+ G_TYPE_INT64,
+ (const gpointer)&duration) )
+ {
+ _emit_metadata(worker,
+ WORKER_METADATA_KEY_DURATION,
+ G_TYPE_INT64,
+ &duration);
+ }
+
+ /* Publish to context FW */
+ if( worker->context_nowplaying == NULL )
+ {
+ worker->context_nowplaying = context_provider_map_new();
+ }
+ context_provider_map_set_integer(worker->context_nowplaying,
+ CONTEXT_PROVIDER_KEY_NOWPLAYING_DURATION,
+ duration);
+ context_provider_set_map(CONTEXT_PROVIDER_KEY_NOWPLAYING,
+ worker->context_nowplaying, FALSE);
+ /* end of publishing to context FW */
+ }
+
+ if( right_query )
+ {
+ worker->media.length_nanos = value;
+ }
+
+ g_debug("media duration: %lld", worker->media.length_nanos);
+}
+
+static void _check_seekability(MafwGstRendererWorker *worker)
+{
+ SeekabilityType seekable = SEEKABILITY_UNKNOWN;
+ if (worker->media.length_nanos >= 0 )
+ {
+ g_debug("Quering GStreamer for seekability");
+ GstQuery *seek_query;
+ GstFormat format = GST_FORMAT_TIME;
+ /* Query the seekability of the stream */
+ seek_query = gst_query_new_seeking(format);
+ if (gst_element_query(worker->pipeline, seek_query)) {
+ gboolean renderer_seekable = FALSE;
+ gst_query_parse_seeking(seek_query,
+ NULL,
+ &renderer_seekable,
+ NULL, NULL);
+ g_debug("GStreamer seekability %d", renderer_seekable);
+ seekable = renderer_seekable ? SEEKABILITY_SEEKABLE : SEEKABILITY_NO_SEEKABLE;
+ }
+ else
+ {
+ g_debug("Could not query pipeline for seekability! Using old value!");
+ seekable = worker->media.seekable;
+ }
+ gst_query_unref(seek_query);
+ }
+ else if( worker->media.length_nanos == DURATION_INDEFINITE )
+ {
+ /* duration indefinite, "clearly" not seekable */
+ seekable = SEEKABILITY_NO_SEEKABLE;
+ }
+ else
+ {
+ /* otherwise we'll use last known/guessed value */
+ seekable = worker->media.seekable;
+ }
+
+ g_debug("media seekable: %d", seekable);
+
+ /* If the seekability is unknown it is set as false and sent. After that it is
+ sent only if it changes to true
+ */
+ if( (seekable == SEEKABILITY_UNKNOWN && worker->media.seekable == SEEKABILITY_UNKNOWN)
+ || seekable != worker->media.seekable )
+ {
+ if( seekable != SEEKABILITY_NO_SEEKABLE )
+ {
+ worker->media.seekable = SEEKABILITY_SEEKABLE;
+ }
+ else
+ {
+ worker->media.seekable = SEEKABILITY_NO_SEEKABLE;
+ }
+
+ gboolean is_seekable = (worker->media.seekable == SEEKABILITY_SEEKABLE);
+ _current_metadata_add(worker,
+ WORKER_METADATA_KEY_IS_SEEKABLE,
+ G_TYPE_BOOLEAN,
+ (const gpointer)&is_seekable);
+ _emit_metadata(worker,
+ WORKER_METADATA_KEY_IS_SEEKABLE,
+ G_TYPE_BOOLEAN,
+ &is_seekable);
+ }
+}
+
+static gboolean _query_duration_and_seekability_timeout(gpointer data)
+{
+ MafwGstRendererWorker *worker = data;
+
+ if (!worker->in_ready)
+ {
+ _check_duration(worker, -1);
+ worker->duration_seek_timeout_loop_count += 1;
+
+ /* for worker's internal logic let's put the indefinite duration if loop limit has been reached */
+ /* this affects the seekability resolution */
+ if( worker->duration_seek_timeout_loop_count >= MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LOOP_LIMIT
+ && worker->media.length_nanos == DURATION_UNQUERIED )
+ {
+ worker->media.length_nanos = DURATION_INDEFINITE;
+ }
+
+ _check_seekability(worker);
+
+ if( worker->media.length_nanos >= DURATION_INDEFINITE )
+ {
+ worker->duration_seek_timeout = 0;
+ /* we've got a valid duration value no need to ask for more */
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ g_warning("_query_duration_and_seekability_timeout: We are in ready state, duration and seekability not checked.");
+ return FALSE;
+ }
+}
+
+/*
+ * Resets the media information.
+ */
+static void _reset_media_info(MafwGstRendererWorker *worker)
+{
+ if (worker->media.location) {
+ g_free(worker->media.location);
+ worker->media.location = NULL;
+ }
+ worker->media.length_nanos = DURATION_UNQUERIED;
+ worker->media.has_visual_content = FALSE;
+ worker->media.seekable = SEEKABILITY_UNKNOWN;
+ worker->media.video_width = 0;
+ worker->media.video_height = 0;
+ worker->media.fps = 0.0;
+}
+
+static void _reset_pipeline_and_worker(MafwGstRendererWorker *worker)
+{
+
+ if (worker->pipeline) {
+ g_debug("destroying pipeline");
+ if (worker->async_bus_id) {
+ g_source_remove(worker->async_bus_id);
+ worker->async_bus_id = 0;
+ }
+ gst_element_set_state(worker->pipeline, GST_STATE_NULL);
+ if (worker->bus) {
+ gst_bus_set_sync_handler(worker->bus, NULL, NULL);
+ gst_object_unref(GST_OBJECT_CAST(worker->bus));
+ worker->bus = NULL;
+ }
+ gst_object_unref(worker->pipeline);
+ worker->pipeline = NULL;
+ }
+
+ worker->report_statechanges = TRUE;
+ worker->state = GST_STATE_NULL;
+ worker->prerolling = FALSE;
+ worker->is_live = FALSE;
+ worker->buffering = FALSE;
+ worker->is_stream = FALSE;
+ worker->is_error = FALSE;
+ worker->eos = FALSE;
+ worker->seek_position = -1;
+ worker->stay_paused = FALSE;
+ worker->playback_speed = 1;
+ worker->in_ready = FALSE;
+ _remove_ready_timeout(worker);
+ _remove_pause_frame_timeout(worker);
+ _free_taglist(worker);
+ if (worker->current_metadata) {
+ g_hash_table_destroy(worker->current_metadata);
+ worker->current_metadata = NULL;
+ }
+
+ if (worker->duration_seek_timeout != 0) {
+ g_source_remove(worker->duration_seek_timeout);
+ worker->duration_seek_timeout = 0;
+ }
+ worker->duration_seek_timeout_loop_count = 0;
+
+ _reset_media_info(worker);
+
+ /* removes all idle timeouts with this worker as data */
+ while(g_idle_remove_by_data(worker));
+}
+
+
+/*
+ * Called when the pipeline transitions into PAUSED state. It extracts more
+ * information from Gst.
+ */
+static void _finalize_startup(MafwGstRendererWorker *worker)
+{
+ /* Check video caps */
+ if (worker->media.has_visual_content && worker->vsink) {
+ GstPad *pad = GST_BASE_SINK_PAD(worker->vsink);
+ GstCaps *caps = GST_PAD_CAPS(pad);
+ if (caps && gst_caps_is_fixed(caps)) {
+ GstStructure *structure;
+ structure = gst_caps_get_structure(caps, 0);
+ if (!_handle_video_info(worker, structure))
+ return;
+ }
+ }
+
+ /* Something might have gone wrong at this point already. */
+ if (worker->is_error) {
+ g_debug("Error occured during preroll");
+ return;
+ }
+
+ /* Streaminfo might reveal the media to be unsupported. Therefore we
+ * need to check the error again. */
+ _parse_stream_info(worker);
+ if (worker->is_error) {
+ g_debug("Error occured. Leaving");
+ return;
+ }
+
+ /* Check duration and seekability */
+ if (worker->duration_seek_timeout != 0) {
+ g_source_remove(worker->duration_seek_timeout);
+ worker->duration_seek_timeout = 0;
+ }
+
+ _check_duration(worker, -1);
+ _check_seekability(worker);
+}
+
+static void _add_duration_seek_query_timeout(MafwGstRendererWorker *worker)
+{
+ if(worker->duration_seek_timeout == 0)
+ {
+ gint timeout = 0;
+ if( worker->duration_seek_timeout_loop_count >= MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LOOP_LIMIT
+ || worker->media.length_nanos >= DURATION_INDEFINITE )
+ {
+ /* this is just for verifying the duration later on if it was received in PAUSED state early on */
+ timeout = MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_LAZY_TIMEOUT;
+ }
+ else
+ {
+ timeout = MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_FAST_TIMEOUT;
+ }
+
+ worker->duration_seek_timeout = g_timeout_add(
+ timeout,
+ _query_duration_and_seekability_timeout,
+ worker);
+ }
+}
+
+static void _do_pause_postprocessing(MafwGstRendererWorker *worker)
+{
+ if (worker->notify_pause_handler) {
+ worker->notify_pause_handler(worker, worker->owner);
+ }
+
+ _add_pause_frame_timeout(worker);
+ _add_ready_timeout(worker);
+}
+
+static void _report_playing_state(MafwGstRendererWorker * worker)
+{
+ if (worker->report_statechanges && worker->notify_play_handler)
+ {
+ worker->notify_play_handler( worker,
+ worker->owner);
+ }
+}
+
+static void _handle_state_changed(GstMessage *msg,
+ MafwGstRendererWorker *worker)
+{
+ GstState newstate, oldstate;
+ GstStateChange statetrans;
+
+ gst_message_parse_state_changed(msg, &oldstate, &newstate, NULL);
+ statetrans = GST_STATE_TRANSITION(oldstate, newstate);
+ g_debug("State changed: %d: %d -> %d", worker->state, oldstate, newstate);
+
+ /* If the state is the same we do nothing, otherwise, we keep it */
+ if (worker->state == newstate)
+ {
+ /* This is used for saving correct pause frame after pauseAt.
+ * If we doing normal seek we dont want to save pause frame.
+ * We use gst_element_get_state to check if the state change is completed.
+ * If gst_element_get_state returns GST_STATE_CHANGE_SUCCESS we know that
+ * it's save to do pause_postprocessing */
+ if (newstate == GST_STATE_PAUSED && worker->stay_paused &&
+ gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS)
+ {
+ worker->seek_position = mafw_gst_renderer_seeker_process(worker->seeker);
+
+ /* has seeking ended successfully? */
+ if( worker->seek_position < 0 )
+ {
+ /* we do pause_postprocessing for pauseAt */
+ _do_pause_postprocessing(worker);
+ }
+ }
+
+ /* the EOS flag should only be cleared if it has been set and seeking has been done
+ * paused -> paused transition should only happen when seeking
+ */
+ if( newstate == GST_STATE_PAUSED && worker->eos )
+ {
+ worker->eos = FALSE;
+ }
+ return;
+ }
+
+ worker->state = newstate;
+
+ switch (statetrans) {
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ if (worker->in_ready) {
+ /* Woken up from READY, resume stream position and playback */
+
+ /*live sources can be sought only in PLAYING state*/
+ if( !worker->is_live ) {
+ _do_seek(worker,
+ GST_SEEK_TYPE_SET,
+ worker->seek_position,
+ FALSE,
+ NULL);
+ }
+
+ /* While buffering, we have to wait in PAUSED until we reach 100% before
+ * doing anything */
+ if (worker->buffering) {
+ return;
+ } else {
+ _do_play(worker);
+ }
+ } else if (worker->prerolling && worker->report_statechanges && !worker->buffering) {
+ /* PAUSED after pipeline has been constructed. We check caps,
+ * seek and duration and if staying in pause is needed, we
+ * perform operations for pausing, such as current frame on
+ * pause and signalling state change and adding the timeout to
+ * go to ready */
+ g_debug ("Prerolling done, finalizaing startup");
+ _finalize_startup(worker);
+
+ if (worker->stay_paused) {
+ /* then we can tell we're paused */
+ _do_pause_postprocessing(worker);
+ }
+
+ if( worker->seek_position > 0 )
+ {
+ g_debug("Immediate seek from READY state to: %d", worker->seek_position);
+ _do_seek(worker, GST_SEEK_TYPE_SET,
+ worker->seek_position, FALSE, NULL);
+
+ if(worker->vsink)
+ {
+ g_object_set(worker->vsink, "show-preroll-frame",
+ TRUE, NULL);
+ }
+
+ /* do_seek will set this to false, but we'll want to report state changes
+ when doing immediate seek from start */
+ worker->report_statechanges = TRUE;
+ }
+ worker->prerolling = FALSE;
+ _do_play(worker);
+ }
+ break;
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ /* When pausing we do the stuff, like signalling state, current
+ * frame on pause and timeout to go to ready */
+ if (worker->report_statechanges) {
+ _do_pause_postprocessing(worker);
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+
+ /*live sources can be sought only in PLAYING state
+ This seek should happen only after READY to PAUSED to PLAYING
+ transitions
+ */
+ if( worker->report_statechanges
+ && worker->seek_position > -1
+ && worker->is_live )
+ {
+ g_debug("Seeking live source in PLAYING state!");
+ _do_seek(worker,
+ GST_SEEK_TYPE_SET,
+ worker->seek_position,
+ FALSE,
+ NULL);
+ /* this has to be set as do_seek sets statechanges to FALSE
+ but we still want to inform that we're in PLAYING state */
+ worker->report_statechanges = TRUE;
+ /* seek position needs to be reset here for a live stream */
+ worker->seek_position = -1;
+ }
+
+ /* Because live streams are sought in PLAYING state, we reset
+ seek_position after all state transitions are completed. Normal
+ streams resetting seek_position here is OK. */
+ if(worker->report_statechanges == FALSE || !worker->is_live)
+ {
+ /* if seek was called, at this point it is really ended */
+ worker->seek_position = mafw_gst_renderer_seeker_process(worker->seeker);
+ }
+
+ /* Signal state change if needed */
+ _report_playing_state(worker);
+
+ /* Prevent blanking if we are playing video */
+ if (worker->media.has_visual_content &&
+ worker->blanking__control_handler)
+ {
+ worker->blanking__control_handler(worker, worker->owner, TRUE);
+ }
+
+ /* Back to playing no longer in_ready (if ever was) */
+ worker->in_ready = FALSE;
+
+ /* context framework adaptation starts */
+ worker->context_nowplaying =
+ _set_context_map_value(worker->context_nowplaying,
+ GST_TAG_LOCATION,
+ worker->media.location);
+ context_provider_set_map(CONTEXT_PROVIDER_KEY_NOWPLAYING,
+ worker->context_nowplaying, FALSE);
+ /* context framework adaptation ends */
+
+ /* Emit metadata. We wait until we reach the playing state because
+ * this speeds up playback start time */
+ _emit_metadatas(worker);
+
+ /* in any case the duration is verified, it may change with VBR media */
+ _add_duration_seek_query_timeout(worker);
+
+ /* We've reached playing state, state changes are not reported
+ * unless explicitly requested (e.g. by PAUSE request) seeking
+ * in PLAYING does not cause state change reports
+ */
+ worker->report_statechanges = FALSE;
+
+ /* Delayed pause e.g. because of seek */
+ if (worker->stay_paused) {
+ mafw_gst_renderer_worker_pause(worker);
+ }
+
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ /* If we went to READY, we free the taglist and * deassign the
+ * timout it */
+ if (worker->in_ready) {
+ g_debug("changed to GST_STATE_READY");
+ worker->ready_timeout = 0;
+ _free_taglist(worker);
+
+ if( worker->notify_ready_state_handler )
+ {
+ worker->notify_ready_state_handler(worker, worker->owner);
+ }
+ }
+ break;
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if(g_str_has_prefix(worker->media.location, STREAM_TYPE_MMSH) ||
+ g_str_has_prefix(worker->media.location, STREAM_TYPE_MMS))
+ {
+ GstElement *source = NULL;
+ g_object_get(worker->pipeline, "source", &source, NULL);
+ if(source)
+ {
+ gst_util_set_object_arg(G_OBJECT(source), "tcp-timeout", MAFW_GST_MMSH_TCP_TIMEOUT);
+ gst_object_unref(source);
+ }
+ else
+ g_warning("Failed to get source element from pipeline");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void _handle_duration(MafwGstRendererWorker *worker)
+{
+ /* if we've got ongoing query timeout ignore this and in any case do it only in PAUSE/PLAYING */
+ if( worker->duration_seek_timeout == 0
+ && ( worker->state == GST_STATE_PAUSED || worker->state == GST_STATE_PLAYING) )
+ {
+ /* We want to check this quickly but not immediately */
+ g_timeout_add_full(G_PRIORITY_DEFAULT,
+ MAFW_GST_RENDERER_WORKER_DURATION_AND_SEEKABILITY_FAST_TIMEOUT,
+ _query_duration_and_seekability_timeout,
+ worker,
+ NULL);
+ }
+}
+
+static void _emit_renderer_art(MafwGstRendererWorker *worker,
+ const GstTagList *list)
+{
+ GstBuffer *buffer = NULL;
+ const GValue *value = NULL;
+
+ g_return_if_fail(gst_tag_list_get_tag_size(list, GST_TAG_IMAGE) > 0);
+
+ value = gst_tag_list_get_value_index(list, GST_TAG_IMAGE, 0);
+
+ g_return_if_fail((value != NULL) && G_VALUE_HOLDS(value, GST_TYPE_BUFFER));
+
+ buffer = g_value_peek_pointer(value);
+
+ g_return_if_fail((buffer != NULL) && GST_IS_BUFFER(buffer));
+
+ _emit_gst_buffer_as_graphic_file(worker,
+ buffer,
+ WORKER_METADATA_KEY_RENDERER_ART_URI);
+}
+
+static void value_dtor(gpointer value)
+{
+
+ if (G_IS_VALUE(value)) {
+ g_value_unset(value);
+ g_free(value);
+ } else {
+ g_value_array_free(value);
+ }
+
+}
+
+static gboolean _current_metadata_add(MafwGstRendererWorker *worker,
+ const gint key,
+ GType type,
+ const gpointer value)
+{
+ GValue *new_gval;
+ gboolean was_updated = FALSE;
+
+ if( value == NULL )
+ {
+ g_warning("Null value for metadata was tried to be set!");
+ return was_updated;
+ }
+
+ if (!worker->current_metadata) {
+ worker->current_metadata = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal,
+ NULL,
+ value_dtor);
+ }
+
+ if (type == G_TYPE_VALUE_ARRAY) {
+ GValueArray *values = (GValueArray *) value;
+
+ if (values->n_values == 1) {
+ GValue *gval = g_value_array_get_nth(values, 0);
+ new_gval = g_new0(GValue, 1);
+ g_value_init(new_gval, G_VALUE_TYPE(gval));
+ g_value_copy(gval, new_gval);
+
+ GValue *existing = (GValue*)g_hash_table_lookup(worker->current_metadata, (gpointer)key);
+ if(!existing || (GST_VALUE_EQUAL != gst_value_compare(existing, new_gval)) )
+ {
+ was_updated = TRUE;
+ }
+ g_hash_table_insert(worker->current_metadata,
+ (gpointer)key,
+ new_gval);
+ } else {
+ GValueArray *new_gvalues = g_value_array_copy(values);
+
+ GValueArray *existing = (GValueArray*)g_hash_table_lookup(worker->current_metadata, (gpointer)key);
+
+ if( existing
+ && new_gvalues->n_values == existing->n_values )
+ {
+ guint size = new_gvalues->n_values;
+
+ guint i = 0;
+ for( ; i < size; ++i )
+ {
+ GValue *newVal = g_value_array_get_nth(new_gvalues, i);
+ GValue *existingVal = g_value_array_get_nth(existing, i);
+ if( GST_VALUE_EQUAL != gst_value_compare(newVal, existingVal) )
+ {
+ was_updated = TRUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ was_updated = TRUE;
+ }
+
+ g_hash_table_insert(worker->current_metadata,
+ (gpointer)key,
+ new_gvalues);
+ }
+
+ return was_updated;
+ }
+
+ new_gval = g_new0(GValue, 1);
+
+ if (_set_value(new_gval, type, value) == FALSE)
+ {
+ g_warning("Metadata type: %i is not being handled", type);
+ return was_updated;
+ }
+
+ GValue *existing = (GValue*)g_hash_table_lookup(worker->current_metadata, (gpointer)key);
+ if(!existing || (GST_VALUE_EQUAL != gst_value_compare(existing, new_gval)) )
+ {
+ was_updated = TRUE;
+ }
+ g_hash_table_insert(worker->current_metadata, (gpointer)key, new_gval);
+
+ return was_updated;
+
+}
+
+static GHashTable* _build_tagmap(void)
+{
+ GHashTable *hash_table = NULL;
+
+ hash_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_TITLE),
+ (gpointer)WORKER_METADATA_KEY_TITLE);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_ARTIST),
+ (gpointer)WORKER_METADATA_KEY_ARTIST);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_AUDIO_CODEC),
+ (gpointer)WORKER_METADATA_KEY_AUDIO_CODEC);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_VIDEO_CODEC),
+ (gpointer)WORKER_METADATA_KEY_VIDEO_CODEC);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_BITRATE),
+ (gpointer)WORKER_METADATA_KEY_BITRATE);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_LANGUAGE_CODE),
+ (gpointer)WORKER_METADATA_KEY_ENCODING);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_ALBUM),
+ (gpointer)WORKER_METADATA_KEY_ALBUM);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_GENRE),
+ (gpointer)WORKER_METADATA_KEY_GENRE);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_TRACK_NUMBER),
+ (gpointer)WORKER_METADATA_KEY_TRACK);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_ORGANIZATION),
+ (gpointer)WORKER_METADATA_KEY_ORGANIZATION);
+ g_hash_table_insert(hash_table, g_strdup(GST_TAG_IMAGE),
+ (gpointer)WORKER_METADATA_KEY_RENDERER_ART_URI);
+
+ return hash_table;
+}
+
+/*
+ * Sets values to given context framework map, allocates it when map is NULL.
+ */
+gpointer _set_context_map_value(gpointer map,
+ const gchar *tag,
+ const gchar *value)
+{
+
+ if (map == NULL)
+ {
+ map = context_provider_map_new();
+ }
+
+ if (g_str_equal(tag, GST_TAG_LOCATION))
+ {
+ context_provider_map_set_string(map,
+ CONTEXT_PROVIDER_KEY_NOWPLAYING_RESOURCE,
+ value);
+ }
+ else if (g_str_equal(tag, GST_TAG_TITLE))
+ {
+ context_provider_map_set_string(map,
+ CONTEXT_PROVIDER_KEY_NOWPLAYING_TITLE,
+ value);
+ }
+ else if (g_str_equal(tag, GST_TAG_ARTIST))
+ {
+ context_provider_map_set_string(map,
+ CONTEXT_PROVIDER_KEY_NOWPLAYING_ARTIST,
+ value);
+ }
+ else if (g_str_equal(tag, GST_TAG_ALBUM))
+ {
+ context_provider_map_set_string(map,
+ CONTEXT_PROVIDER_KEY_NOWPLAYING_ALBUM,
+ value);
+ }
+ else if (g_str_equal(tag, GST_TAG_GENRE))
+ {
+ context_provider_map_set_string(map,
+ CONTEXT_PROVIDER_KEY_NOWPLAYING_GENRE,
+ value);
+ }
+
+ return map;
+
+}
+
+/*
+ * Emits metadata-changed signals for gst tags.
+ */
+static void _emit_tag(const GstTagList *list,
+ const gchar *tag,
+ MafwGstRendererWorker *worker)
+{
+ /* Mapping between Gst <-> MAFW metadata tags
+ * NOTE: This assumes that GTypes matches between GST and MAFW. */
+ static GHashTable *tagmap = NULL;
+ gint i, count;
+ gint mafwtag;
+ GType type;
+ GValueArray *values;
+
+ if (tagmap == NULL) {
+ tagmap = _build_tagmap();
+ }
+
+ g_debug("tag: '%s' (type: %s)", tag, g_type_name(gst_tag_get_type(tag)));
+ /* Is there a mapping for this tag? */
+ mafwtag = (gint)g_hash_table_lookup(tagmap, tag);
+ if (!mafwtag)
+ return;
+
+ if (mafwtag == WORKER_METADATA_KEY_RENDERER_ART_URI) {
+ _emit_renderer_art(worker, list);
+ return;
+ }
+
+ /* Build a value array of this tag. We need to make sure that strings
+ * are UTF-8. GstTagList API says that the value is always UTF8, but it
+ * looks like the ID3 demuxer still might sometimes produce non-UTF-8
+ * strings. */
+ count = gst_tag_list_get_tag_size(list, tag);
+
+ type = gst_tag_get_type(tag);
+ values = g_value_array_new(count);
+ for (i = 0; i < count; ++i) {
+ GValue *v = (GValue *)
+ gst_tag_list_get_value_index(list, tag, i);
+ if (type == G_TYPE_STRING) {
+ gchar *orig, *utf8;
+
+ gboolean tagExists = gst_tag_list_get_string_index(list, tag, i, &orig);
+ UNUSED(tagExists); //TODO what if tag does not exists?
+ if (convert_utf8(orig, &utf8)) {
+ GValue utf8gval;
+ memset(&utf8gval, 0, sizeof(utf8gval));
+
+ g_value_init(&utf8gval, G_TYPE_STRING);
+ g_value_take_string(&utf8gval, utf8);
+ g_value_array_append(values, &utf8gval);
+ g_value_unset(&utf8gval);
+ }
+ /* context framework adaptation starts */
+ worker->context_nowplaying =
+ _set_context_map_value(worker->context_nowplaying,
+ tag,
+ orig);
+ /* context framework adaptation ends */
+ g_free(orig);
+ } else if (type == G_TYPE_UINT) {
+ GValue intgval;
+ memset(&intgval, 0, sizeof(intgval));
+
+ g_value_init(&intgval, G_TYPE_INT);
+ g_value_transform(v, &intgval);
+ g_value_array_append(values, &intgval);
+ g_value_unset(&intgval);
+ } else {
+ g_value_array_append(values, v);
+ }
+ }
+
+ /* context framework adaptation starts */
+ context_provider_set_map(CONTEXT_PROVIDER_KEY_NOWPLAYING,
+ worker->context_nowplaying, FALSE);
+ /* context framework adaptation ends */
+
+ /* Add the info to the current metadata. */
+ gboolean changed = _current_metadata_add(worker,
+ mafwtag,
+ G_TYPE_VALUE_ARRAY,
+ (const gpointer) values);
+
+ /* Emit the metadata. */
+ if (changed && worker->notify_metadata_handler)
+ {
+ worker->notify_metadata_handler(worker,
+ worker->owner,
+ mafwtag,
+ G_TYPE_VALUE_ARRAY,
+ values);
+ }
+
+ g_value_array_free(values);
+}
+
+/**
+ * Collect tag-messages, parse it later, when playing is ongoing
+ */
+static void _handle_tag(MafwGstRendererWorker *worker, GstMessage *msg)
+{
+ /* Do not emit metadata until we get to PLAYING state to speed up playback
+ * start */
+ if (worker->tag_list == NULL)
+ worker->tag_list = g_ptr_array_new();
+ g_ptr_array_add(worker->tag_list, gst_message_ref(msg));
+
+ /* Some tags come in playing state, so in this case we have to emit them
+ * right away (example: radio stations) */
+ if (worker->state == GST_STATE_PLAYING) {
+ _emit_metadatas(worker);
+ }
+}
+
+/**
+ * Parses the list of tag-messages
+ */
+static void _parse_tagmsg(GstMessage *msg, MafwGstRendererWorker *worker)
+{
+ GstTagList *new_tags;
+
+ gst_message_parse_tag(msg, &new_tags);
+ gst_tag_list_foreach(new_tags, (gpointer)_emit_tag, worker);
+ gst_tag_list_free(new_tags);
+ gst_message_unref(msg);
+}
+
+/**
+ * Parses the collected tag messages, and emits the metadatas
+ */
+static void _emit_metadatas(MafwGstRendererWorker *worker)
+{
+ if (worker->tag_list != NULL)
+ {
+ g_ptr_array_foreach(worker->tag_list, (GFunc)_parse_tagmsg, worker);
+ g_ptr_array_free(worker->tag_list, TRUE);
+ worker->tag_list = NULL;
+ }
+}
+
+static void _handle_buffering(MafwGstRendererWorker *worker, GstMessage *msg)
+{
+ /* We set smaller buffer for mms streams */
+ if((g_str_has_prefix(worker->media.location, STREAM_TYPE_MMSH) || g_str_has_prefix(worker->media.location, STREAM_TYPE_MMS))
+ && worker->state != GST_STATE_PLAYING && !worker->buffering)
+ {
+ if(worker->queue)
+ {
+ g_object_set(worker->queue, "high-percent", 30, NULL);
+ }
+ else
+ {
+ g_warning("Queue2 element doesn't exist!");
+ }
+ }
+
+ /* We can ignore buffering messages when we are in READY state or when going to it */
+ if(worker->state == GST_STATE_READY || worker->ready_timeout != 0 )
+ {
+ worker->buffering = TRUE;
+ return;
+ }
+
+ gint percent;
+ gst_message_parse_buffering(msg, &percent);
+ g_debug("buffering: %d", percent);
+
+ /* No state management needed for live pipelines */
+ if (!worker->is_live) {
+ worker->buffering = TRUE;
+ if (percent < 100 && worker->state == GST_STATE_PLAYING) {
+ /* If we need to buffer more, we set larger buffer */
+ if(g_str_has_prefix(worker->media.location, STREAM_TYPE_MMSH) || g_str_has_prefix(worker->media.location, STREAM_TYPE_MMS))
+ {
+ if(worker->queue)
+ {
+ g_object_set(worker->queue, "high-percent", 100, NULL);
+ }
+ else
+ {
+ g_warning("Queue2 element doesn't exist!");
+ }
+ }
+ g_debug("setting pipeline to PAUSED not to wolf the buffer down");
+
+ //if there's no requested state transitions i.e. resume/pause let's keep this quiet
+ if( gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS )
+ {
+ worker->report_statechanges = FALSE;
+ }
+
+ /* We can't call _pause() here, since it sets the
+ * "report_statechanges" to TRUE. We don't want that, application
+ * doesn't need to know that internally the state changed to PAUSED.
+ */
+ gst_element_set_state(worker->pipeline, GST_STATE_PAUSED);
+ }
+
+ if (percent >= 100) {
+ /* On buffering we go to PAUSED, so here we move back to PLAYING */
+ worker->buffering = FALSE;
+ if (worker->state == GST_STATE_PAUSED)
+ {
+ /* If buffering more than once, do this only the first time we
+ * are done with buffering */
+ if (worker->prerolling)
+ {
+ g_debug("buffering concluded during prerolling");
+ _finalize_startup(worker);
+ _do_play(worker);
+ /* Send the paused notification */
+ if (worker->stay_paused &&
+ worker->notify_pause_handler)
+ {
+ worker->notify_pause_handler(worker, worker->owner);
+ }
+ worker->prerolling = FALSE;
+ }
+ /* if eos has been reached no automatic playing should be done
+ only on resume request e.g. eos reached -> seek requested => stays paused after seek&buffering completed */
+ else if (!worker->stay_paused && !worker->eos)
+ {
+ g_debug("buffering concluded, setting "
+ "pipeline to PLAYING again");
+ worker->report_statechanges = TRUE;
+ gst_element_set_state(worker->pipeline, GST_STATE_PLAYING);
+ }
+ }
+ /* if there's no pending state changes and we're really in PLAYING state... */
+ else if (gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS
+ && worker->state == GST_STATE_PLAYING)
+ {
+ g_debug("buffering concluded, signalling state change");
+ /* In this case we got a PLAY command while buffering, likely
+ * because it was issued before we got the first buffering
+ * signal. The UI should not do this, but if it does, we have
+ * to signal that we have executed the state change, since in
+ * _handle_state_changed we do not do anything if we are
+ * buffering */
+ if (worker->report_statechanges &&
+ worker->notify_play_handler) {
+ worker->notify_play_handler(worker, worker->owner);
+ }
+ _add_duration_seek_query_timeout(worker);
+
+ }
+ /* has somebody requested pause transition? */
+ else if( !worker->stay_paused )
+ {
+ /* we're in PLAYING but pending for paused state change.
+ Let's request new state change to override the pause */
+ gst_element_set_state(worker->pipeline, GST_STATE_PLAYING);
+ }
+ }
+ }
+
+ /* Send buffer percentage */
+ if (worker->notify_buffer_status_handler)
+ worker->notify_buffer_status_handler(worker, worker->owner, percent);
+}
+
+static void _handle_element_msg(MafwGstRendererWorker *worker, GstMessage *msg)
+{
+ /* Only HelixBin sends "resolution" messages. */
+ if (gst_structure_has_name(msg->structure, "resolution") &&
+ _handle_video_info(worker, msg->structure))
+ {
+ worker->media.has_visual_content = TRUE;
+ set_dolby_video_property(worker, worker->config->mobile_surround_video.state);
+ set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.room, TRUE);
+ set_dolby_video_sound_property(worker, worker->config->mobile_surround_video.color, FALSE);
+ }
+ /* We do RTSP redirect when we try to play .sdp streams */
+ else if(gst_structure_has_name(msg->structure, "redirect"))
+ {
+ /* "new-location" contains the rtsp uri what we are going to play */
+ mafw_gst_renderer_worker_play(worker, gst_structure_get_string(msg->structure, "new-location"));
+ }
+
+}
+
+static GError * _get_specific_missing_plugin_error(GstMessage *msg)
+{
+ const GstStructure *gst_struct;
+ const gchar *type;
+
+ GError *error;
+ gchar *desc;
+
+ desc = gst_missing_plugin_message_get_description(msg);
+
+ gst_struct = gst_message_get_structure(msg);
+ type = gst_structure_get_string(gst_struct, "type");
+
+ if ((type) && ((strcmp(type, MAFW_GST_MISSING_TYPE_DECODER) == 0) ||
+ (strcmp(type, MAFW_GST_MISSING_TYPE_ENCODER) == 0))) {
+
+ /* Missing codec error. */
+ const GValue *val;
+ const GstCaps *caps;
+ GstStructure *caps_struct;
+ const gchar *mime;
+
+ val = gst_structure_get_value(gst_struct, "detail");
+ caps = gst_value_get_caps(val);
+ caps_struct = gst_caps_get_structure(caps, 0);
+ mime = gst_structure_get_name(caps_struct);
+
+ if (g_strrstr(mime, "video")) {
+ error = g_error_new_literal(WORKER_ERROR,
+ WORKER_ERROR_VIDEO_CODEC_NOT_FOUND,
+ desc);
+ } else if (g_strrstr(mime, "audio")) {
+ error = g_error_new_literal(WORKER_ERROR,
+ WORKER_ERROR_AUDIO_CODEC_NOT_FOUND,
+ desc);
+ } else {
+ error = g_error_new_literal(WORKER_ERROR,
+ WORKER_ERROR_CODEC_NOT_FOUND,
+ desc);
+ }
+ } else {
+ /* Unsupported type error. */
+ error = g_error_new(WORKER_ERROR,
+ WORKER_ERROR_UNSUPPORTED_TYPE,
+ "missing plugin: %s", desc);
+ }
+
+ g_free(desc);
+
+ return error;
+}
+
+/*
+ * Asynchronous message handler. It gets removed from if it returns FALSE.
+ */
+static gboolean _async_bus_handler(GstBus *bus,
+ GstMessage *msg,
+ MafwGstRendererWorker *worker)
+{
+
+ UNUSED(bus);
+
+ /* No need to handle message if error has already occured. */
+ if (worker->is_error)
+ return TRUE;
+
+ /* Handle missing-plugin (element) messages separately, relaying more
+ * details. */
+ if (gst_is_missing_plugin_message(msg)) {
+ GError *err = _get_specific_missing_plugin_error(msg);
+ /* FIXME?: for some reason, calling the error handler directly
+ * (_send_error) causes problems. On the other hand, turning
+ * the error into a new GstMessage and letting the next
+ * iteration handle it seems to work. */
+ _post_error(worker, err);
+ return TRUE;
+ }
+ switch (GST_MESSAGE_TYPE(msg)) {
+ case GST_MESSAGE_ERROR:
+ if (!worker->is_error) {
+ gchar *debug;
+ GError *err;
+ debug = NULL;
+ gst_message_parse_error(msg, &err, &debug);
+ g_debug("gst error: domain = %s, code = %d, "
+ "message = '%s', debug = '%s'",
+ g_quark_to_string(err->domain), err->code, err->message, debug);
+ if (debug)
+ {
+ g_free(debug);
+ }
+ //decodebin2 uses the error only to report text files
+ if (err->code == GST_STREAM_ERROR_WRONG_TYPE && g_str_has_prefix(GST_MESSAGE_SRC_NAME(msg), "decodebin2"))
+ {
+ err->code = WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE;
+ }
+
+ _send_error(worker, err);
+ }
+ break;
+ case GST_MESSAGE_EOS:
+ if (!worker->is_error) {
+ worker->eos = TRUE;
+ worker->seek_position = -1;
+ if (worker->notify_eos_handler)
+ {
+ worker->notify_eos_handler(worker, worker->owner);
+ }
+ }
+ break;
+ case GST_MESSAGE_TAG:
+ _handle_tag(worker, msg);
+ break;
+ case GST_MESSAGE_BUFFERING:
+ _handle_buffering(worker, msg);
+ break;
+ case GST_MESSAGE_DURATION:
+ /* in ready state we might not get correct seekability info */
+ if (!worker->in_ready)
+ {
+ _handle_duration(worker);
+ }
+ break;
+ case GST_MESSAGE_ELEMENT:
+ _handle_element_msg(worker, msg);
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
+ if ((GstElement *)GST_MESSAGE_SRC(msg) == worker->pipeline)
+ _handle_state_changed(msg, worker);
+ break;
+ case GST_MESSAGE_APPLICATION:
+ if (gst_structure_has_name(gst_message_get_structure(msg), "ckey"))
+ {
+ _emit_property(worker,
+ WORKER_PROPERTY_COLORKEY,
+ G_TYPE_INT,
+ &worker->colorkey);
+ }
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+/* NOTE this function will possibly be called from a different thread than the
+ * glib main thread. */
+static void _stream_info_cb(GstObject *pipeline, GParamSpec *unused,
+ MafwGstRendererWorker *worker)
+{
+ UNUSED(pipeline);
+ UNUSED(unused);
+
+ g_debug("stream-info changed");
+ _parse_stream_info(worker);
+}
+
+static void _element_added_cb(GstBin *bin, GstElement *element,
+ MafwGstRendererWorker *worker)
+{
+ UNUSED(bin);
+ gchar *element_name;
+
+ element_name = gst_element_get_name(element);
+ if(g_str_has_prefix(element_name, "uridecodebin") ||
+ g_str_has_prefix(element_name, "decodebin2"))
+ {
+ g_signal_connect(element, "element-added",
+ G_CALLBACK(_element_added_cb), worker);
+ }
+ else if(g_str_has_prefix(element_name, "sdpdemux"))
+ {
+ g_object_set(element, "redirect", FALSE, NULL);
+ }
+ else if(g_str_has_prefix(element_name, "queue2"))
+ {
+ worker->queue = element;
+ }
+ g_free(element_name);
+}
+
+/*
+ * Start to play the media
+ */
+static void _start_play(MafwGstRendererWorker *worker)
+{
+ GstStateChangeReturn state_change_info;
+ worker->stay_paused = FALSE;
+ char *autoload_sub = NULL;
+
+ g_assert(worker->pipeline);
+ g_object_set(G_OBJECT(worker->pipeline),
+ "uri", worker->media.location, NULL);
+
+ if (worker->config->autoload_subtitles) {
+ autoload_sub = uri_get_subtitle_uri(worker->media.location);
+ if (autoload_sub) {
+ g_debug("SUBURI: %s", autoload_sub);
+ g_object_set(G_OBJECT(worker->pipeline),
+ "suburi", autoload_sub,
+ "subtitle-font-desc", worker->config->subtitle_font,
+ "subtitle-encoding", worker->config->subtitle_encoding,
+ NULL);
+
+ gst_element_set_state(worker->pipeline, GST_STATE_READY);
+ g_free(autoload_sub);
+ }
+ } else {
+ g_object_set(G_OBJECT(worker->pipeline), "suburi", NULL, NULL);
+ }
+
+ g_debug("URI: %s", worker->media.location);
+ g_debug("setting pipeline to PAUSED");
+
+ worker->report_statechanges = TRUE;
+ state_change_info = gst_element_set_state(worker->pipeline,
+ GST_STATE_PAUSED);
+ if (state_change_info == GST_STATE_CHANGE_NO_PREROLL) {
+ /* FIXME: for live sources we may have to handle buffering and
+ * prerolling differently */
+ g_debug ("Source is live!");
+ worker->is_live = TRUE;
+ }
+ worker->prerolling = TRUE;
+
+ worker->is_stream = uri_is_stream(worker->media.location);
+
+}
+
+/*
+ * Constructs gst pipeline
+ *
+ * FIXME: Could the same pipeline be used for playing all media instead of
+ * constantly deleting and reconstructing it again?
+ */
+static void _construct_pipeline(MafwGstRendererWorker *worker, configuration *config)
+{
+ g_debug("constructing pipeline");
+ g_assert(worker != NULL);
+
+ /* Return if we have already one */
+ if (worker->pipeline)
+ return;
+
+ _free_taglist(worker);
+
+ g_debug("Creating a new instance of playbin2");
+ worker->pipeline = gst_element_factory_make("playbin2", "playbin");
+ if (worker->pipeline == NULL)
+ {
+ /* Let's try with playbin */
+ g_warning ("playbin2 failed, falling back to playbin");
+ worker->pipeline = gst_element_factory_make("playbin", "playbin");
+
+ if (worker->pipeline) {
+ /* Use nwqueue only for non-rtsp and non-mms(h) streams. */
+ gboolean use_nw;
+ use_nw = worker->media.location &&
+ !g_str_has_prefix(worker->media.location, "rtsp://") &&
+ !g_str_has_prefix(worker->media.location, "mms://") &&
+ !g_str_has_prefix(worker->media.location, "mmsh://");
+
+ g_debug("playbin using network queue: %d", use_nw);
+
+ gst_object_ref_sink(worker->pipeline);
+ /* These need a modified version of playbin. */
+ g_object_set(G_OBJECT(worker->pipeline),
+ "nw-queue", use_nw,
+ "no-video-transform", TRUE,
+ NULL);
+
+ }
+ }
+
+ if (!worker->pipeline) {
+ g_critical("failed to create playback pipeline");
+ _send_error(worker,
+ g_error_new(WORKER_ERROR,
+ WORKER_ERROR_UNABLE_TO_PERFORM,
+ "Could not create pipeline"));
+ g_assert_not_reached();
+ }
+
+ worker->bus = gst_pipeline_get_bus(GST_PIPELINE(worker->pipeline));
+ gst_bus_set_sync_handler(worker->bus,
+ (GstBusSyncHandler)_sync_bus_handler,
+ worker);
+ worker->async_bus_id = gst_bus_add_watch_full(
+ worker->bus,G_PRIORITY_HIGH,
+ (GstBusFunc)_async_bus_handler,
+ worker, NULL);
+
+ /* Listen for changes in stream-info object to find out whether the media
+ * contains video and throw error if application has not provided video
+ * window. */
+ g_signal_connect(worker->pipeline, "notify::stream-info",
+ G_CALLBACK(_stream_info_cb), worker);
+
+ g_signal_connect(worker->pipeline, "element-added",
+ G_CALLBACK(_element_added_cb), worker);
+
+ /* Set audio and video sinks ourselves. We create and configure them only
+ * once. */
+ if (!worker->asink) {
+ const gchar *sink = g_getenv("AUDIO_SINK");
+ worker->asink = gst_element_factory_make(sink?sink: worker->config->asink, NULL);
+ if (!worker->asink){
+ worker->asink = gst_element_factory_make("alsasink", NULL);
+ }
+ if (!worker->asink) {
+ g_critical("Failed to create pipeline audio sink");
+ _send_error(worker,
+ g_error_new(WORKER_ERROR,
+ WORKER_ERROR_UNABLE_TO_PERFORM,
+ "Could not create audio sink"));
+ g_assert_not_reached();
+ }
+ g_debug("MafwGstRendererWorker: Using following buffer-time: %lld and latency-time: %lld",
+ config->buffer_time,
+ config->latency_time);
+ gst_object_ref_sink(worker->asink);
+ g_object_set(worker->asink,
+ "buffer-time", config->buffer_time,
+ "latency-time", config->latency_time,
+ NULL);
+ }
+
+ if (worker->config->use_dhmmixer && !worker->amixer)
+ {
+ worker->amixer = gst_element_factory_make("nokiadhmmix", NULL);
+ if( !worker->amixer )
+ {
+ g_warning("Could not create dhmmixer, falling back to basic audiosink!");
+ }
+ }
+
+ if( worker->config->use_dhmmixer && worker->amixer && !worker->audiobin )
+ {
+ worker->audiobin = gst_bin_new("audiobin");
+ if( worker->audiobin )
+ {
+ gst_bin_add(GST_BIN (worker->audiobin), worker->amixer);
+ gst_bin_add(GST_BIN (worker->audiobin), worker->asink);
+ gst_element_link(worker->amixer, worker->asink);
+ GstPad *pad;
+ pad = gst_element_get_static_pad (worker->amixer, "sink");
+ gst_element_add_pad (worker->audiobin, gst_ghost_pad_new ("sink", pad));
+ gst_object_unref (GST_OBJECT (pad));
+
+ gst_object_ref(worker->audiobin);
+
+ /* Use Dolby music settings by default */
+ set_dolby_music_property(worker, worker->config->mobile_surround_music.state);
+ set_dolby_music_sound_property(worker, worker->config->mobile_surround_music.room, TRUE);
+ set_dolby_music_sound_property(worker, worker->config->mobile_surround_music.color, FALSE);
+ }
+ else
+ {
+ gst_object_ref_sink(worker->asink);
+ gst_object_sink(worker->amixer);
+ g_warning("Could not create audiobin! Falling back to basic audio-sink!");
+ }
+ }
+
+
+ if( worker->config->use_dhmmixer && worker->amixer && worker->audiobin )
+ {
+ g_object_set(worker->pipeline,
+ "audio-sink", worker->audiobin,
+ "flags", worker->config->flags,
+ NULL);
+ }
+ else
+ {
+ g_object_set(worker->pipeline,
+ "audio-sink", worker->asink,
+ "flags", worker->config->flags,
+ NULL);
+ }
+
+ if( worker->pipeline )
+ {
+ mafw_gst_renderer_seeker_set_pipeline(worker->seeker, worker->pipeline);
+
+ if( worker->vsink && worker->xid != 0 )
+ {
+ g_object_set(worker->pipeline,
+ "video-sink", worker->vsink,
+ NULL);
+ }
+ }
+
+ if (!worker->tsink) {
+ worker->tsink = gst_element_factory_make("textoverlay", NULL);
+ if (!worker->tsink) {
+ g_critical("Failed to create pipeline text sink");
+ _send_error(worker,
+ g_error_new(WORKER_ERROR,
+ WORKER_ERROR_UNABLE_TO_PERFORM,
+ "Could not create text sink"));
+ g_assert_not_reached();
+ }
+ gst_object_ref(worker->tsink);
+ }
+ g_object_set(worker->pipeline, "text-sink", worker->tsink, NULL);
+}
+
+guint check_dolby_audioroute(MafwGstRendererWorker *worker, guint prop) {
+ if (g_slist_find(worker->destinations,
+ GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)) ||
+ g_slist_find(worker->destinations,
+ GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)))
+ {
+ return prop;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void set_dolby_music_property(MafwGstRendererWorker *worker, guint prop) {
+ worker->config->mobile_surround_music.state = prop;
+ if (worker->amixer && !worker->media.has_visual_content) {
+ GValue a;
+ guint tempprop = check_dolby_audioroute(worker, prop);
+ if (_set_value(&a, G_TYPE_UINT, &tempprop))
+ {
+ g_object_set_property(G_OBJECT(worker->amixer), "mobile-surround", &a);
+ g_value_unset (&a);
+ }
+ }
+}
+
+void set_dolby_music_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty) {
+ if (isRoomProperty) {
+ worker->config->mobile_surround_music.room = prop;
+ } else {
+ worker->config->mobile_surround_music.color = prop;
+ }
+ if (worker->amixer && !worker->media.has_visual_content) {
+ GValue a;
+
+ if (_set_value(&a, G_TYPE_UINT, &prop))
+ {
+ if (isRoomProperty) {
+ g_object_set_property(G_OBJECT(worker->amixer), "room-size", &a);
+ } else {
+ g_object_set_property(G_OBJECT(worker->amixer), "brightness", &a);
+ }
+ g_value_unset (&a);
+ }
+ }
+}
+
+void set_dolby_video_property(MafwGstRendererWorker *worker, guint prop) {
+ worker->config->mobile_surround_video.state = prop;
+ if (worker->amixer && worker->media.has_visual_content) {
+ GValue a;
+ guint tempprop = check_dolby_audioroute(worker, prop);
+ if (_set_value(&a, G_TYPE_UINT, &tempprop))
+ {
+ g_object_set_property(G_OBJECT(worker->amixer), "mobile-surround", &a);
+ g_value_unset (&a);
+ }
+ }
+}
+
+void set_dolby_video_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty) {
+ if (isRoomProperty) {
+ worker->config->mobile_surround_video.room = prop;
+ } else {
+ worker->config->mobile_surround_video.color = prop;
+ }
+ if (worker->amixer && worker->media.has_visual_content) {
+ GValue a;
+
+ if (_set_value(&a, G_TYPE_UINT, &prop))
+ {
+ if (isRoomProperty) {
+ g_object_set_property(G_OBJECT(worker->amixer), "room-size", &a);
+ } else {
+ g_object_set_property(G_OBJECT(worker->amixer), "brightness", &a);
+ }
+ g_value_unset (&a);
+ }
+ }
+}
+
+/*
+ * @seek_type: GstSeekType
+ * @position: Time in seconds where to seek
+ * @key_frame_seek: True if this is a key frame based seek
+ * @error: Possible error that is set and returned
+ */
+static void _do_seek(MafwGstRendererWorker *worker,
+ GstSeekType seek_type,
+ gint position,
+ gboolean key_frame_seek,
+ GError **error)
+{
+ gboolean ret;
+ gint64 spos;
+ GstSeekFlags flags = GST_SEEK_FLAG_FLUSH;
+
+ g_assert(worker != NULL);
+
+ if (!worker->media.seekable == SEEKABILITY_SEEKABLE)
+ {
+ goto err;
+ }
+
+ /* According to the docs, relative seeking is not so easy:
+ GST_SEEK_TYPE_CUR - change relative to currently configured segment.
+ This can't be used to seek relative to the current playback position -
+ do a position query, calculate the desired position and then do an
+ absolute position seek instead if that's what you want to do. */
+ if (seek_type == GST_SEEK_TYPE_CUR)
+ {
+ gint curpos = mafw_gst_renderer_worker_get_position(worker);
+ position = curpos + position;
+ seek_type = GST_SEEK_TYPE_SET;
+ }
+
+ if (position < 0) {
+ position = 0;
+ }
+
+ worker->seek_position = position;
+
+ if (worker->state != GST_STATE_PLAYING && worker->state != GST_STATE_PAUSED )
+ {
+ g_debug("_do_seek: Not in playing or paused state, seeking delayed.");
+ return;
+ }
+ else if( worker->is_live && worker->state == GST_STATE_PAUSED )
+ {
+ g_debug("_do_seek: Live source can be seeked only in playing state, seeking delayed!");
+ return;
+ }
+
+ worker->report_statechanges = FALSE;
+
+ if (key_frame_seek == TRUE)
+ {
+ /* tries to do key frame seeks at least with some change */
+ ret = mafw_gst_renderer_seeker_seek_to(worker->seeker, worker->seek_position);
+ }
+ else
+ {
+ spos = (gint64)position * GST_SECOND;
+ g_debug("seek: type = %d, offset = %lld", seek_type, spos);
+
+ /* exact seek */
+ ret = gst_element_seek(worker->pipeline,
+ 1.0,
+ GST_FORMAT_TIME,
+ flags,
+ seek_type,
+ spos,
+ GST_SEEK_TYPE_NONE,
+ GST_CLOCK_TIME_NONE);
+ }
+
+ if (ret)
+ {
+ /* Seeking is async, so seek_position should not be invalidated here */
+ return;
+ }
+
+err:
+ g_set_error(error,
+ WORKER_ERROR,
+ WORKER_ERROR_CANNOT_SET_POSITION,
+ "Seeking to %d failed", position);
+ worker->report_statechanges = TRUE;
+ worker->seek_position = -1;
+ mafw_gst_renderer_seeker_cancel(worker->seeker);
+}
+
+void mafw_gst_renderer_worker_set_current_frame_on_pause(
+ MafwGstRendererWorker *worker,
+ gboolean current_frame_on_pause)
+{
+
+ worker->current_frame_on_pause = current_frame_on_pause;
+
+ _emit_property(worker,
+ WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE,
+ G_TYPE_BOOLEAN,
+ &worker->current_frame_on_pause);
+}
+
+gboolean mafw_gst_renderer_worker_get_current_frame_on_pause(
+ MafwGstRendererWorker *worker)
+{
+ return worker->current_frame_on_pause;
+}
+
+configuration *mafw_gst_renderer_worker_create_default_configuration(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return _create_default_configuration();
+}
+
+void mafw_gst_renderer_worker_set_configuration(MafwGstRendererWorker *worker,
+ configuration *config)
+{
+ if( config == NULL )
+ {
+ g_warning("NULL config was tried to be set!");
+ return;
+ }
+
+ if( worker->config )
+ {
+ _free_configuration(worker->config);
+ }
+ worker->config = config;
+
+ if( (worker->pipeline == NULL)
+ || (worker->state == GST_STATE_NULL && gst_element_get_state(worker->pipeline, NULL, NULL, 0) == GST_STATE_CHANGE_SUCCESS) )
+ {
+ _reset_pipeline_and_worker(worker);
+ _construct_pipeline(worker, worker->config);
+ }
+}
+
+/*
+ * Sets the pipeline PAUSED-to-READY timeout to given value (in seconds). If the
+ * pipeline is already in PAUSED state and this called with zero value the pipeline
+ * get immediately set to READY state.
+ */
+void mafw_gst_renderer_worker_set_ready_timeout(MafwGstRendererWorker *worker,
+ guint seconds)
+{
+ g_debug(G_STRFUNC);
+
+ worker->config->seconds_to_pause_to_ready = seconds;
+
+ /* zero is a special case: if we are already in PAUSED state, a pending
+ * ready timeout has not yet elapsed and we are asked to set the timeout
+ * value to zero --> remove the pending tmo and go immediately to READY.
+ * This forces GStreamer to release all pipeline resources and for the
+ * outsiders it looks like we are still in the PAUSED state. */
+ if (seconds == 0 && worker->ready_timeout && worker->state == GST_STATE_PAUSED)
+ {
+ _remove_ready_timeout(worker);
+ _add_ready_timeout(worker);
+ }
+
+}
+
+void mafw_gst_renderer_worker_set_position(MafwGstRendererWorker *worker,
+ GstSeekType seek_type,
+ gint position, GError **error)
+{
+ _do_seek(worker, seek_type, position, TRUE, error);
+ if (worker->notify_seek_handler)
+ worker->notify_seek_handler(worker, worker->owner);
+}
+
+static gint64 _get_duration(MafwGstRendererWorker *worker)
+{
+ gint64 value = DURATION_UNQUERIED;
+ GstFormat format = GST_FORMAT_TIME;
+
+ gboolean right_query = gst_element_query_duration(worker->pipeline, &format, &value);
+ if( !right_query )
+ {
+ /* just in case gstreamer messes with the value */
+ value = DURATION_UNQUERIED;
+ }
+ return value;
+}
+
+/*
+ * Gets current position, rounded down into precision of one second. If a seek
+ * is pending, returns the position we are going to seek. Returns -1 on
+ * failure.
+ */
+gint mafw_gst_renderer_worker_get_position(MafwGstRendererWorker *worker)
+{
+ GstFormat format;
+ gint64 time = 0;
+ g_assert(worker != NULL);
+
+ /* If seek is ongoing, return the position where we are seeking. */
+ if (worker->seek_position != -1)
+ {
+ return worker->seek_position;
+ }
+
+ /* Otherwise query position from pipeline. */
+ format = GST_FORMAT_TIME;
+ if (worker->pipeline &&
+ gst_element_query_position(worker->pipeline, &format, &time))
+ {
+ return (gint)(time / GST_SECOND);
+ }
+ /* lets return the duration if we're in eos and the pipeline cannot return position */
+ else if( worker->pipeline && worker->eos )
+ {
+ gint64 duration = _get_duration(worker);
+ if( duration > 0 )
+ {
+ return (gint)(duration / GST_SECOND);
+ }
+ }
+ return -1;
+}
+
+/*
+ * Returns the duration of the current media in seconds
+ */
+gint64 mafw_gst_renderer_worker_get_duration(MafwGstRendererWorker *worker)
+{
+ gint64 duration = _get_duration(worker);
+ if( duration >= 0 )
+ {
+ gint64 second_precision = (duration + (GST_SECOND/2)) / GST_SECOND;
+
+ if( !_seconds_duration_equal(duration, worker->media.length_nanos) )
+ {
+ worker->media.length_nanos = duration;
+
+ if( _current_metadata_add(worker,
+ WORKER_METADATA_KEY_DURATION,
+ G_TYPE_INT64,
+ (const gpointer)&second_precision) )
+ {
+ _emit_metadata(worker,
+ WORKER_METADATA_KEY_DURATION,
+ G_TYPE_INT64,
+ &second_precision);
+ }
+ }
+ return second_precision;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+gint64 mafw_gst_renderer_worker_get_last_known_duration(MafwGstRendererWorker *worker)
+{
+ if( worker->media.length_nanos <= 0 )
+ {
+ return worker->media.length_nanos;
+ }
+ else
+ {
+ return (worker->media.length_nanos + (GST_SECOND/2)) / GST_SECOND;
+ }
+}
+
+GHashTable *mafw_gst_renderer_worker_get_current_metadata(
+ MafwGstRendererWorker *worker)
+{
+ return worker->current_metadata;
+}
+
+void mafw_gst_renderer_worker_set_xid(MafwGstRendererWorker *worker, XID xid)
+{
+ /* Store the target window id */
+ g_debug("Setting xid: %x", (guint)xid);
+ worker->xid = xid;
+
+ if( !worker->vsink )
+ {
+ g_debug("Creating video-sink as XID has been set, %s", worker->config->vsink);
+ worker->vsink = gst_element_factory_make(worker->config->vsink, NULL);
+ if (!worker->vsink) {
+ worker->vsink = gst_element_factory_make("xvimagesink", NULL);
+ }
+ if (!worker->vsink) {
+ g_critical("Failed to create pipeline video sink");
+ _send_error(worker,
+ g_error_new(WORKER_ERROR,
+ WORKER_ERROR_UNABLE_TO_PERFORM,
+ "Could not create video sink"));
+ g_assert_not_reached();
+ }
+ gst_object_ref_sink(worker->vsink);
+
+ //special case for xvimagesink
+ {
+ gchar* element_name = gst_element_get_name(worker->vsink);
+ g_object_set(G_OBJECT(worker->vsink),
+ "colorkey", 0x080810,
+ NULL);
+ if (g_str_has_prefix(element_name, "xvimagesink"))
+ {
+ g_object_set(G_OBJECT(worker->vsink),
+ "handle-events", TRUE,
+ "force-aspect-ratio", TRUE,
+ NULL);
+ }
+ g_free(element_name);
+ }
+
+ //do not dare to set video-sink in any other state
+ if( worker->pipeline && worker->state == GST_STATE_NULL )
+ {
+ g_object_set(worker->pipeline,
+ "video-sink", worker->vsink,
+ NULL);
+ }
+ }
+
+ /* We don't want to set XID to video sink here when in READY state, because
+ it prevents "prepare-xwindow-id" message. Setting it when we are
+ PAUSED or PLAYING is fine, because we already got "prepare-xwindow-id". */
+ if(worker->state == GST_STATE_PLAYING ||
+ worker->state == GST_STATE_PAUSED)
+ {
+ /* Check if we should use it right away */
+ mafw_gst_renderer_worker_apply_xid(worker);
+ }
+
+ _emit_property(worker, WORKER_PROPERTY_XID, G_TYPE_UINT, &worker->xid);
+
+}
+
+XID mafw_gst_renderer_worker_get_xid(MafwGstRendererWorker *worker)
+{
+ return worker->xid;
+}
+
+void mafw_gst_renderer_worker_set_render_rectangle(MafwGstRendererWorker *worker, render_rectangle *rect)
+{
+ /* Store the target window id */
+ g_debug("Setting render rectangle: X:%d,Y:%d Width:%d, Height:%d",
+ rect->x, rect->y, rect->width, rect->height);
+
+ worker->x_overlay_rectangle.x = rect->x;
+ worker->x_overlay_rectangle.y = rect->y;
+ worker->x_overlay_rectangle.width = rect->width;
+ worker->x_overlay_rectangle.height = rect->height;
+
+ /* Check if we should use it right away */
+ mafw_gst_renderer_worker_apply_render_rectangle(worker);
+
+ GValueArray *rect_array = g_value_array_new(4);
+ GValue x;
+ GValue y;
+ GValue width;
+ GValue height;
+
+ _set_value(&x, G_TYPE_INT, &(rect->x));
+ _set_value(&y, G_TYPE_INT, &(rect->y));
+ _set_value(&width, G_TYPE_INT, &(rect->width));
+ _set_value(&height, G_TYPE_INT, &(rect->height));
+
+ g_value_array_insert(rect_array, 0, &x );
+ g_value_array_insert(rect_array, 1, &y );
+ g_value_array_insert(rect_array, 2, &width );
+ g_value_array_insert(rect_array, 3, &height );
+
+ GValue value;
+ memset(&value, 0, sizeof(value));
+ g_value_init(&value, G_TYPE_VALUE_ARRAY);
+ g_value_take_boxed(&value, rect_array);
+
+ _emit_property(worker, WORKER_PROPERTY_RENDER_RECTANGLE, G_TYPE_VALUE_ARRAY, &value);
+
+ g_value_unset(&value);
+}
+
+const render_rectangle* mafw_gst_renderer_worker_get_render_rectangle(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return &worker->x_overlay_rectangle;
+}
+
+gboolean mafw_gst_renderer_worker_get_autopaint(MafwGstRendererWorker *worker)
+{
+ return worker->autopaint;
+}
+
+void mafw_gst_renderer_worker_set_autopaint(MafwGstRendererWorker *worker,
+ gboolean autopaint)
+{
+ /* TODO Is this a bug or a feature? */
+ worker->autopaint = autopaint;
+ if (worker->vsink)
+ g_object_set(worker->vsink, "autopaint-colorkey", autopaint, NULL);
+
+ _emit_property(worker,
+ WORKER_PROPERTY_AUTOPAINT,
+ G_TYPE_BOOLEAN,
+ &autopaint);
+
+}
+
+gboolean mafw_gst_renderer_worker_set_playback_speed(MafwGstRendererWorker* worker,
+ gfloat speed)
+{
+ gboolean retVal = FALSE;
+
+ if (worker->state == GST_STATE_PLAYING)
+ {
+ worker->playback_speed = speed;
+
+ gint64 current_position;
+ GstFormat format = GST_FORMAT_TIME;
+
+ if (worker->pipeline && gst_element_query_position(worker->pipeline,
+ &format,
+ ¤t_position))
+ {
+
+ retVal = gst_element_seek(worker->pipeline,
+ speed,
+ GST_FORMAT_DEFAULT,
+ GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_KEY_UNIT,
+ GST_SEEK_TYPE_NONE,
+ current_position,
+ GST_SEEK_TYPE_NONE,
+ GST_CLOCK_TIME_NONE);
+
+ if(retVal)
+ {
+ _emit_property(worker,
+ WORKER_PROPERTY_PLAYBACK_SPEED,
+ G_TYPE_FLOAT,
+ &speed);
+ }
+ }
+ }
+
+ return retVal;
+}
+
+gfloat mafw_gst_renderer_worker_get_playback_speed(MafwGstRendererWorker* worker)
+{
+ return worker->playback_speed;
+}
+
+void mafw_gst_renderer_worker_set_force_aspect_ratio(MafwGstRendererWorker *worker, gboolean force)
+{
+
+ worker->force_aspect_ratio = force;
+ if (worker->vsink)
+ {
+ g_object_set(worker->vsink, "force-aspect-ratio", force, NULL);
+ }
+ _emit_property(worker, WORKER_PROPERTY_FORCE_ASPECT_RATIO, G_TYPE_BOOLEAN, &force);
+
+}
+
+gboolean mafw_gst_renderer_worker_get_force_aspect_ratio(MafwGstRendererWorker *worker)
+{
+ return worker->force_aspect_ratio;
+}
+
+gint mafw_gst_renderer_worker_get_colorkey(MafwGstRendererWorker *worker)
+{
+ return worker->colorkey;
+}
+
+gboolean mafw_gst_renderer_worker_get_seekable(MafwGstRendererWorker *worker)
+{
+ return worker->media.seekable == SEEKABILITY_SEEKABLE;
+}
+
+gboolean mafw_gst_renderer_worker_get_streaming(MafwGstRendererWorker *worker)
+{
+ return uri_is_stream(worker->media.location);
+}
+
+const char* mafw_gst_renderer_worker_get_uri(MafwGstRendererWorker *worker)
+{
+ return worker->media.location;
+}
+
+static void _do_play(MafwGstRendererWorker *worker)
+{
+ g_assert(worker != NULL);
+
+ if (worker->pipeline == NULL) {
+ g_debug("play without a pipeline!");
+ return;
+ }
+ worker->report_statechanges = TRUE;
+
+ /* If we have to stay paused, we do and add the ready timeout. Otherwise, we
+ * move the pipeline */
+ if (!worker->stay_paused) {
+ /* If pipeline is READY, we move it to PAUSED, otherwise, to PLAYING */
+ if (worker->state == GST_STATE_READY) {
+ gst_element_set_state(worker->pipeline, GST_STATE_PAUSED);
+ g_debug("setting pipeline to PAUSED");
+ } else {
+ gst_element_set_state(worker->pipeline, GST_STATE_PLAYING);
+ g_debug("setting pipeline to PLAYING");
+ }
+ }
+ else {
+ g_debug("staying in PAUSED state");
+ _add_ready_timeout(worker);
+ }
+}
+
+void mafw_gst_renderer_worker_play(MafwGstRendererWorker *worker,
+ const gchar *uri)
+{
+ g_assert(uri);
+
+ mafw_gst_renderer_worker_stop(worker);
+ _reset_media_info(worker);
+
+ /* Set the item to be played */
+ worker->media.location = g_strdup(uri);
+
+ _start_play(worker);
+}
+
+/*
+ * Currently, stop destroys the Gst pipeline and resets the worker into
+ * default startup configuration.
+ */
+void mafw_gst_renderer_worker_stop(MafwGstRendererWorker *worker)
+{
+ g_debug("worker stop");
+ g_assert(worker != NULL);
+
+ /* If location is NULL, this is a pre-created pipeline */
+ if (worker->async_bus_id && worker->pipeline && !worker->media.location)
+ return;
+
+ _reset_pipeline_and_worker(worker);
+
+ /* context framework adaptation starts */
+ if (worker->context_nowplaying) {
+ context_provider_map_free(worker->context_nowplaying);
+ worker->context_nowplaying = NULL;
+ }
+ context_provider_set_null(CONTEXT_PROVIDER_KEY_NOWPLAYING);
+ /* context framework adaptation ends */
+
+ /* We are not playing, so we can let the screen blank */
+ if (worker->blanking__control_handler)
+ {
+ worker->blanking__control_handler(worker, worker->owner, FALSE);
+ }
+
+ /* And now get a fresh pipeline ready */
+ _construct_pipeline(worker, worker->config);
+}
+
+void mafw_gst_renderer_worker_pause(MafwGstRendererWorker *worker)
+{
+ g_assert(worker != NULL);
+
+ if (worker->buffering && worker->state == GST_STATE_PAUSED &&
+ !worker->prerolling)
+ {
+ /* If we are buffering and get a pause, we have to
+ * signal state change and stay_paused */
+ g_debug("Pausing while buffering, signalling state change");
+
+ /* We need to make sure that we go into real PAUSE state */
+ if (worker->blanking__control_handler)
+ {
+ worker->blanking__control_handler(worker, worker->owner, FALSE);
+ }
+ _do_pause_postprocessing(worker);
+ }
+ else
+ {
+ worker->report_statechanges = TRUE;
+ if (worker->seek_position == -1 && worker->state == GST_STATE_PLAYING )
+ {
+ gst_element_set_state(worker->pipeline, GST_STATE_PAUSED);
+ if (worker->blanking__control_handler)
+ {
+ worker->blanking__control_handler(worker, worker->owner, FALSE);
+ }
+ }
+ }
+
+ worker->stay_paused = TRUE;
+ worker->pause_frame_taken = FALSE;
+}
+
+/*
+ * Notifier to call when audio/video routing changes
+ */
+void mafw_gst_renderer_worker_notify_media_destination(
+ MafwGstRendererWorker *worker,
+ GSList *destinations)
+{
+ g_assert(worker != NULL);
+ g_assert(destinations != NULL);
+
+ /* 1. update our records of current destinations */
+ g_slist_free(worker->destinations);
+ worker->destinations = g_slist_copy(destinations);
+
+ /* 2. prevent blanking if we are playing video and outputting it on our own
+ * display, otherwise disable it */
+ if (worker->blanking__control_handler &&
+ worker->media.has_visual_content &&
+ worker->state == GST_STATE_PLAYING &&
+ g_slist_find(worker->destinations,
+ GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)))
+ {
+ worker->blanking__control_handler(worker, worker->owner, TRUE);
+ }
+ else
+ {
+ worker->blanking__control_handler(worker, worker->owner, FALSE);
+ }
+
+ /* 3. disabling Dolby Headphone effect if not outputting to audio jack or
+ * bluetooth headphones, otherwise using the effect. Actual route check is done
+ * in set_dolby_*****_property function*/
+ set_dolby_music_property(worker, worker->config->mobile_surround_music.state);
+ set_dolby_video_property(worker, worker->config->mobile_surround_video.state);
+
+}
+
+void mafw_gst_renderer_worker_pause_at(MafwGstRendererWorker *worker, guint position)
+{
+ /* the current implementation works only from ready i.e. stopped state */
+ g_assert( worker != NULL);
+ worker->stay_paused = TRUE;
+ worker->pause_frame_taken = FALSE;
+ worker->seek_position = position;
+
+ if( worker->vsink )
+ {
+ g_object_set(worker->vsink, "show-preroll-frame",
+ FALSE, NULL);
+ }
+}
+
+void mafw_gst_renderer_worker_resume(MafwGstRendererWorker *worker)
+{
+ worker->stay_paused = FALSE;
+ if (worker->buffering && worker->state == GST_STATE_PAUSED &&
+ !worker->prerolling) {
+ /* If we are buffering we cannot resume, but we know that the pipeline
+ * will be moved to PLAYING as stay_paused is FALSE, so we just
+ * activate the state change report, this way as soon as buffering
+ * is finished the pipeline will be set to PLAYING and the state
+ * change will be reported */
+ worker->report_statechanges = TRUE;
+ g_debug("Resumed while buffering, activating pipeline state changes");
+ /* Notice though that we can receive the Resume before we get any
+ buffering information. In that case we go with the "else" branch
+ and set the pipeline to to PLAYING. However, it is possible that
+ in this case we get the fist buffering signal before the PAUSED ->
+ PLAYING state change. In that case, since we ignore state changes
+ while buffering we never signal the state change to PLAYING. We
+ can only fix this by checking, when we receive a PAUSED -> PLAYING
+ transition if we are buffering, and in that case signal the state
+ change (if we get that transition while buffering is on, it can
+ only mean that the client resumed playback while buffering, and
+ we must notify the state change) */
+ } else {
+ _do_play(worker);
+ }
+
+ /* we want to resume no use for these timers anymore */
+ _remove_pause_frame_timeout(worker);
+ _remove_ready_timeout(worker);
+}
+
+MafwGstRendererWorker *mafw_gst_renderer_worker_new(gpointer owner)
+{
+ MafwGstRendererWorker *worker;
+
+ g_debug("%s", G_STRFUNC);
+
+ worker = g_new0(MafwGstRendererWorker, 1);
+ worker->owner = owner;
+ worker->report_statechanges = TRUE;
+ worker->state = GST_STATE_NULL;
+ worker->seek_position = -1;
+ worker->ready_timeout = 0;
+ worker->pause_frame_timeout = 0;
+ worker->duration_seek_timeout = 0;
+ worker->duration_seek_timeout_loop_count = 0;
+ worker->in_ready = FALSE;
+ worker->xid = 0;
+ worker->x_overlay_rectangle.x = -1;
+ worker->x_overlay_rectangle.y = -1;
+ worker->x_overlay_rectangle.width = -1;
+ worker->x_overlay_rectangle.height = -1;
+ worker->autopaint = TRUE;
+ worker->playback_speed = 1;
+ worker->colorkey = -1;
+ worker->vsink = NULL;
+ worker->asink = NULL;
+ worker->tsink = NULL;
+ worker->amixer = NULL;
+ worker->audiobin = NULL;
+ worker->tag_list = NULL;
+ worker->current_metadata = NULL;
+ worker->media.seekable = SEEKABILITY_SEEKABLE;
+
+ worker->destinations = NULL;
+
+ worker->current_frame_on_pause = FALSE;
+ worker->taking_screenshot = FALSE;
+ worker->force_aspect_ratio = TRUE;
+ _init_tmp_files_pool(worker);
+ worker->notify_seek_handler = NULL;
+ worker->notify_pause_handler = NULL;
+ worker->notify_play_handler = NULL;
+ worker->notify_buffer_status_handler = NULL;
+ worker->notify_eos_handler = NULL;
+ worker->notify_metadata_handler = NULL;
+ worker->notify_error_handler = NULL;
+ worker->blanking__control_handler = NULL;
+ worker->screenshot_handler = NULL;
+
+ worker->config = _create_default_configuration();
+
+ worker->seeker = mafw_gst_renderer_seeker_new();
+
+ if (!_context_fw_initialised)
+ {
+ /* context framework adaptation starts */
+ if (context_provider_init(DBUS_BUS_SESSION, CONTEXT_PROVIDER_BUS_NAME)) {
+ _context_fw_initialised = TRUE;
+ context_provider_install_key(CONTEXT_PROVIDER_KEY_NOWPLAYING, FALSE,
+ NULL, NULL);
+ g_debug("Initialized context framework provider");
+ }
+ else {
+ g_warning("Could not initialize context framework provider");
+ }
+ }
+ /* context framework adaptation ends */
+
+ return worker;
+
+}
+
+void mafw_gst_renderer_worker_exit(MafwGstRendererWorker *worker)
+{
+ _destroy_tmp_files_pool(worker);
+ _reset_pipeline_and_worker(worker);
+
+ /* We are not playing, so we can let the screen blank */
+ if (worker->blanking__control_handler)
+ {
+ worker->blanking__control_handler(worker, worker->owner, FALSE);
+ }
+
+ /* now finally sinks/bins are released */
+ if( worker->audiobin )
+ {
+ gst_object_unref(worker->audiobin);
+ worker->audiobin = NULL;
+ }
+ else if( worker->asink )
+ {
+ gst_object_unref(worker->asink);
+ worker->asink = NULL;
+ }
+
+ if( worker->vsink )
+ {
+ gst_object_unref(worker->vsink);
+ worker->vsink = NULL;
+ }
+
+ context_provider_stop();
+ _context_fw_initialised = FALSE;
+
+ if( worker->destinations )
+ {
+ g_slist_free(worker->destinations);
+ worker->destinations = NULL;
+ }
+
+ if( worker->config )
+ {
+ _free_configuration(worker->config);
+ worker->config = NULL;
+ }
+
+ if( worker->seeker )
+ {
+ mafw_gst_renderer_seeker_free(worker->seeker);
+ worker->seeker = NULL;
+ }
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QObject>
+#include <sys/creds.h>
+
+namespace Stub
+{
+ bool global_route_provider_trusted = true;
+}
+
+creds_t creds_gettask(pid_t /*pid*/)
+{
+ return (creds_t)1;
+}
+
+int creds_have_p(const creds_t creds, creds_type_t type, creds_value_t value)
+{
+ Q_UNUSED(creds);
+ Q_UNUSED(type);
+ Q_UNUSED(value);
+
+ if( Stub::global_route_provider_trusted )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+long creds_str2creds(const char *credential, creds_value_t *value)
+{
+ Q_UNUSED(credential);
+ Q_UNUSED(value);
+
+ return 1234;
+}
--- /dev/null
+#include <MafwBasicRenderer.h>
+#include "MafwStubHelper.h"
+
+MafwStubHelper* m_stubHelper = 0;
+MafwRendererPolicy* m_policyStub;
+
+void setStubHelper(MafwStubHelper* stubHlp)
+{
+ m_stubHelper = stubHlp;
+}
+
+void setMafwRendererPolicy(MafwRendererPolicy *policy )
+{
+ m_policyStub = policy;
+}
+
+bool MafwBasicRenderer::initialize()
+{
+ return m_stubHelper->getReturn("initialize").toBool();
+}
+
+bool MafwBasicRenderer::setDefaultRendererPolicy(MafwRendererPolicy::PolicyGroup)
+{
+ return m_stubHelper->getReturn("setDefaultRendererPolicy").toBool();
+}
+
+MafwRendererPolicy* MafwBasicRenderer::rendererPolicy() const
+{
+ return m_policyStub;
+}
+
+bool MafwBasicRenderer::setMafwProperty(const QString &name, const QVariant &value)
+{
+ return MafwRenderer::setMafwProperty(name, value);
+}
+
+bool MafwBasicRenderer::pause()
+{
+ doPause();
+ return true;
+}
+
--- /dev/null
+#include "MafwGstRendererPlaylistFileUtility.h"
+#include "MafwGstRenderer.h"
+#include <QUrl>
+#include <QTimer>
+#include <QDebug>
+#include "MafwStubHelper.h"
+
+MafwGstRenderer* m_rnd = 0;
+QStringList stubPlaylistFileUtilityUris = QStringList() << "testUri1" << "testUri2";
+
+MafwGstRendererPlaylistFileUtility::MafwGstRendererPlaylistFileUtility(QObject* parent):
+ QObject(parent)
+{
+ m_rnd = static_cast<MafwGstRenderer*>(parent);
+}
+
+MafwGstRendererPlaylistFileUtility::~MafwGstRendererPlaylistFileUtility(){}
+
+void MafwGstRendererPlaylistFileUtility::parsePlaylistFile(const QUrl&)
+{
+ qDebug() << "MafwGstRendererPlaylistFileUtility::parsePlaylistFile";
+ m_uriList.append(stubPlaylistFileUtilityUris);
+ Q_EMIT parsingReady(true);
+ Q_EMIT firstItemParsed();
+}
+
+QStringList MafwGstRendererPlaylistFileUtility::getUriList()
+{
+ return m_uriList;
+}
+
+QString MafwGstRendererPlaylistFileUtility::takeFirstUri()
+{
+ if (m_uriList.isEmpty())
+ {
+ return QString();
+ }
+ else
+ {
+ return m_uriList.takeFirst();
+ }
+}
+
+void MafwGstRendererPlaylistFileUtility::uriParsed(TotemPlParser*,
+ gchar*,
+ gpointer,
+ MafwGstRendererPlaylistFileUtility*)
+{}
+
+void MafwGstRendererPlaylistFileUtility::readyCb(TotemPlParser*, GAsyncResult*, MafwGstRendererPlaylistFileUtility*)
+{}
+
+void MafwGstRendererPlaylistFileUtility::setPendingError(MafwError& error)
+{
+ m_pendingError = error;
+}
+
+/********************************************************************
+ * MafwGstRendererPlaylistFileUtility::takePendingError
+ ********************************************************************/
+MafwError MafwGstRendererPlaylistFileUtility::takePendingError()
+{
+ MafwError error = m_pendingError;
+ m_pendingError = MafwError();
+ return error;
+}
--- /dev/null
+#include "MafwRendererPolicyStub.h"
+
+MafwRendererPolicyStub::MafwRendererPolicyStub()
+{
+}
+
+MafwRendererPolicyStub::~MafwRendererPolicyStub()
+{
+
+}
+
+bool MafwRendererPolicyStub::initialize(MafwRendererPolicy::PolicyGroup group)
+{
+ return group == MafwRendererPolicy::MediaPlayer;
+}
+
+void MafwRendererPolicyStub::setDefaultResources(MafwRendererPolicy::PolicyResourceFlags)
+{
+ //nothing to do here
+}
+
+void MafwRendererPolicyStub::request(MafwRendererPolicy::PolicyResourceFlags)
+{
+
+}
+
+void MafwRendererPolicyStub::release(MafwRendererPolicy::PolicyResourceFlags flags)
+{
+ m_latestRelease = flags;
+}
+
+MafwRendererPolicy::PolicyResourceFlags MafwRendererPolicyStub::latestReleaseFlags()
+{
+ MafwRendererPolicy::PolicyResourceFlags toReturn = m_latestRelease;
+ m_latestRelease = 0;
+ return toReturn;
+}
+
+
--- /dev/null
+#include<MafwRendererPolicy.h>
+
+class MafwRendererPolicyStub : public MafwRendererPolicy
+{
+ Q_OBJECT
+
+public:
+ MafwRendererPolicyStub();
+ ~MafwRendererPolicyStub();
+
+ bool initialize(MafwRendererPolicy::PolicyGroup);
+ void setDefaultResources(QFlags<MafwRendererPolicy::PolicyResourceFlag>);
+ void request(QFlags<MafwRendererPolicy::PolicyResourceFlag>);
+ void release(QFlags<MafwRendererPolicy::PolicyResourceFlag>);
+
+ //testing functions
+ MafwRendererPolicy::PolicyResourceFlags latestReleaseFlags();
+
+private:
+ MafwRendererPolicy::PolicyResourceFlags m_latestRelease;
+};
--- /dev/null
+
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwRoutingInfoHandler.h"
+
+#include <contextsubscriber/contextproperty.h>
+#include <contextsubscriber/contextpropertyinfo.h>
+#include <contextsubscriber/contextproviderinfo.h>
+
+#include <QDebug>
+#include <QDBusReply>
+#include <QDBusConnectionInterface>
+
+bool routeTrusted = false;
+
+MafwRoutingInfoHandler::MafwRoutingInfoHandler(ContextProperty& property) :
+ m_property(property)
+{
+
+}
+
+MafwRoutingInfoHandler::~MafwRoutingInfoHandler()
+{
+}
+
+void MafwRoutingInfoHandler::startProviderCheck()
+{
+ qDebug() << "startProviderCheck";
+}
+
+ void MafwRoutingInfoHandler::callFinishedSlot(QDBusPendingCallWatcher*)
+ {
+ qDebug() << "callFinishedSlot";
+ }
+
+void MafwRoutingInfoHandler::gotReply(int)
+{
+ Q_EMIT routeChanged(routeTrusted);
+}
+
+void MafwRoutingInfoHandler::error()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ Q_EMIT routeChanged(false);
+}
+
+bool MafwRoutingInfoHandler::isPidTrusted (int)
+{
+
+ return true;
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+
+#include <QDebug>
+#include <QStringList>
+
+#include "MafwStubHelper.h"
+
+MafwStubHelper::MafwStubHelper()
+{
+ m_expectedCalls = QQueue<ExpectedItem*>();
+}
+
+MafwStubHelper::~MafwStubHelper()
+{
+ clear();
+}
+
+void MafwStubHelper::printExpects() const
+{
+ QStringList expectedNames;
+ for(int i=0; i<m_expectedCalls.size(); i++ )
+ {
+ expectedNames << m_expectedCalls[i]->expectedName;
+ }
+ qDebug() << "Expected calls enqueued (" << m_expectedCalls.size() << "): \n\t" << expectedNames.join(",\n\t ");
+}
+
+void MafwStubHelper::expect(const QString& function, QVariant returnVal)
+{
+ QList<QVariant> emptyParams;
+ QList<QVariant> returnList;
+ returnList << returnVal;
+ expect(function, emptyParams, returnList);
+}
+
+
+void MafwStubHelper::expect(const QString function, const QList<QVariant> params,
+ const QList<QVariant> returns)
+{
+ qDebug() << "MafwStubHelper::expect, function = " << function << " " << returns.at(0);
+
+ ExpectedItem* item = new ExpectedItem;
+ item->expectedName = function;
+ item->expectedParams = params;
+ item->returnValues = returns;
+ m_expectedCalls.enqueue(item);
+}
+
+QVariant MafwStubHelper::getReturn(const QString& function)
+{
+ QList<QVariant> emptyParams;
+ QList<QVariant> returnList;
+ getReturn(function, emptyParams, returnList);
+ if (returnList.isEmpty())
+ {
+ return QVariant();
+ }
+ else
+ {
+ return returnList.first();
+ }
+}
+
+void MafwStubHelper::getReturn(const QString function, const QList<QVariant> params,
+ QList<QVariant>& returns)
+{
+ // Check if the call is expected
+ if ( m_expectedCalls.isEmpty() )
+ {
+ qDebug() << "MafwStubHelper::getReturn, function = " << function <<", no expected calls";
+ return;
+ }
+ if (!m_expectedCalls.isEmpty() && function.compare(m_expectedCalls.head()->expectedName))
+ {
+ qDebug() << "MafwStubHelper::getReturn: " << function << ", not expected (2)";
+ printExpects();
+ return;
+ }
+ ExpectedItem* item = m_expectedCalls.dequeue();
+
+ // Check if the parameters match
+ if (!item->expectedParams.isEmpty())
+ {
+ for (int i = 0; i < item->expectedParams.count() && item->expectedParams.count() == params.count(); ++i)
+ {
+ if (item->expectedParams.at(i) != params.at(i))
+ {
+ qDebug() << "MafwStubHelper::getReturn: " << function <<", not expected (2)";
+ return;
+ }
+ }
+ }
+ // Expected parameters list was empty but given was not
+ else if (!params.isEmpty())
+ {
+ qDebug() << "MafwStubHelper::getReturn: " << function <<", not expected (3)";
+ return;
+ }
+ else
+ {
+ }
+
+ // Everything ok, let's find the return values
+ returns = item->returnValues;
+
+ qDebug() << "MafwStubHelper::getReturn, function: " << function << ", returns: " << returns;
+
+ delete item;
+}
+
+bool MafwStubHelper::allCallsConsumed() const
+{
+ return m_expectedCalls.isEmpty();
+}
+
+void MafwStubHelper::clear()
+{
+ qDebug() << "MafwStubHelper::clear()";
+
+ qDeleteAll(m_expectedCalls);
+ m_expectedCalls.clear();
+}
+
+// End of file
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef MAFWSTUBHELPER_H_
+#define MAFWSTUBHELPER_H_
+
+#include <QQueue>
+#include <QList>
+#include <QMultiMap>
+#include <QString>
+#include <QVariant>
+
+/**
+ * This class is meant to help implementing stubs needed in unit testing.
+ *
+ * Usage: Create instance of MafwStubHelper and provide your stub access
+ * to it. Initialize MafwStubHelper with function calls the stub is
+ * expected to get. Implement your stub to ask for return values from
+ * MafwStubHelper. At the end of a test case, check if all expected
+ * calls are consumed.
+ */
+
+
+class MafwStubHelper
+{
+public:
+ MafwStubHelper();
+ ~MafwStubHelper();
+
+ /**
+ * expect - Adds call to expected calls
+ *
+ * @param function Name of the expected function call, without paranthesis.
+ * @param params List of expected parameters given to function call.
+ * @param returns List of return values to be given to the stub.
+ */
+ void expect(const QString function, const QList<QVariant> params, const QList<QVariant> returns);
+
+ /**
+ * expect - Adds call to expected calls
+ *
+ * @param function Name of the expected function call, without paranthesis.
+ * @param returnVal The return value to be given to the stub.
+ */
+ void expect(const QString& function, QVariant returnVal);
+
+ /**
+ * getReturn - Consumes call from expected calls
+ *
+ * @param function Name of the function call, without paranthesis.
+ * @param params List of parameters given to function call.
+ * @param returns Empty list for getting the return values.
+ * List is empty at return if function wasn't the next expected function call.
+ */
+ void getReturn(const QString function, const QList<QVariant> params, QList<QVariant>& returns);
+
+ /**
+ * getReturn - Consumes call from expected calls
+ *
+ * @param function Name of the function call, without paranthesis.
+ * @return return value is invalid if function wasn't the next expected function call.
+ */
+ QVariant getReturn(const QString& function);
+
+ /**
+ * allCallsConsumed - Checks if all expected calls are consumed
+ *
+ * @return true, if all expected calls are consumed
+ * false otherwise.
+ */
+ bool allCallsConsumed() const;
+
+ /**
+ * clear - Clears all data
+ */
+ void clear();
+
+private:
+ void printExpects() const;
+
+
+private:
+
+ struct ExpectedItem
+ {
+ QString expectedName;
+ QList<QVariant> expectedParams;
+ QList<QVariant> returnValues;
+ };
+
+ QQueue<ExpectedItem*> m_expectedCalls;
+};
+
+#endif /*MAFWSTUBHELPER_H_*/
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "QNetworkStubs.h"
+
+#include <QDebug>
+#include <QTimer>
+#include <QtNetwork/QNetworkConfiguration>
+#include <QtNetwork/QNetworkConfigurationManager>
+
+
+NetworkStubHelper networkStub;
+int NetworkStubHelper::networkConfigurationManagerInstances = 0;
+
+/**
+
+ QNetworkConfiguration
+
+ **/
+
+bool NetworkStubHelper::currentCreatedConfigIsValid = false;
+
+static int staticCreationId = 0;
+class QNetworkConfigurationPrivate : public QSharedData
+{
+public:
+ int creationId;
+ bool isValid;
+};
+
+QNetworkConfiguration::QNetworkConfiguration()
+{
+ d = new QNetworkConfigurationPrivate;
+ d->creationId = ++staticCreationId;
+ d->isValid = networkStub.currentCreatedConfigIsValid;
+}
+
+QNetworkConfiguration::~QNetworkConfiguration()
+{
+
+}
+
+QNetworkConfiguration::QNetworkConfiguration(const QNetworkConfiguration &other)
+{
+ d = new QNetworkConfigurationPrivate;
+ d->creationId = other.d->creationId;
+}
+
+QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const
+{
+ return networkStub.m_currentConfState;
+}
+
+QString QNetworkConfiguration::name() const
+{
+ return "Test conf";
+}
+
+bool QNetworkConfiguration::isValid() const
+{
+ return d->isValid;
+}
+
+QNetworkConfiguration& QNetworkConfiguration::operator=(QNetworkConfiguration const &other)
+{
+ d->creationId = other.d->creationId;
+ return *this;
+}
+
+bool QNetworkConfiguration::operator==(const QNetworkConfiguration &other ) const
+{
+ return d->creationId == other.d->creationId;
+}
+
+/**
+
+ QNetworkConfigurationManager
+
+ **/
+
+QNetworkConfigurationManager::QNetworkConfigurationManager(QObject *parent)
+ :
+ QObject(parent)
+{
+ ++networkStub.networkConfigurationManagerInstances;
+ if( networkStub.networkConfigurationManagerInstances == 1)
+ {
+ connect( &networkStub, SIGNAL(configurationChange(QNetworkConfiguration)),
+ this, SIGNAL(configurationChanged(QNetworkConfiguration)));
+ }
+}
+
+QNetworkConfigurationManager::~QNetworkConfigurationManager()
+{
+ --networkStub.networkConfigurationManagerInstances;
+ if( networkStub.networkConfigurationManagerInstances == 0 )
+ {
+ networkStub.disconnect(this);
+ }
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef QNETWORKSTUBS_H
+#define QNETWORKSTUBS_H
+
+#include <QObject>
+#include <QtNetwork/QNetworkConfiguration>
+
+class QNetworkConfigurationManager;
+
+class NetworkStubHelper : public QObject
+{
+ Q_OBJECT
+
+ static int networkConfigurationManagerInstances;
+
+ friend class QNetworkConfiguration;
+ friend class QNetworkConfigurationManager;
+public:
+ static bool currentCreatedConfigIsValid;
+
+ void emitConfigurationChange(const QNetworkConfiguration &config,
+ QNetworkConfiguration::StateFlags confState)
+ {
+ m_currentConfState = confState;
+ Q_EMIT configurationChange(config);
+ }
+
+ void changeCurrentConfiguration(int id);
+
+Q_SIGNALS:
+ void configurationChange(QNetworkConfiguration config);
+
+private:
+ QNetworkConfiguration::StateFlags m_currentConfState;
+};
+
+#endif // QNETWORKSTUBS_H
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <string.h> //memset
+#include "mafw-gst-renderer-worker.h"
+#include "mafw-gst-renderer-utils.h"
+
+GError* global_error = 0;
+gint global_position = 0;
+gint global_worker_audio_destination = -1;
+gint global_worker_video_destination = -1;
+gchar *global_worker_uri = 0;
+gint global_worker_stop_called = 0;
+gint global_worker_seek_request = 0;
+GSList *global_worker_destinations = NULL;
+guint global_ready_timeout = 99999;
+
+guint m_volume;
+gboolean m_mute;
+gboolean m_current_frame_on_pause;
+gboolean m_force_aspect_ratio;
+gfloat m_playback_speed = 1;
+XID m_xid;
+
+render_rectangle m_render_rectangle;
+configuration *current_worker_conf;
+
+
+gboolean global_worker_playing = FALSE;
+
+#define UNUSED(x) (void)(x)
+
+void mafw_gst_renderer_worker_set_volume(MafwGstRendererWorker *worker,
+ guint volume)
+{
+ UNUSED(worker);
+ m_volume = volume;
+}
+
+guint mafw_gst_renderer_worker_get_volume(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return m_volume;
+}
+
+void mafw_gst_renderer_worker_set_mute(MafwGstRendererWorker *worker,
+ gboolean mute)
+{
+ UNUSED(worker);
+ m_mute = mute;
+}
+
+gboolean mafw_gst_renderer_worker_get_mute(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return m_mute;
+}
+
+gint64 mafw_gst_renderer_worker_get_last_known_duration(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return 10;
+}
+
+const char* mafw_gst_renderer_worker_get_uri(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return global_worker_uri;
+}
+
+gboolean mafw_gst_renderer_worker_get_seekable(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return TRUE;
+}
+
+void _free_configuration(configuration *config)
+{
+ if( !config )
+ {
+ return;
+ }
+
+ if( config->asink )
+ {
+ g_free(config->asink);
+ }
+ if( config->vsink )
+ {
+ g_free(config->vsink);
+ }
+
+ g_free(config);
+}
+
+void mafw_gst_renderer_worker_set_current_frame_on_pause(
+ MafwGstRendererWorker *worker,
+ gboolean current_frame_on_pause)
+{
+ UNUSED(worker);
+ m_current_frame_on_pause = current_frame_on_pause;
+}
+
+gboolean mafw_gst_renderer_worker_get_current_frame_on_pause(
+ MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return m_current_frame_on_pause;
+}
+
+void mafw_gst_renderer_worker_set_position(MafwGstRendererWorker *worker,
+ GstSeekType seek_type,
+ gint position, GError **error)
+{
+ UNUSED(worker);
+ UNUSED(seek_type);
+ global_worker_seek_request = position;
+ *error = global_error;
+}
+
+gint mafw_gst_renderer_worker_get_position(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return global_position;
+}
+
+void mafw_gst_renderer_worker_set_xid(MafwGstRendererWorker *worker, XID xid)
+{
+ UNUSED(worker);
+ m_xid = xid;
+}
+
+gboolean mafw_gst_renderer_worker_get_streaming(MafwGstRendererWorker *worker)
+{
+ return uri_is_stream(global_worker_uri);
+}
+
+XID mafw_gst_renderer_worker_get_xid(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return m_xid;
+}
+
+
+void mafw_gst_renderer_worker_set_render_rectangle(MafwGstRendererWorker *worker, render_rectangle *rect)
+{
+ UNUSED(worker);
+ m_render_rectangle.x = rect->x;
+ m_render_rectangle.y = rect->y;
+ m_render_rectangle.width = rect->width;
+ m_render_rectangle.height = rect->height;
+}
+
+const render_rectangle* mafw_gst_renderer_worker_get_render_rectangle(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return &m_render_rectangle;
+}
+
+
+gboolean mafw_gst_renderer_worker_get_autopaint(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return TRUE;
+}
+
+void mafw_gst_renderer_worker_set_ready_timeout(MafwGstRendererWorker *worker,
+ guint seconds)
+{
+ UNUSED(worker);
+ global_ready_timeout = seconds;
+}
+
+void mafw_gst_renderer_worker_set_autopaint(MafwGstRendererWorker *worker,
+ gboolean autopaint)
+{
+ UNUSED(worker);
+ UNUSED(autopaint);
+}
+
+gint mafw_gst_renderer_worker_get_colorkey(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return 1;
+}
+
+void mafw_gst_renderer_worker_play(MafwGstRendererWorker *worker,
+ const gchar *uri)
+{
+ UNUSED(worker);
+ UNUSED(uri);
+ global_worker_playing = TRUE;
+ g_free(global_worker_uri);
+ global_worker_uri = g_strdup(uri);
+ worker->notify_play_handler(worker, worker->owner);
+}
+
+void mafw_gst_renderer_worker_stop(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ global_worker_playing = FALSE;
+ ++global_worker_stop_called;
+
+ g_free(global_worker_uri);
+ global_worker_uri = NULL;
+}
+
+void mafw_gst_renderer_worker_pause(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ global_worker_playing = FALSE;
+ worker->notify_pause_handler(worker, worker->owner);
+}
+
+void mafw_gst_renderer_worker_pause_at(MafwGstRendererWorker *worker, guint position)
+{
+ UNUSED(worker);
+ UNUSED(position);
+}
+
+void mafw_gst_renderer_worker_resume(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+}
+
+MafwGstRendererWorker *mafw_gst_renderer_worker_new(gpointer owner)
+{
+ MafwGstRendererWorker *newWorker = g_new0(MafwGstRendererWorker, 1);
+ newWorker->owner = owner;
+ newWorker->config = g_new0(configuration, 1);
+ return newWorker;
+}
+
+void mafw_gst_renderer_worker_exit(MafwGstRendererWorker *worker)
+{
+ if( worker )
+ {
+ _free_configuration(worker->config);
+ worker->config = NULL;
+ }
+}
+
+gboolean mafw_gst_renderer_worker_set_playback_speed(MafwGstRendererWorker *worker, gfloat speed)
+{
+ UNUSED(worker);
+
+ if(!global_worker_playing)
+ {
+ return FALSE;
+ }
+
+ m_playback_speed = speed;
+
+ GValue v;
+ memset(&v, 0, sizeof(GValue));
+ g_value_init(&v, G_TYPE_FLOAT);
+ g_value_set_float(&v, m_playback_speed);
+
+ worker->notify_property_handler(worker, worker->owner, WORKER_PROPERTY_PLAYBACK_SPEED, &v);
+ g_value_unset(&v);
+
+ return TRUE;
+}
+
+gfloat mafw_gst_renderer_worker_get_playback_speed(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return m_playback_speed;
+}
+
+void mafw_gst_renderer_worker_set_force_aspect_ratio(MafwGstRendererWorker *worker, gboolean force)
+{
+ UNUSED(worker);
+ m_force_aspect_ratio = force;
+}
+
+gboolean mafw_gst_renderer_worker_get_force_aspect_ratio(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+ return m_force_aspect_ratio;
+}
+
+void mafw_gst_renderer_worker_notify_media_destination(MafwGstRendererWorker *worker,
+ GSList *destination)
+{
+ UNUSED(worker);
+ g_slist_free(global_worker_destinations);
+ global_worker_destinations = g_slist_copy(destination);
+}
+
+configuration* mafw_gst_renderer_worker_create_default_configuration(MafwGstRendererWorker *worker)
+{
+ configuration *config = g_malloc0(sizeof(configuration));
+ config->asink = g_strdup("pulsesink");
+ config->vsink = g_strdup("omapxvsink");
+ config->flags = 67;
+ config->buffer_time = 300000;
+ config->latency_time = 100000;
+
+ /* timers */
+ config->milliseconds_to_pause_frame = 1000;
+ config->seconds_to_pause_to_ready = 3;
+
+ /* dhmmixer */
+ config->use_dhmmixer = TRUE;
+
+ config->mobile_surround_music.state = 0;
+ config->mobile_surround_music.room = 2;
+ config->mobile_surround_music.color = 2;
+ config->mobile_surround_video.state = 0;
+ config->mobile_surround_video.room = 2;
+ config->mobile_surround_video.color = 2;
+
+ return config;
+}
+
+void mafw_gst_renderer_worker_set_configuration(MafwGstRendererWorker *worker, configuration *config)
+{
+ if( worker->config )
+ {
+ _free_configuration(worker->config);
+ }
+ worker->config = config;
+ current_worker_conf = config;
+}
+
+void set_dolby_music_property(MafwGstRendererWorker *worker, guint prop)
+{
+ worker->config->mobile_surround_music.state = prop;
+}
+
+void set_dolby_music_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty)
+{
+ if (isRoomProperty)
+ {
+ worker->config->mobile_surround_music.room = prop;
+ }
+ else
+ {
+ worker->config->mobile_surround_music.color = prop;
+ }
+}
+
+void set_dolby_video_property(MafwGstRendererWorker *worker, guint prop)
+{
+ worker->config->mobile_surround_video.state = prop;
+}
+
+void set_dolby_video_sound_property(MafwGstRendererWorker *worker, gint prop, gboolean isRoomProperty)
+{
+ if (isRoomProperty)
+ {
+ worker->config->mobile_surround_video.room = prop;
+ }
+ else
+ {
+ worker->config->mobile_surround_video.color = prop;
+ }
+}
+
+gint64 mafw_gst_renderer_worker_get_duration(MafwGstRendererWorker *worker)
+{
+ UNUSED(worker);
+
+ return 0;
+}
--- /dev/null
+ut_MafwGstRendererWorker/media/
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+STATUS=0
+
+qmake -project SUBDIRS+=`find . -type d -name ut_\*` -t subdirs -nopwd
+qmake
+if [ $SINGLE_PROCESS == "yes" ]; then
+ make -B
+else
+ make -B -j3
+fi
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+files=`find . -maxdepth 2 -name 'ut_*' -type f -perm -u+x -print`
+
+echo '<?xml version="1.0"?>' > result.xml
+echo '<unittestresults>' >> result.xml
+for file in $files; do
+ echo "Running test $file"
+ $file -lightxml -o tmp_result.xml;
+
+ if [ $? -ne 0 ]; then
+ STATUS=2
+ fi
+
+ cat tmp_result.xml >>result.xml
+done
+echo '</unittestresults>' >> result.xml
+rm -f tmp_result.xml
+sh run_valgrind.sh
+
+echo "Done"
+exit $STATUS
+
--- /dev/null
+#!/bin/sh
+export G_SLICE=always-malloc G_DEBUG=gc-friendly
+#WAIT_TIMEOUT is for worker test
+export WAIT_TIMEOUT=25000
+find . -maxdepth 2 -name 'ut_*' -type f -perm -u+x -print | xargs -t -i{} valgrind --leak-check=full --xml=yes --suppressions=test.suppressions --xml-file={}.vg.xml {}
+
--- /dev/null
+{
+ <Possibly lost: Maemo::QmDisplayState::QmDisplayState>
+ Memcheck:Leak
+ ...
+ fun:_ZN5Maemo14QmDisplayStateC1EP7QObject
+ ...
+}
+{
+ <Possibly lost: ContextProperty::ContextProperty>
+ Memcheck:Leak
+ ...
+ fun:_ZN15ContextPropertyC1ERK7QStringP7QObject
+}
+{
+ <Possibly lost: QDBusConnection::sessionBus()>
+ Memcheck:Leak
+ fun:malloc
+ fun:dbus_malloc
+ ...
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ fun:dbus_message_new_signal
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libQtDBus.so.*
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+ obj:/targets/*/usr/lib/libQtDBus.so.*
+ fun:_ZN15QDBusConnection10sessionBusEv
+}
+{
+ <Possibly lost: QDBusConnection::connectToBus>
+ Memcheck:Leak
+ fun:calloc
+ fun:dbus_malloc0
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ fun:dbus_parse_address
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libQtDBus.so.*
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+ obj:/targets/*/usr/lib/libQtDBus.so.*
+}
+{
+ <Possibly lost dbus_message_new_signal>
+ Memcheck:Leak
+ fun:realloc
+ fun:dbus_realloc
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ fun:dbus_message_new_signal
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+ obj:/targets/*/usr/lib/libdbus-1.so.*
+}
+{
+ <Possibly lost: start_thread>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_slice_alloc
+ ...
+ fun:g_main_context_new
+ fun:_ZN27QEventDispatcherGlibPrivateC1EP13_GMainContext
+ fun:_ZN20QEventDispatcherGlibC1EP7QObject
+ obj:/targets/*/usr/lib/libQtCore.so.*
+ obj:/targets/*/usr/lib/libQtCore.so.*
+ fun:start_thread
+}
+{
+ <Possibly lost: g_option_context_parse>
+ Memcheck:Leak
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+ fun:g_option_context_parse
+}
+{
+ <Possibly lost: gst_element_register>
+ Memcheck:Leak
+ ...
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_object_newv
+ ...
+ fun:gst_element_register
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+}
+{
+ <Possibly lost: gst_task_pool_new>
+ Memcheck:Leak
+ fun:*alloc
+ fun:g_malloc*
+ ...
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_object_newv
+ fun:gst_task_pool_new
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+}
+{
+ <Possibly lost: gst_caps_new_simple>
+ Memcheck:Leak
+ ...
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/lib/libglib-2.*
+ ...
+ fun:gst_caps_new_simple
+}
+
+{
+ <Possibly lost: gst_caps_copy>
+ Memcheck:Leak
+ ...
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/lib/libglib-2.*
+ ...
+ fun:gst_caps_copy
+ ...
+ fun:g_object_newv
+ fun:g_object_new_valist
+}
+
+{
+ <Possibly lost: gst_pad_set_caps>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:gst_pad_set_caps
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+}
+
+{
+ <Possibly lost: gst_pad_start_task>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ ...
+ fun:gst_pad_start_task
+ ...
+ obj:/targets/*/usr/lib/libgstbase-0.1*
+}
+
+
+{
+ <Possibly lost: gst_update_registry>
+ Memcheck:Leak
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+ fun:gst_registry_binary_read_cache
+ fun:gst_update_registry
+}
+
+{
+ <Possibly lost: gst_pad_new_from_template>
+ Memcheck:Leak
+ fun:memalign
+ ...
+ fun:g_object_new
+ fun:gst_pad_new_from_template
+ obj:/targets/*/usr/lib/libgstbase-0.1*
+}
+
+
+{
+ <Possibly lost: g_type_class_ref>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2.*
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ fun:g_type_create_instance
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_object_newv
+ fun:gst_task_pool_new
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+ fun:g_type_class_ref
+}
+{
+ <Possibly lost: gst_buffer_new_and_alloc>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ ...
+ fun:gst_buffer_new_and_alloc
+}
+{
+ <Possibly lost: gst_element_factory_make>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2.*
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ fun:g_type_create_instance
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_object_newv
+ ...
+ fun:gst_element_factory_create
+ fun:gst_element_factory_make
+}
+{
+ <Possibly lost: gst_caps_is_subset>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ ...
+ fun:gst_caps_subtract
+ fun:gst_caps_is_subset
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.25.0
+}
+{
+ <Possibly lost: gst_element_change_state>
+ Memcheck:Leak
+ fun:memalign
+ ...
+ fun:gst_element_change_state
+ ...
+}
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_ptr_array_add
+ fun:g_main_context_check
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_main_context_pending
+ fun:_ZN20QEventDispatcherGlib16hasPendingEventsEv
+ fun:_ZN16QCoreApplication16hasPendingEventsEv
+}
+{
+ <Possibly lost: QEventDispatcherGlibPrivateC2EP13_GMainContext>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_slice_alloc
+ fun:g_array_sized_new
+ fun:g_array_new
+ fun:g_static_private_set
+ fun:g_get_filename_charsets
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_thread_init_glib
+ fun:g_thread_init
+ fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+}
+{
+ <Possibly lost: QCoreApplicationPrivate >
+ Memcheck:Leak
+ ...
+ fun:g_get_language_names
+ fun:g_thread_init
+ fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+ fun:_ZN16QCoreApplication4initEv
+ fun:_ZN16QCoreApplicationC2ER23QCoreApplicationPrivate
+}
+{
+ <Possibly lost: QApplicationPrivate::createEventDispatcher()>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ ...
+ fun:g_get_filename_charsets
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_thread_init_glib
+ fun:g_thread_init
+ fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+}
+{
+ <Possibly lost: QCoreApplication::init() 1>
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ ...
+ fun:g_get_filename_charsets
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_thread_init_glib
+ fun:g_thread_init
+ fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+ fun:_ZN16QCoreApplication4initEv
+}
+{
+ <Possibly lost: QCoreApplication::init() 2>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_array_set_size
+ fun:g_static_private_set
+ fun:g_get_language_names
+ fun:g_thread_init
+ fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+ fun:_ZN16QCoreApplication4initEv
+}
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_slice_alloc
+ ...
+ ...
+ fun:_ZN27QEventDispatcherGlibPrivateC2EP13_GMainContext
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_ZN19QApplicationPrivate21createEventDispatcherEv
+}
+
+{
+ <Possibly lost: QApplication::QApplication>
+ Memcheck:Leak
+ fun:_Znwj
+ obj:/targets/*/usr/lib/libQtCore.so.*
+ obj:/targets/*/usr/lib/libQtCore.so.*
+ obj:/targets/*/usr/lib/libQtCore.so.*
+ fun:_ZN9QSettingsC1ENS_5ScopeERK7QStringS3_P7QObject
+ fun:_ZN19QApplicationPrivate18x11_apply_settingsEv
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+ fun:main
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/usr/lib/libfontconfig.so.*
+ obj:/targets/*/usr/lib/libfontconfig.so.*
+ ...
+ obj:/targets/*/usr/lib/libexpat.so.*
+ obj:/targets/*/usr/lib/libexpat.so.*
+ ...
+ fun:XML_ParseBuffer
+ fun:FcConfigParseAndLoad
+ fun:FcConfigParseAndLoad
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_ptr_array_add
+ fun:g_main_context_check
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_main_context_iteration
+ fun:_ZN20QEventDispatcherGlib13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_ZN16QCoreApplication13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEEi
+ fun:_ZN5QTestL5qWaitEi
+}
+
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ fun:_dl_relocate_object
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:*/ld-2.5.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ fun:_dl_relocate_object
+ fun:dl_open_worker
+ fun:_dl_catch_error
+ fun:_dl_open
+ fun:do_dlopen
+ fun:_dl_catch_error
+ fun:dlerror_run
+ fun:__libc_dlopen_mode
+ fun:__gconv_find_shlib
+ fun:find_module
+ fun:__gconv_lookup_cache
+ fun:__gconv_find_transform
+
+ obj:*/ld-2.5.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ fun:__libc_dlopen_mode
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ fun:__libc_dlopen_mode
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+ fun:__libc_dlopen_mode
+ obj:/targets/*/lib/libc-2.5.so
+ obj:/targets/*/lib/libc-2.5.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+ fun:main
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+ fun:main
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ obj:/targets/*/usr/lib/libQtGui.so.4.6.0
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+ fun:_ZN8QLibrary4loadEv
+ obj:/targets/*/usr/lib/libQtGui.so.*
+ fun:_Z7qt_initP19QApplicationPrivateiP9_XDisplaymm
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ obj:/targets/*/lib/ld-2.5.so
+ obj:/targets/*/lib/libdl-2.5.so
+ fun:dlopen
+ fun:_ZN15QLibraryPrivate8load_sysEv
+ fun:_ZN15QLibraryPrivate4loadEv
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ fun:_ZN11QMetaObject16checkConnectArgsEPKcS1_
+}
+{
+ <insert a suppression name here>
+ Memcheck:Addr1
+ fun:_ZN11QMetaObject16checkConnectArgsEPKcS1_
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ fun:strlen
+ fun:_dl_init_paths
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/targets/*/lib/ld-2.*.so
+}
+{
+ <insert a suppression name here>
+ Memcheck:Cond
+ fun:_dl_relocate_object
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/targets/*/lib/ld-2.*.so
+}
+{
+ <DEFINITELY LOST: XGetDefault>
+ Memcheck:Leak
+ fun:realloc
+ obj:/targets/*/usr/lib/libX11.so.*
+ obj:/targets/*/usr/lib/libX11.so.*
+ obj:/targets/*/usr/lib/libX11.so.*
+ fun:_XlcCreateLC
+ fun:_XlcDefaultLoader
+ fun:_XOpenLC
+ fun:_XrmInitParseInfo
+ obj:/targets/*/usr/lib/libX11.so.*
+ fun:XrmGetStringDatabase
+ obj:/targets/*/usr/lib/libX11.so.*
+ fun:XGetDefault
+}
+{
+ <suppresion for the known g_type_init leak>
+ Memcheck:Leak
+ ...
+ fun:g_type_init_with_debug_flags
+ fun:g_type_init
+ ...
+}
+
+{
+ <G_TYPE_VALUE macro seems to leak memory>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ ...
+ fun:g_type_register_static
+ fun:g_boxed_type_register_static
+ fun:g_value_get_type
+ ...
+}
+
+{
+ <G_TYPE_VALUE macro seems to leak memory>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ ...
+ fun:g_type_register_static
+ fun:g_param_type_register_static
+ fun:gst_param_spec_mini_object_get_type
+ ...
+}
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2.*
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ fun:g_type_create_instance
+ fun:gst_mini_object_new
+ fun:gst_buffer_new
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+ obj:/targets/*/usr/lib/libgstbase-0.10*
+ obj:/targets/*/usr/lib/libgstbase-0.10*
+ obj:/targets/*/usr/lib/libgstreamer-0*
+}
+
+
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2*
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ fun:gst_poll_new
+ fun:gst_poll_new_timer
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+ fun:g_type_create_instance
+ obj:/targets/*/usr/lib/libgobject-2*
+ fun:g_object_newv
+ fun:g_object_new_valist
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_new_object
+ fun:_dl_map_object_from_fd
+ fun:_dl_map_object
+ fun:openaux
+ fun:_dl_catch_error
+ fun:_dl_map_object_deps
+ fun:dl_open_worker
+ fun:_dl_catch_error
+ fun:_dl_open
+ fun:dlopen_doit
+ fun:_dl_catch_error
+}
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:memalign
+ fun:posix_memalign
+ obj:/targets/*/lib/libglib-2*
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ obj:/targets/*/usr/lib/libgstreamer-0.1*
+ fun:g_value_init
+ fun:gst_value_init_and_copy
+ fun:gst_structure_copy
+ fun:gst_ffmpegcsp_transform_caps
+ obj:/targets/*/usr/lib/libgstbase-0.1*
+ obj:/targets/*/usr/lib/libgstbase-0.1*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/ld-2.10.*
+ ...
+ obj:/targets/*/lib/libc-2.10.*
+ obj:/targets/*/lib/libc-2.10.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/ld-2.10.*
+ ...
+ obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+ obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/ld-2.10.*
+ ...
+ obj:/targets/*/lib/libc-2.10.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/ld-2.10.*
+ ...
+ obj:/targets/*/lib/libdl-2.10.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/libdl-2.10.*
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/libdl-2.10.*
+ fun:dlopen
+ obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+ obj:/targets/*/usr/lib/libQtCore.so.4.7.0
+ obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+ obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+ fun:_ZN15QDBusConnection9systemBusEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.10.*
+ ...
+ fun:gst_plugin_feature_load
+ fun:gst_element_factory_create
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.10.*
+ obj:/targets/*/lib/ld-2.10.*
+ ...
+ fun:gst_plugin_load_file
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ fun:g_strdupv
+ fun:gst_type_find_register
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgsttypefindfunctions.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+ fun:gst_plugin_load_file
+ fun:gst_plugin_load_by_name
+ fun:gst_plugin_feature_load
+ fun:gst_type_find_factory_call_function
+ fun:gst_type_find_helper_get_range_ext
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ ...
+ fun:gst_plugin_load_file
+ fun:gst_plugin_load_by_name
+}
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/lib/ld-2.10.*
+ fun:gst_type_find_factory_call_function
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_pcm_prepare
+ fun:snd_pcm_hw_params
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_dmix_open
+ fun:_snd_pcm_dmix_open
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:_snd_pcm_softvol_open
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_pcm_hwsync
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_start
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_start
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_mmap_writei
+ fun:snd_pcm_writei
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_pcm_hwsync
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_hwsync
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_delay
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ fun:gst_ring_buffer_delay
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_pcm_start
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_dmix_open
+ fun:_snd_pcm_dmix_open
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:_snd_pcm_softvol_open
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:_snd_pcm_plug_open
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_timer_start
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_start
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_start
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_mmap_writei
+ fun:snd_pcm_writei
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_pcm_hwsync
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_hwsync
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_poll_descriptors_revents
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_wait
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ obj:/targets/*/lib/libglib-2.0.so.0.2400.1
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_timer_stop
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_drop
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_drop
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ fun:gst_ring_buffer_pause
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_pcm_hwsync
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_mmap_commit
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_mmap_commit
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_mmap_writei
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_class_ref
+ fun:g_object_newv
+ fun:gst_element_factory_create
+ fun:gst_element_factory_make
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ fun:gst_element_change_state
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ ...
+ fun:gst_element_factory_create
+ fun:gst_element_factory_make
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ ...
+ fun:gst_element_factory_make
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+ fun:gst_element_provide_clock
+}
+
+
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ ioctl(arg)
+ fun:ioctl
+ fun:snd_pcm_hwsync
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_avail_update
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_poll_descriptors_revents
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_wait
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_hook_load
+ fun:snd_config_hook_load_for_all_cards
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_hook_load
+ fun:snd_config_hook_load_for_all_cards
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:snd_config_hook_load
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+ fun:gst_plugin_load_file
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ fun:gst_element_set_state
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ fun:g_io_modules_scan_all_in_directory
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ fun:g_vfs_get_file_for_uri
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:_snd_pcm_empty_open
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_search_definition
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+ fun:gst_plugin_load_file
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:_snd_pcm_softvol_open
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:_snd_pcm_plug_open
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:_snd_pcm_asym_open
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_add_interface_static
+ fun:gst_tag_reader_add_interface_to_type
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_hook_load
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_searcha_hooks
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_search_definition
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_object_newv
+ fun:g_object_new
+ fun:g_io_module_new
+ fun:g_io_modules_scan_all_in_directory
+ obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_rate_open
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_pcm_hw_params
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ fun:gst_ring_buffer_acquire
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_register_static
+ fun:g_boxed_type_register_static
+ fun:gst_tag_list_get_type
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ fun:g_type_class_ref
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstvolume.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+ fun:gst_plugin_load_file
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_hook_load
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_searcha_hooks
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ fun:snd_config_search_definition
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ fun:snd_config_*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ fun:snd_config_searcha_hooks
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstalsa.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ fun:g_desktop_app_info_lookup_get_type
+ obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgio-2.0.so.0.2400.1
+ fun:g_once_impl
+ fun:g_vfs_get_default
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ fun:g_input_stream_get_type
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstgio.so
+ obj:/targets/*/usr/lib/libgstbase-0.10.so.0.26.0
+ obj:/targets/*/usr/lib/libgstbase-0.10.so.0.26.0
+ fun:gst_pad_activate_pull
+ fun:gst_pad_activate_pull
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ fun:gst_ring_buffer_open_device
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/lib/ld-2.10.1.so
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ fun:snd_config_update_r
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Param
+ semctl(IPC_SET, arg.buf)
+ fun:semctl
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+ ...
+ obj:/targets/*/usr/lib/libasound.so.2.0.0
+}
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ fun:gst_element_change_state
+}
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ ...
+ fun:g_type_class_ref
+ fun:g_object_new_valist
+ fun:g_object_new
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ ...
+ fun:g_type_class_ref
+ fun:g_object_new_valist
+ fun:g_object_new
+}
+
+
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ fun:gst_plugin_load_file
+ fun:gst_plugin_load_by_name
+ fun:gst_plugin_feature_load
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ obj:/targets/*/lib/libdl-2.10.1.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ ...
+ obj:/targets/*/usr/lib/gio/modules/libgio-playready-vfs.so
+ fun:g_vfs_get_file_for_uri
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/lib/ld-2.10.1.so
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ fun:gst_plugin_load_file
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ obj:/targets/*/lib/libdl-2.10.1.so
+ fun:dlopen
+ fun:g_module_open
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ fun:gst_plugin_load_file
+ fun:gst_plugin_load_by_name
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.0.26.0
+ ...
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ obj:/targets/*/lib/ld-2.10.1.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ ...
+ obj:/targets/*/usr/lib/libgstbase-0.10.so.0.26.0
+ fun:gst_pad_get_range
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ ...
+ obj:/targets/*/usr/lib/libgstaudio-0.10.so.0.21.0
+ fun:g_type_create_instance
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ ...
+ fun:gst_element_factory_create
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ ...
+ fun:g_object_new
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ ...
+ fun:g_object_new
+ fun:gst_element_factory_create
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ fun:gst_plugin_load_by_name
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstwavparse.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.2400.1
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstdecodebin2.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.0.*
+ ...
+ fun:_ZN24ut_MafwGstRendererWorker19rendererArtTestCaseEv
+ fun:_ZN24ut_MafwGstRendererWorker11qt_metacallEN11QMetaObject4CallEiPPv
+ fun:_ZN11QMetaObject8metacallEP7QObjectNS_4CallEiPPv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ fun:g_module_open
+ fun:gst_plugin_load_file
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ ...
+ fun:g_type_class_ref
+ fun:g_object_new_valist
+}
+
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ ...
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:dbus_malloc
+ ...
+ fun:dbus_pending_call_block
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ ...
+ fun:dbus_connection_send_with_reply
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ ...
+ fun:dbus_connection_send_with_reply
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+ fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+ fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:dbus_malloc
+ ...
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:dbus_malloc
+ ...
+ obj:/targets/*/usr/lib/libdbus-1.so.3.5.1
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ ...
+ obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+ fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+ fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+ fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:g_realloc
+ obj:/targets/maemo6-i486/usr/lib/libgobject-2.0.so.*
+ obj:/targets/maemo6-i486/usr/lib/libgobject-2.0.so.*
+ fun:g_type_register_static
+ fun:gconf_client_get_type
+ fun:gconf_client_get_default
+ obj:/targets/*/usr/lib/libgq-gconf.so.*
+ ...
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:dbus_malloc0
+ ...
+ fun:_ZN9GConfItem12update_valueEb
+ fun:_ZN9GConfItemC1ERK7QStringP7QObject
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:dbus_realloc
+ ...
+ fun:dbus_message_append_args
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN15QDBusConnection10sessionBusEv
+ fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:_Z7qMallocj
+ ...
+ obj:/targets/maemo6-i486/usr/lib/libdbus-1.so.3.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:_Znwj
+ obj:/targets/*/usr/lib/libQtDBus.so.4.*
+ ...
+ fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+ fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:_Znwj
+ fun:_ZN14QObjectPrivate13addConnectionEiPNS_10ConnectionE
+ ...
+ fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:_Znwj
+ ...
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+ obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN15QDBusConnection10sessionBusEv
+ fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:_Z7qMallocj
+ ...
+ fun:_ZN11QMetaObject8metacallEP7QObjectNS_4CallEiPPv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:dbus_realloc
+ ...
+ obj:/targets/*/usr/lib/libdbus-1.so.3.5.1
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:_Z7qMallocj
+ ...
+ fun:dbus_connection_set_watch_functions
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:_Znwj
+ ...
+ obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:dbus_realloc
+ ...
+ obj:/targets/*/usr/lib/libdbus-1.so.3.5.1
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:_Znwj
+ ...
+ fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+ fun:_ZN17ContextSubscriber14PropertyHandle8instanceERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:_Z7qMallocj
+ fun:_ZN9QListData11detach_growEPii
+ ...
+ fun:_ZN16QCoreApplication6notifyEP7QObjectP6QEvent
+ fun:_ZN16QCoreApplication14notifyInternalEP7QObjectP6QEvent
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:dbus_malloc0
+ ...
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+ obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:_Z8qReallocPvj
+ ...
+ obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:_Z8qReallocPvj
+ ...
+ fun:_ZN22QDBusAbstractInterfaceC2ERK7QStringS2_PKcRK15QDBusConnectionP7QObject
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:_Z7qMallocj
+ ...
+ obj:/targets/*/lib/ld-2.*.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:_Znaj
+ ...
+ obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:_Znaj
+ ...
+ fun:_ZN17ContextSubscriber14PropertyHandleC1ERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN15QDBusConnection10sessionBusEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:_Z7qMallocj
+ ...
+ fun:_ZN15QDBusConnection12connectToBusENS_7BusTypeERK7QString
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ obj:/targets/*/usr/lib/libQtDBus.so.4.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN17ContextSubscriber16DBusNameListener14startListeningEb
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ ...
+ fun:dbus_connection_send_with_reply_and_block
+ fun:dbus_bus_register
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:dbus_malloc0
+ ...
+ obj:/targets/*/usr/lib/libQtDBus.so.4.7.0
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ obj:/targets/maemo6-i486/usr/lib/libfontconfig.so.1.*
+ ...
+ fun:XML_ParseBuffer
+ fun:FcConfigParseAndLoad
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+ fun:main
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+ fun:main
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.*.so
+ ...
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+ fun:main
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Cond
+ obj:/targets/*/lib/ld-2.10.1.so
+ ...
+ fun:_ZN19QApplicationPrivate9constructEP9_XDisplaymm
+ fun:_ZN12QApplicationC1ERiPPci
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ ...
+ fun:g_type_register_static
+ ...
+ fun:_ZN9GConfItemC1ERK7QStringP7QObject
+ fun:_ZN20MafwGstRendererDolby10initializeEv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:g_realloc
+ fun:g_realloc_n
+ ...
+ fun:g_type_register_static
+ ...
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2*.so.*
+ obj:/targets/*/usr/lib/libgobject-2*.so.*
+ obj:/targets/*/usr/lib/libgobject-2*.so.*
+ obj:/targets/*/usr/lib/libgobject-2*.so.*
+ obj:/targets/*/usr/lib/libgobject-2*.so.*
+ fun:g_type_add_interface_static
+ ...
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_param_spec_flags
+ obj:/targets/*/usr/lib/libgio-2.*.so.*
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_io_extension_ref_class
+ obj:/targets/*/usr/lib/libgio-2.*.so.*
+ fun:g_once_impl
+ obj:/targets/*/usr/lib/libgio-2.*.so.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ ...
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ fun:g_once_impl
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ ...
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ fun:g_type_class_ref
+ fun:g_object_newv
+ fun:g_object_new
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ fun:g_vfs_get_file_for_path
+ fun:g_file_new_for_path
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ fun:g_type_add_interface_static
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ fun:g_vfs_get_file_for_path
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ fun:g_realloc_n
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ fun:g_vfs_get_file_for_path
+ fun:g_file_new_for_path
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_type_create_instance
+ fun:g_param_spec_internal
+ fun:g_param_spec_int
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_io_extension_ref_class
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ fun:g_realloc_n
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ obj:/targets/*/usr/lib/libgobject-2.0.so.*
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ fun:g_file_get_type
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ obj:/targets/*/usr/lib/libgio-2.0.so.*
+ fun:g_vfs_get_file_for_path
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ fun:pthread_create@@GLIBC_2.1
+ obj:/targets/*/usr/lib/libgthread-2.0.so.*
+ fun:g_thread_create_full
+ obj:/targets/*/lib/libglib-2.0.so.*
+ fun:g_thread_pool_push
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+ fun:gst_task_pool_push
+ fun:gst_task_set_state
+ fun:gst_pad_start_task
+ obj:/targets/*/usr/lib/libgstbase-0.10.so.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_register_static
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstplaybin.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ fun:g_realloc_n
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ fun:gst_data_queue_get_type
+ fun:gst_data_queue_new_full
+ obj:/targets/*/usr/lib/gstreamer-0.10/libgstcoreelements.so
+ obj:/targets/*/usr/lib/libgstreamer-0.10.so.*
+ fun:gst_element_get_request_pad
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ fun:g_realloc_n
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_register_static
+ fun:gst_x_overlay_get_type
+ fun:mafw_gst_renderer_worker_apply_xid
+ fun:_sync_bus_handler
+ fun:gst_bus_post
+ fun:_ZN24ut_MafwGstRendererWorker18pauseFrameTestCaseEv
+ fun:_ZN24ut_MafwGstRendererWorker11qt_metacallEN11QMetaObject4CallEiPPv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ fun:g_realloc_n
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_register_static
+ fun:g_enum_register_static
+ obj:/targets/*/usr/lib/libgsttag-0.10.so.*
+ fun:g_once_impl
+ fun:gst_tag_image_type_get_type
+ fun:_ZN24ut_MafwGstRendererWorker19rendererArtTestCaseEv
+ fun:_ZN24ut_MafwGstRendererWorker11qt_metacallEN11QMetaObject4CallEiPPv
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Addr4
+ obj:/targets/*/usr/lib/libqttracker.so.1~6.12.8
+ ...
+ obj:/targets/*/usr/lib/libqttracker.so.1~6.12.8
+ obj:/targets/*/usr/lib/libqttracker.so.1~6.12.8
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_add_interface_static
+ fun:g_type_module_get_type
+ fun:g_io_module_get_type
+ fun:g_io_module_new
+ fun:g_io_modules_scan_all_in_directory
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_object_newv
+ fun:g_object_new
+ fun:g_io_module_new
+ fun:g_io_modules_scan_all_in_directory
+ obj:/targets/*/usr/lib/libgio-2.*
+ obj:/targets/*/usr/lib/libgio-2.*
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:realloc
+ fun:g_realloc
+ fun:g_realloc_n
+ obj:/targets/*/usr/lib/libgobject-2.*
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_register_static
+ fun:g_type_register_static_simple
+ obj:/targets/*/usr/lib/libgio-2.*
+ obj:/targets/*/usr/lib/libgio-2.*
+ obj:/targets/*/usr/lib/libgio-2.*
+ fun:g_vfs_get_file_for_path
+ obj:/targets/*/usr/lib/gio/modules/libprdrm-gio-vfs0.so
+}
+
+{
+ <insert_a_suppression_name_here>
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_memdup
+ obj:/targets/*/usr/lib/libgobject-2.*
+ fun:g_type_class_ref
+ fun:g_object_newv
+ fun:g_object_new
+ obj:/targets/*/usr/lib/libgio-2.*
+ obj:/targets/*/usr/lib/libgio-2.*
+ fun:g_vfs_get_file_for_path
+ obj:/targets/*/usr/lib/gio/modules/libprdrm-gio-vfs0.so
+ fun:g_vfs_get_file_for_path
+}
+
+
+
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QTimer>
+
+#include <string.h>
+#include <glib.h>
+#include <gst/gst.h>
+
+#include "MafwGstScreenshot.h"
+#include "ut_GstScreenshot.h"
+
+static gchar *global_failing_gst_element = NULL;
+
+/* START OF STUB DEFINITIONS */
+GstElement *gst_element_factory_make(const gchar *factoryname, const gchar *name)
+{
+
+ GstElementFactory *factory;
+
+ qDebug() << __PRETTY_FUNCTION__ << factoryname;
+
+ if (global_failing_gst_element != NULL &&
+ g_str_equal(factoryname, global_failing_gst_element))
+ {
+ qDebug() << "SIMULATED FAIL OF gst_element_factory_make()";
+ return NULL;
+ }
+ else
+ {
+ factory = gst_element_factory_find(factoryname);
+ return gst_element_factory_create(factory, name);
+ }
+
+}
+/* END OF STUB DEFINITIONS */
+
+void ut_GstScreenshot::testFailures()
+{
+ gint width = 1024;
+ gint height = 1024;
+ gint size = width * height + width * height / 2;
+ GstBuffer *buf = gst_buffer_new_and_alloc(size);
+ QCOMPARE(GST_OBJECT_REFCOUNT_VALUE(buf), 1);
+
+ memset(GST_BUFFER_DATA(buf), 0, size);
+
+ /* no caps set, returns false */
+ QVERIFY(m_screenshot->savePauseFrame(buf,
+ "/dev/null") == FALSE);
+
+ buf = gst_buffer_new_and_alloc(size);
+ memset(GST_BUFFER_DATA(buf), 0, size);
+
+ GstCaps *caps;
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I','4','2','0'),
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ gst_buffer_set_caps(buf, caps);
+
+ /* fakesrc creation fails, returns false */
+ global_failing_gst_element = g_strdup("fakesrc");
+ QVERIFY(m_screenshot->savePauseFrame(buf,
+ "/dev/null") == FALSE);
+
+ gst_caps_unref(caps);
+
+ /* TODO: Gst pipeline errors are difficult to test... */
+}
+
+void ut_GstScreenshot::testConvert()
+{
+ gint width = 1024;
+ gint height = 512;
+ gint size = width * height + width * height / 2;
+ GstBuffer *buf = gst_buffer_new_and_alloc(size);
+ memset(GST_BUFFER_DATA(buf), 0, size);
+
+ /* set caps, returns true */
+ GstCaps *caps;
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I','4','2','0'),
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ gst_buffer_set_caps(buf, caps);
+ QVERIFY(m_screenshot->savePauseFrame(buf,
+ "/dev/null") == TRUE);
+
+ QTest::qWait(500);
+ QVERIFY(m_gotScreenshotSignal == TRUE);
+
+ gst_caps_unref(caps);
+}
+
+
+void ut_GstScreenshot::testCancel()
+{
+ gint width = 1024;
+ gint height = 512;
+ gint size = width * height + width * height / 2;
+ GstBuffer *buf = gst_buffer_new_and_alloc(size);
+ memset(GST_BUFFER_DATA(buf), 0, size);
+
+ QFETCH(uint, timeout);
+
+ /* set caps, returns true */
+ GstCaps *caps;
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I','4','2','0'),
+ "framerate", GST_TYPE_FRACTION, 25, 1,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+ gst_buffer_set_caps(buf, caps);
+
+ QVERIFY(m_screenshot->savePauseFrame(buf,
+ "/dev/null") == TRUE);
+ QTest::qWait(timeout);
+ if (m_gotScreenshotSignal == false )
+ {
+ m_screenshot->cancelPauseFrame();
+ QVERIFY(m_gotCancelSignal == TRUE);
+ }
+}
+
+void ut_GstScreenshot::testCancel_data()
+{
+ QTest::addColumn<uint>("timeout");
+ QTest::newRow("0 ms") << (uint)0;
+ QTest::newRow("1 ms") << (uint)1;
+ QTest::newRow("5 ms") << (uint)5;
+ QTest::newRow("10 ms") << (uint)10;
+ QTest::newRow("20 ms") << (uint)20;
+ QTest::newRow("35 ms") << (uint)35;
+ QTest::newRow("50 ms") << (uint)50;
+ QTest::newRow("100 ms") << (uint)100;
+}
+
+void ut_GstScreenshot::slotScreenshot(char *location, GError *error)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+ Q_UNUSED(location);
+ Q_UNUSED(error);
+ m_gotScreenshotSignal = TRUE;
+}
+
+void ut_GstScreenshot::slotCancelScreenshot()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ m_gotCancelSignal = TRUE;
+}
+
+void ut_GstScreenshot::init()
+{
+
+ qDebug() << __PRETTY_FUNCTION__;
+
+ gst_init(0, 0);
+
+ m_gotScreenshotSignal = FALSE;
+ m_gotCancelSignal = FALSE;
+
+ m_screenshot = new MafwGstScreenshot(this);
+ connect(m_screenshot, SIGNAL(screenshotTaken(char*,GError*)), this, SLOT(slotScreenshot(char*,GError*)));
+ connect(m_screenshot, SIGNAL(screenshotCancelled()), this, SLOT(slotCancelScreenshot()));
+
+ global_failing_gst_element = NULL;
+
+}
+
+void ut_GstScreenshot::cleanup()
+{
+
+ qDebug() << __PRETTY_FUNCTION__;
+ g_free(global_failing_gst_element);
+
+ while(QCoreApplication::hasPendingEvents())
+ {
+ QCoreApplication::sendPostedEvents();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+ }
+ delete m_screenshot;
+}
+
+QTEST_MAIN(ut_GstScreenshot)
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_GSTSCREENSHOT_H_
+#define UT_GSTSCREENSHOT_H_
+
+#include <QObject>
+#include <QtTest/QtTest>
+
+#include "MafwGstScreenshot.h"
+
+class MafwGstScreenshot;
+
+class ut_GstScreenshot: public QObject
+{
+ Q_OBJECT
+
+private slots: // tests, don't touch the test order
+
+ void testFailures();
+ void testConvert();
+ void testCancel();
+ void testCancel_data();
+
+ void init();
+ void cleanup();
+
+protected slots:
+ void slotScreenshot(char *location, GError *error);
+ void slotCancelScreenshot();
+
+private: //data
+ MafwGstScreenshot *m_screenshot;
+ bool m_gotCancelSignal;
+ bool m_gotScreenshotSignal;
+};
+
+#endif
--- /dev/null
+TEMPLATE = app
+
+CONFIG -= gui
+CONFIG += console
+
+isEmpty(PREFIX) {
+ PREFIX=/usr
+}
+
+CONFIG += qt link_pkgconfig release
+CONFIG += qtestlib
+PKGCONFIG += glib-2.0 gobject-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10
+
+LIBS += -lgcov
+
+DEPENDPATH += . ../../inc ../../src
+INCLUDEPATH += . ../../inc
+
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+
+QMAKE_CLEAN += *.gcda *.gcno *.gcov ut_GstScreenshot *.vg.xml vgcore.*
+
+HEADERS += ut_GstScreenshot.h \
+ MafwGstScreenshot.h
+
+SOURCES += ut_GstScreenshot.cpp \
+ MafwGstScreenshot.cpp
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <contextsubscriber/contextproperty.h>
+#include <contextsubscriber/contextproviderinfo.h>
+#include <contextsubscriber/contextpropertyinfo.h>
+#include <sys/creds.h>
+#include <QDebug>
+#include <QDBusConnectionInterface>
+
+ContextProperty *global_video_route_property = 0;
+ContextProperty *global_audio_route_property = 0;
+QString global_audio_route("");
+QString global_video_route("");
+ContextPropertyInfo propertyInfo("key");
+
+ContextProperty::ContextProperty(const QString& key, QObject*)
+{
+ if (key == "/com/nokia/policy/video_route" && global_video_route_property == 0)
+ {
+ global_video_route_property = this;
+ }
+ else if (key == "/com/nokia/policy/audio_route" && global_audio_route_property == 0)
+ {
+ global_audio_route_property = this;
+ }
+}
+
+ContextProperty::~ContextProperty()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+ if (this == global_video_route_property)
+ {
+ global_video_route_property = 0;
+ }
+ else if (this == global_audio_route_property)
+ {
+ global_audio_route_property = 0;
+ }
+}
+
+// this non-const function is used to trigger the signal emissions
+void ContextProperty::ignoreCommander()
+{
+ Q_EMIT global_video_route_property->valueChanged();
+ Q_EMIT global_audio_route_property->valueChanged();
+}
+
+QString ContextProperty::key() const
+{
+ if (this == global_video_route_property)
+ {
+ return "/com/nokia/policy/video_route";
+ }
+ else if (this == global_audio_route_property)
+ {
+ return "/com/nokia/policy/audio_route";
+ }
+ else
+ {
+ return "";
+ }
+}
+
+QVariant ContextProperty::value() const
+{
+ if (this == global_video_route_property)
+ {
+ return QVariant(global_video_route);
+ }
+ else if (this == global_audio_route_property)
+ {
+ return QVariant(global_audio_route);
+ }
+ else
+ {
+ return QVariant();
+ }
+}
+
+const ContextPropertyInfo* ContextProperty::info() const
+{
+ return &propertyInfo;
+}
+
+ContextPropertyInfo::ContextPropertyInfo(const QString &key, QObject *parent)
+{
+ Q_UNUSED(key);
+ Q_UNUSED(parent);
+}
+
+const QList<ContextProviderInfo> ContextPropertyInfo::providers() const
+{
+ QList<ContextProviderInfo> list;
+ list << ContextProviderInfo("contextkit-dbus", "system:com.nokia.policy.pcfd");
+ return list;
+}
+
+// d-bus stub
+bool QDBusError::isValid() const
+{
+ return false;
+}
+
+QDBusMessage::MessageType QDBusMessage::type() const
+{
+ if( this->member()=="GetConnectionUnixProcessID" )
+ {
+ return QDBusMessage::ReplyMessage;
+ }
+
+ return QDBusMessage::SignalMessage;
+}
--- /dev/null
+#include "MafwGstRendererDolby.h"
+
+#include <QDebug>
+
+const int DEFAULT_COLOR = 2;
+const int DEFAULT_ROOM_SIZE = 2;
+const int MAX_VALUE = 4;
+
+enum MafwDolbyStates
+{
+ MafwDolbyOff,
+ MafwDolbyOn,
+ MafwDolbyAuto
+};
+
+MafwGstRendererDolby::MafwGstRendererDolby( QObject* parent ):
+ QObject(parent),
+ m_dolbyConfMusic(0),
+ m_dolbyConfMusicRoom(0),
+ m_dolbyConfMusicColor(0),
+ m_dolbyConfVideo(0),
+ m_dolbyConfVideoRoom(0),
+ m_dolbyConfVideoColor(0)
+{
+ qDebug() << Q_FUNC_INFO;
+ m_currentMusicDolbyState = MafwDolbyOff;
+ m_currentMusicDolbyRoom = DEFAULT_ROOM_SIZE;
+ m_currentMusicDolbyColor = DEFAULT_COLOR;
+ m_currentVideoDolbyState = MafwDolbyOff;
+ m_currentVideoDolbyRoom = DEFAULT_ROOM_SIZE;
+ m_currentVideoDolbyColor = DEFAULT_COLOR;
+}
+
+void MafwGstRendererDolby::initialize()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+MafwGstRendererDolby::~MafwGstRendererDolby()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+bool MafwGstRendererDolby::setMusicDolbyState (uint value)
+{
+}
+
+bool MafwGstRendererDolby::setMusicDolbyRoom (int value)
+{
+ qDebug() << Q_FUNC_INFO;
+ return true;
+}
+
+bool MafwGstRendererDolby::setMusicDolbyColor (int value)
+{
+ qDebug() << Q_FUNC_INFO;
+ return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyState (uint value)
+{
+ qDebug() << Q_FUNC_INFO;
+ return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyRoom (int value)
+{
+ qDebug() << Q_FUNC_INFO;
+ return true;
+}
+
+bool MafwGstRendererDolby::setVideoDolbyColor (int value)
+{
+ qDebug() << Q_FUNC_INFO;
+ return true;
+}
+
+void MafwGstRendererDolby::valueMusicChanged()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+void MafwGstRendererDolby::valueVideoChanged()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+uint MafwGstRendererDolby::getMusicDolbyState ()
+{
+ qDebug() << Q_FUNC_INFO;
+ return m_currentMusicDolbyState;
+}
+
+int MafwGstRendererDolby::getMusicDolbyRoom ()
+{
+ qDebug() << Q_FUNC_INFO;
+ return m_currentMusicDolbyRoom;
+}
+
+int MafwGstRendererDolby::getMusicDolbyColor ()
+{
+ qDebug() << Q_FUNC_INFO;
+ return m_currentMusicDolbyColor;
+}
+
+uint MafwGstRendererDolby::getVideoDolbyState ()
+{
+ qDebug() << Q_FUNC_INFO;
+ return m_currentVideoDolbyState;
+}
+
+int MafwGstRendererDolby::getVideoDolbyRoom ()
+{
+ qDebug() << Q_FUNC_INFO;
+ return m_currentVideoDolbyRoom;
+}
+
+int MafwGstRendererDolby::getVideoDolbyColor ()
+{
+ qDebug() << Q_FUNC_INFO;
+ return m_currentVideoDolbyColor;
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "MafwMmcMonitor.h"
+#include <QDebug>
+
+bool stubMmcMounted = true;
+MafwMmcMonitor* stubMmcMonitor;
+
+const QString MafwMmcMonitor::MMC_URI_PREFIX="file:///home/user/MyDocs";
+
+MafwMmcMonitor::MafwMmcMonitor(QObject* parent) : QObject(parent), m_mounted(false)
+{
+ stubMmcMonitor = this;
+}
+
+MafwMmcMonitor::~MafwMmcMonitor()
+{
+ stubMmcMonitor = 0;
+}
+
+bool MafwMmcMonitor::isMounted()
+{
+ return stubMmcMounted;
+}
+
+void MafwMmcMonitor::preUnmountEvent(const QString &/*state*/)
+{
+ Q_EMIT stubMmcMonitor->preUnmount();
+}
+
--- /dev/null
+#include <QSettings>
+
+QMap<QString, QVariant> globalSettingsMap;
+
+//QSettings stub
+QSettings::QSettings( const QString&, const QString&, QObject* ){}
+//Hope we will never need below ctor stub, because it is used somehow by unit test framework.
+//QSettings::QSettings(QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(QSettings::Format, QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(const QString&, QSettings::Format, QObject*){}
+QSettings::QSettings(QObject*){}
+QSettings::~QSettings(){}
+
+QVariant QSettings::value(const QString& key, const QVariant& defaultValue) const
+{
+ return globalSettingsMap.value(key, defaultValue);
+}
+
+bool QSettings::contains(const QString &key) const
+{
+ return true;
+}
+
+void QSettings::beginGroup(const QString &prefix)
+{
+
+}
+
+void QSettings::endGroup()
+{
+
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <qmdisplaystate.h>
+#include <QDebug>
+
+int global_qmsystemstub_setBlankingPauseCalled;
+
+namespace MeeGo {
+ QmDisplayState::QmDisplayState(QObject* parent) : QObject(parent)
+ {
+ }
+
+ QmDisplayState::~QmDisplayState(){}
+
+ bool QmDisplayState::setBlankingPause(void)
+ {
+ global_qmsystemstub_setBlankingPauseCalled++;
+ return true;
+ }
+ bool QmDisplayState::cancelBlankingPause(void)
+ {
+ return true;
+ }
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "Ut_MafwGstRenderer.h"
+
+#include <QDebug>
+#include <QVariant>
+#include <QDBusMessage>
+#include <MafwContent.h>
+#include <MafwMediaInfo.h>
+#include "MafwGstRendererVolume.h"
+#include "MafwMetadata.h"
+#include "MafwGstRendererPlaylistFileUtility.h"
+#include "MafwStubHelper.h"
+#include "MafwRendererPolicyStub.h"
+#include "mafw-gst-renderer-worker.h"
+#include "MafwMediaInfo.h"
+
+#include "QNetworkStubs.h"
+#include <QtNetwork/QNetworkConfiguration>
+
+#define private public // access private members from unit tests
+#include "MafwGstRenderer.h"
+#include "MafwMmcMonitor.h"
+
+extern void setStubHelper(MafwStubHelper* stubHlp);
+extern void setMafwRendererPolicy(MafwRendererPolicy *policy );
+
+extern GError* global_error;
+extern gint global_position;
+extern int global_qmsystemstub_setBlankingPauseCalled;
+extern ContextProperty *global_video_route_property;
+extern ContextProperty *global_audio_route_property;
+extern QString global_audio_route;
+extern QString global_video_route;
+extern gboolean global_worker_playing;
+extern const gchar* global_worker_uri;
+extern int global_worker_stop_called;
+extern int global_worker_seek_request;
+extern guint global_ready_timeout;
+extern GSList *global_worker_destinations;
+extern NetworkStubHelper networkStub;
+extern configuration *current_worker_conf;
+extern QMap<QString, QVariant> globalSettingsMap;
+
+extern bool stubMmcMounted;
+extern MafwMmcMonitor* stubMmcMonitor;
+extern QStringList stubPlaylistFileUtilityUris;
+
+void Ut_MafwGstRenderer::initTestCase()
+{
+ qRegisterMetaType<MafwError>();
+ qRegisterMetaType<MafwError::Code>();
+ qRegisterMetaType<QVariant>();
+ g_type_init();
+
+ m_stubHelper = new MafwStubHelper;
+ setStubHelper(m_stubHelper);
+ m_rendererPolicy = new MafwRendererPolicyStub();
+ setMafwRendererPolicy(m_rendererPolicy);
+
+ m_metadataCount = 0;
+
+ /* Section to test initialization */
+ MafwGstRenderer *renderer = new MafwGstRenderer("renderer_uuid", "renderer-plugin", "rendere_name");
+ //Basic renderer initialize fails
+ m_stubHelper->expect("initialize", false);
+ QVERIFY(renderer->initialize(0) == false);
+ // Let setDefaultRendererPolicy fail now to get more complete unittesting.
+ // Failure in loading policy is not considered fatal at this point.
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("setDefaultRendererPolicy", false);
+ QVERIFY(renderer->initialize(0) == true);
+ delete renderer;
+ /* Section End */
+
+ m_renderer = new MafwGstRenderer("renderer_uuid", "renderer-plugin", "rendere_name");
+
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("setDefaultRendererPolicy", true);
+ QVERIFY(m_renderer->initialize(0) == true);
+ QVERIFY(m_renderer->m_worker);
+
+ //redundant initialize call
+ QVERIFY(m_renderer->initialize(0) == true);
+
+ global_qmsystemstub_setBlankingPauseCalled = 0;
+}
+
+void Ut_MafwGstRenderer::testPlayURI()
+{
+ //rendererPlaying signal not emitted there
+ MafwMediaInfo content("");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+
+ m_renderer->doPlay(content);
+}
+
+/**
+ * PlaylistFileUtilityStub gives always two uris to play
+ */
+void Ut_MafwGstRenderer::testPlayPlaylistFile()
+{
+ QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+
+ MafwMediaInfo mediaInfo;
+ QMap<QString, QVariant> testUri;
+ QMap<QString, QVariant> testMimeType;
+ testUri.insert(MAFW_METADATA_KEY_URI, "file:///var/tmp/tunein-station.pls");
+ testMimeType.insert(MAFW_METADATA_KEY_MIME, "audio/x-scpls");
+
+ mediaInfo.setMetaData(testUri);
+ mediaInfo.setMetaData(testMimeType);
+
+ m_renderer->doPlay(mediaInfo);
+ QTest::qWait(10);
+ QCOMPARE(playSpy.count(), 1);
+ QList<QVariant> arguments = playSpy.takeFirst();
+ QCOMPARE(arguments.count(), 1);
+ QCOMPARE(arguments.at(0).toInt(), 1); //MafwRendererPlayingUri::CurrentUri
+
+//Test that next uri is started to play if playing first stops because of an error
+ GError* error = g_error_new_literal(1, 2, "Playlist uri playback error");
+ m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+ QTest::qWait(10);
+ QCOMPARE(playSpy.count(), 0);
+ QVERIFY(global_worker_playing);
+ QCOMPARE(QString(global_worker_uri), QString("testUri2"));
+
+//Test that renderer does not go playing state anymore when all uris is used
+ m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+ QTest::qWait(10);
+ QCOMPARE(playSpy.count(), 0);
+
+ g_error_free(error);
+}
+
+void Ut_MafwGstRenderer::testStop()
+{
+ //@TODO doStop needs to be tested for all the states the renderer can be in.
+ QSignalSpy spy(m_renderer, SIGNAL(rendererStopped()));
+ m_renderer->doStop();
+ QCOMPARE(spy.count(), 1);
+ //Not clear that should signal be emitted when calling doStop at stopped state
+ m_renderer->doStop();
+ m_renderer->doStop();
+}
+
+void Ut_MafwGstRenderer::testPause()
+{
+ m_renderer->doPause();
+}
+
+void Ut_MafwGstRenderer::testResume()
+{
+ m_renderer->doResume();
+}
+
+void Ut_MafwGstRenderer::testSeek()
+{
+ QSignalSpy errorSpy(m_renderer, SIGNAL(rendererError(MafwError)));
+ global_error = g_error_new_literal(1, 2, "The seek error");
+ m_renderer->doSeek(1, MafwRenderer::SeekAbsolute);
+ QCOMPARE(errorSpy.count(), 1);
+
+ global_error = 0;
+ m_renderer->doSeek(100, MafwRenderer::SeekRelative);
+}
+
+void Ut_MafwGstRenderer::testDefaultConfiguration()
+{
+ QVERIFY2(sizeof(configuration) == 64, "You've (or somebody else) most likely changed the configuration struct! Update the unittests also!");
+
+ MafwGstRenderer *rnd = new MafwGstRenderer("tesssssst", "conf-test-plug", "conf-test-rnd");
+ QSettings settings("test-set", QSettings::NativeFormat);
+
+ m_stubHelper->expect("initialize", true);
+
+ rnd->initialize(&settings);
+
+ QCOMPARE(current_worker_conf->asink, "pulsesink");
+ QCOMPARE(current_worker_conf->vsink, "omapxvsink");
+ QCOMPARE(current_worker_conf->buffer_time, 300000LL);
+ QCOMPARE(current_worker_conf->latency_time, 100000LL);
+ QCOMPARE(current_worker_conf->flags, 67);
+
+ QCOMPARE(current_worker_conf->mobile_surround_music.state, 0U);
+ QCOMPARE(current_worker_conf->mobile_surround_music.color, 2);
+ QCOMPARE(current_worker_conf->mobile_surround_music.room, 2);
+ QCOMPARE(current_worker_conf->mobile_surround_video.state, 0U);
+ QCOMPARE(current_worker_conf->mobile_surround_video.color, 2);
+ QCOMPARE(current_worker_conf->mobile_surround_video.room, 2);
+
+ QCOMPARE(current_worker_conf->milliseconds_to_pause_frame, 1000U);
+ QCOMPARE(current_worker_conf->seconds_to_pause_to_ready, 3U);
+ QCOMPARE(current_worker_conf->use_dhmmixer, 1);
+
+ delete rnd;
+
+}
+
+void Ut_MafwGstRenderer::testConfiguration()
+{
+ globalSettingsMap.clear();
+ globalSettingsMap.insert("audio-sink", "no-audio");
+ globalSettingsMap.insert("video-sink", "no-video");
+ globalSettingsMap.insert("flags", 67);
+ globalSettingsMap.insert("use_dhmmixer", false);
+ globalSettingsMap.insert("buffer-time", 313);
+ globalSettingsMap.insert("latency-time", 007);
+
+ globalSettingsMap.insert("pause-frame", 13000);
+ globalSettingsMap.insert("pause-to-ready", 7);
+
+ globalSettingsMap.insert("dhm-music-surround", 6);
+ globalSettingsMap.insert("dhm-music-color", 5);
+ globalSettingsMap.insert("dhm-music-room-size", 4);
+ globalSettingsMap.insert("dhm-video-surround", 3);
+ globalSettingsMap.insert("dhm-video-color", 12);
+ globalSettingsMap.insert("dhm-video-room-size", 1);
+
+ MafwGstRenderer *rnd = new MafwGstRenderer("tesst", "conf-test-plug", "conf-test-rnd");
+ QSettings settings("test-set", QSettings::NativeFormat);
+ m_stubHelper->expect("initialize", true);
+ rnd->initialize(&settings);
+
+ QCOMPARE(current_worker_conf->asink, "no-audio");
+ QCOMPARE(current_worker_conf->vsink, "no-video");
+ QCOMPARE(current_worker_conf->buffer_time, 313LL);
+ QCOMPARE(current_worker_conf->latency_time, 007LL);
+ QCOMPARE(current_worker_conf->flags, 67);
+
+ QCOMPARE(current_worker_conf->mobile_surround_music.state, 6U);
+ QCOMPARE(current_worker_conf->mobile_surround_music.color, 5);
+ QCOMPARE(current_worker_conf->mobile_surround_music.room, 4);
+
+ // for some reason video values are overwritten via gconf in unittests
+ QCOMPARE(current_worker_conf->mobile_surround_video.state, 3U);
+ QCOMPARE(current_worker_conf->mobile_surround_video.color, 12);
+ QCOMPARE(current_worker_conf->mobile_surround_video.room, 1);
+
+ QCOMPARE(current_worker_conf->milliseconds_to_pause_frame, 13000U);
+ QCOMPARE(current_worker_conf->seconds_to_pause_to_ready, 7U);
+ QCOMPARE(current_worker_conf->use_dhmmixer, 0);
+
+ globalSettingsMap.clear();
+
+ delete rnd;
+}
+
+void Ut_MafwGstRenderer::testNextHint()
+{
+ MafwMediaInfo content("");
+ QMap<QString,QList<QVariant> >map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.next_uri";
+ content.setMetaData(map);
+
+ m_renderer->doNextHint(content);
+}
+
+void Ut_MafwGstRenderer::testPosition()
+{
+ QVERIFY(connect(m_renderer, SIGNAL(rendererError(MafwError)), this, SLOT(positionError(MafwError))));
+ //set renderer to playing state first
+ MafwMediaInfo content("");
+ QMap<QString,QList<QVariant> >map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+
+ m_renderer->doPlay(content);
+
+ // Normal case
+ m_position = 0;
+ global_position = 157;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+ QVERIFY2(m_position == 157, "Wrong position");
+
+ //repeated call with same value
+ m_position = 0;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+ QVERIFY2(m_position == 157, "Wrong position");
+
+ // Normal case, maxint position
+ m_position = 0;
+ int maxint = 2147483647;
+ global_position = maxint;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+ QVERIFY2(m_position == (uint)maxint, "Wrong position");
+
+ // Normal case, position to 0
+ global_position = 0;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+ QVERIFY2(m_position == 0, "Wrong position");
+
+ // Errorenuous position case
+ m_position = 0;
+ global_position = -1;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+ QVERIFY2(m_position == 0, "Wrong position");
+ QVERIFY2(m_error.code() == MafwError::RendererError_CannotGetPosition, "Wrong error code");
+
+ //Errorenuous position case, -maxint
+ m_position = 0;
+ global_position = -maxint;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+ QVERIFY2(m_position == 0, "Wrong position");
+
+ //NULL result slot
+ global_position = 1;
+ m_renderer->getPosition(0, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+
+ //Not existing error slot
+ global_position = -1;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+
+ // Stopped case when 0 should be returned
+ m_renderer->doStop();
+ m_position = 0;
+ global_position = -1;
+ m_renderer->getPosition(this, SLOT(positionChanged(uint)));
+ QTest::qWait(10);
+ QVERIFY2(m_position == 0, "Wrong position");
+}
+
+void Ut_MafwGstRenderer::testProperty()
+{
+ QFETCH(QString, name);
+ QFETCH(QVariant, value);
+ bool success = m_renderer->setMafwProperty(name, value);
+ QVERIFY2(success, "Unable to set property");
+
+ m_renderer->mafwProperty(name, this, SLOT(propertyChanged(const QString&, const QVariant&)));
+ QTest::qWait(10);
+
+ //@TODO getter for current-frame-on-pause needs to be implemented
+ if (name == "colorkey")
+ {
+ QCOMPARE(m_value, QVariant(1)); //value comes from worker stub
+
+ //Test unexisting slot case
+ m_renderer->mafwProperty(name, this, SLOT(propertyChanged2(const QString&, const QVariant&)));
+ QTest::qWait(10);
+ }
+ else if (name != "unknown"
+ && name!= "current-frame-on-pause"
+ && name != MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE )
+ {
+ QCOMPARE(m_name, name);
+ QCOMPARE(m_value, value);
+ }
+}
+
+void Ut_MafwGstRenderer::testProperty_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QVariant>("value");
+
+ QTest::newRow("volume") << "volume" << QVariant(1);
+ QTest::newRow("force-aspect-ratio") << "force-aspect-ratio" << QVariant(false);
+ QTest::newRow("autopaint") << "autopaint" << QVariant(true);
+ QTest::newRow("xid") << "xid" << QVariant(12345);
+ QTest::newRow("current-frame-on-pause") << "current-frame-on-pause" << QVariant(true);
+ QTest::newRow("colorkey") << "colorkey" << QVariant(23456);
+ QTest::newRow("render-rectangle") << "render-rectangle" << QVariant(QString("%1,%2,%3,%4").arg(1).arg(2).arg(3).arg(4));
+ QTest::newRow("unknown property") << "unknown" << QVariant(true);
+}
+
+void Ut_MafwGstRenderer::testPlaybackSpeedProperty()
+{
+ QString propertyName = "playback-speed";
+
+ QSignalSpy propertyChangedSpy(m_renderer, SIGNAL(mafwPropertyChanged(const QString&, const QVariant&)));
+
+ //
+ //Stopped - won't accept the property
+ //
+ m_renderer->setMafwProperty(propertyName, 0);
+ m_renderer->setMafwProperty(propertyName, 1);
+ m_renderer->setMafwProperty(propertyName, -1);
+ QCOMPARE(propertyChangedSpy.size(), 0);
+
+ //
+ //Playing
+ //
+ //then test in playing state
+ MafwMediaInfo content("");
+ QMap<QString,QList<QVariant> >map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+
+ m_renderer->doPlay(content);
+
+ //no change in playback, just expect the signal
+ m_renderer->setMafwProperty(propertyName, 1);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ QList<QVariant> arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(1));
+
+ m_renderer->setMafwProperty(propertyName, 2);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(2));
+
+ m_renderer->setMafwProperty(propertyName, 2);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(2));
+
+ m_renderer->setMafwProperty(propertyName, -1);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(-1));
+
+ m_renderer->setMafwProperty(propertyName, 0.3);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(0.3));
+
+ m_renderer->setMafwProperty(propertyName, 1.3);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(1.3));
+
+ m_renderer->setMafwProperty(propertyName, -0.3);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(-0.3));
+
+ m_renderer->setMafwProperty(propertyName, -1.3);
+ QTest::qWait(20);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(-1.3));
+ //check that mafwProperty() returns the correct value
+ m_value = QVariant(0);
+ QVERIFY(m_renderer->mafwProperty(propertyName, this, SLOT(propertyChanged(const QString&, const QVariant&))));
+ QTest::qWait(20);
+ QCOMPARE(m_value.toFloat(), float(-1.3));
+
+ //TODO what does 0 mean?
+ m_renderer->setMafwProperty(propertyName, 0);
+ QCOMPARE(propertyChangedSpy.size(), 1);
+ arguments = propertyChangedSpy.takeFirst();
+ QCOMPARE(arguments.count(), 2);
+ QCOMPARE(arguments.at(0).toString(), propertyName);
+ //There is a QVariant inside QVariant
+ QCOMPARE(arguments.at(1).value<QVariant>().toFloat(), float(0));
+
+ //
+ //Paused - won't accept the property
+ //
+ m_renderer->doPause();
+ m_renderer->setMafwProperty(propertyName, 3);
+ //check that mafwProperty() returns the correct value
+ m_value = QVariant(-1); //not same as the last value set in playing state
+ QVERIFY(m_renderer->mafwProperty(propertyName, this, SLOT(propertyChanged(const QString&, const QVariant&))));
+ QTest::qWait(20);
+ QCOMPARE(m_value, QVariant(0)); //the value that was last set in playing state
+
+ //TODO test property value after resume
+
+ //
+ //Stopped - won't accept the property
+ //
+ m_renderer->doStop();
+
+ m_renderer->setMafwProperty(propertyName, 3);
+ //check that mafwProperty() returns the correct value
+ m_value = QVariant(-1); //not same as the last value set in playing state
+ QVERIFY(m_renderer->mafwProperty(propertyName, this, SLOT(propertyChanged(const QString&, const QVariant&))));
+ QTest::qWait(20);
+ QCOMPARE(m_value, QVariant(0)); //the value that was last set in playing state
+
+}
+
+void Ut_MafwGstRenderer::cleanupTestCase()
+{
+ delete m_renderer;
+ g_slist_free(global_worker_destinations);
+
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ while(QCoreApplication::hasPendingEvents())
+ {
+ QCoreApplication::sendPostedEvents();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+ }
+}
+
+/**
+ * Pointers to callback functions after are set to renderer worker at
+ * MafwGstRenderer::initialize
+ */
+void Ut_MafwGstRenderer::testCallbacks()
+{
+ GValue intValue;
+ GValue uintValue;
+ GValue boolValue;
+ GValue stringValue;
+ GValue uninitValue;
+ GValue objectValue;
+ GValue doubleValue;
+ GValue int64Value;
+
+ memset(&intValue, 0, sizeof(GValue));
+ memset(&uintValue, 0, sizeof(GValue));
+ memset(&boolValue, 0, sizeof(GValue));
+ memset(&stringValue, 0, sizeof(GValue));
+ memset(&uninitValue, 0, sizeof(GValue));
+ memset(&objectValue, 0, sizeof(GValue));
+ memset(&doubleValue, 0, sizeof(GValue));
+ memset(&int64Value, 0, sizeof(GValue));
+
+ g_value_init(&intValue, G_TYPE_INT);
+ g_value_init(&uintValue, G_TYPE_UINT);
+ g_value_init(&boolValue, G_TYPE_BOOLEAN);
+ g_value_init(&stringValue, G_TYPE_STRING);
+ g_value_init(&objectValue, G_TYPE_OBJECT);
+ g_value_init(&doubleValue, G_TYPE_DOUBLE);
+ g_value_init(&int64Value, G_TYPE_INT64);
+
+ g_value_set_int(&intValue, -123);
+ g_value_set_uint(&uintValue, (uint)-1);
+ g_value_set_boolean(&boolValue, TRUE);
+ g_value_set_string(&stringValue, "The test property");
+ g_value_set_double(&doubleValue, 1.01);
+ g_value_set_int64(&int64Value, 1234567890);
+
+//playCallback
+ QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+ m_renderer->m_worker->notify_play_handler(m_renderer->m_worker, m_renderer);
+ QCOMPARE(playSpy.count(), 1);
+
+//pauseCallback
+ QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+ m_renderer->m_worker->notify_pause_handler(m_renderer->m_worker, m_renderer);
+ QCOMPARE(pauseSpy.count(), 1);
+
+//errorCallback
+ QSignalSpy errorSpy(m_renderer, SIGNAL(rendererError(MafwError)));
+ GError* error = g_error_new_literal(1, 2, "The unit test error");
+ GError* error2 = g_error_new_literal(1, -1, "Another unit test error");
+ m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+ m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error2);
+ QCOMPARE(errorSpy.count(), 2);
+ g_error_free(error);
+ g_error_free(error2);
+
+//eosCallback
+ QSignalSpy eosSpy(m_renderer, SIGNAL(rendererEos()));
+ m_renderer->m_worker->notify_eos_handler(m_renderer->m_worker, m_renderer);
+ QTest::qWait(10); //renderer paused will be emitted asynchronously
+ QCOMPARE(eosSpy.count(), 1);
+
+//metadataCallback
+ QSignalSpy metadataSpy(m_renderer, SIGNAL(metadataChanged(const QString&, const QList<QVariant>&)));
+ GValueArray *array = g_value_array_new(0);
+ g_value_array_append(array, &stringValue);
+ g_value_array_append(array, &doubleValue);
+ g_value_array_append(array, &int64Value);
+
+ //unknown metadata key
+ m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, -1, G_TYPE_VALUE_ARRAY, array);
+ //invalid type
+ m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, 1, G_TYPE_VALUE, &stringValue);
+ //valid case
+ m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, 1, G_TYPE_VALUE_ARRAY, array);
+
+ QCOMPARE(metadataSpy.count(), 1);
+ g_value_array_free(array);
+
+//propertyCallback
+ int count = 0;
+ QSignalSpy propertySpy(m_renderer, SIGNAL(mafwPropertyChanged(const QString&, const QVariant&)));
+
+ //auto paint
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_AUTOPAINT, &boolValue);
+ QCOMPARE(propertySpy.count(), ++count);
+
+ //color key
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_COLORKEY, &intValue);
+ QCOMPARE(propertySpy.count(), ++count);
+
+ //xid
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_XID, &uintValue);
+ QCOMPARE(propertySpy.count(), ++count);
+
+ //pause frame
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE, &boolValue);
+ QCOMPARE(propertySpy.count(), ++count);
+
+ //force aspect ratio
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_FORCE_ASPECT_RATIO, &boolValue);
+ QCOMPARE(propertySpy.count(), ++count);
+
+ //playback speed
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_PLAYBACK_SPEED, &doubleValue);
+ QCOMPARE(propertySpy.count(), ++count);
+
+ //unknown property id
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, 6, &uintValue);
+ QCOMPARE(propertySpy.count(), ++count);
+
+ //!G_IS_VALUE
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE, &uninitValue);
+ QCOMPARE(propertySpy.count(), count);
+
+ //unsupported value g_type
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_MUTE, &objectValue);
+ QCOMPARE(propertySpy.count(), count);
+
+ //boolean property with string value, currently there is no check -> emits mafwPropertyChanged( "mute", "The test property" )
+ m_renderer->m_worker->notify_property_handler(m_renderer->m_worker, m_renderer, WORKER_PROPERTY_MUTE, &intValue);
+
+
+//bufferStatusCallback
+ QSignalSpy bufferSpy(m_renderer, SIGNAL(bufferingInfo(float)));
+ m_renderer->m_worker->notify_buffer_status_handler(m_renderer->m_worker, m_renderer, (gdouble)1.001);
+ m_renderer->m_worker->notify_buffer_status_handler(m_renderer->m_worker, m_renderer, (gdouble)-1.001);
+ m_renderer->m_worker->notify_buffer_status_handler(m_renderer->m_worker, m_renderer, (gdouble)1001);
+ QCOMPARE(bufferSpy.count(), 3);
+
+ g_value_unset(&intValue);
+ g_value_unset(&uintValue);
+ g_value_unset(&boolValue);
+ g_value_unset(&stringValue);
+ g_value_unset(&int64Value);
+ g_value_unset(&doubleValue);
+}
+
+void Ut_MafwGstRenderer::testGetCurrentMediaInfo()
+{
+ QFETCH(QString, name);
+ QFETCH(QList<QVariant>, values);
+
+ qDebug() << "values.size():" << values.size();
+
+ MafwMediaInfo content("");
+ MafwMediaInfo mediaInfo;
+ QMap<QString,QList<QVariant> > map;
+ QMap<QString,QList<QVariant> >old_map;
+
+ bool success = false;
+ m_name = name;
+
+ GValueArray *array = g_value_array_new(0);
+
+ if(name == "all")
+ {
+ QList<QVariant> valueList;
+ valueList.append("http://test.play.uri");
+ map[MAFW_METADATA_KEY_URI] = valueList;
+ old_map[MAFW_METADATA_KEY_URI] = valueList;
+ mediaInfo.setMetaData(map);
+ content.setMetaData(old_map);
+
+ GValue geevalue;
+ memset(&geevalue, 0, sizeof(GValue));
+ g_value_init(&geevalue, G_TYPE_STRING);
+ g_value_set_string(&geevalue, "http://test.play.uri");
+ g_value_array_append(array, &geevalue);
+ g_value_unset(&geevalue);
+
+ m_renderer->doPlay(content);
+ m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, 18, G_TYPE_VALUE_ARRAY, array);
+ success = m_renderer->getCurrentMediaInfo(this, SLOT(media_info_result(const MafwMediaInfo& )));
+ QTest::qWait(10);
+
+ if(success)
+ {
+ QCOMPARE(m_media_values.at(0), mediaInfo.firstMetaData(MAFW_METADATA_KEY_URI));
+ }
+ else if(!success)
+ {
+ QVERIFY(success);
+ }
+ }
+ else
+ {
+ //URI must be set
+ QMap<QString, QVariant> onlyURI;
+ onlyURI[MAFW_METADATA_KEY_URI] = "http://2222.222.22";
+ content.setMetaData(onlyURI);
+ m_renderer->doPlay(content);
+
+ map[name] = values;
+ old_map[name] = values;
+ mediaInfo.setMetaData(map);
+ content.setMetaData(old_map);
+ m_metadataCount++;
+
+ Q_FOREACH(QVariant value, values)
+ {
+ GValue geevalue;
+ memset(&geevalue, 0, sizeof(GValue));
+ QString type = value.typeName();
+
+ if(type == "QString")
+ {
+ g_value_init(&geevalue, G_TYPE_STRING);
+ g_value_set_string(&geevalue, value.toByteArray());
+ }
+ else if(type == "int")
+ {
+ g_value_init(&geevalue, G_TYPE_INT);
+ g_value_set_int(&geevalue, value.toInt());
+ }
+ else if(type == "float")
+ {
+ g_value_init(&geevalue, G_TYPE_DOUBLE);
+ g_value_set_double(&geevalue, value.toDouble());
+ }
+ else if(type == "bool")
+ {
+ g_value_init(&geevalue, G_TYPE_BOOLEAN);
+ g_value_set_boolean(&geevalue, value.toBool());
+ }
+
+ g_value_array_append(array, &geevalue);
+ g_value_unset(&geevalue);
+ }
+ qDebug() << "array.size:" << array->n_values;
+ m_renderer->m_worker->notify_metadata_handler(m_renderer->m_worker, m_renderer, m_metadataCount, G_TYPE_VALUE_ARRAY, array);
+
+ success = m_renderer->getCurrentMediaInfo(this, SLOT(media_info_result(const MafwMediaInfo& )), name);
+ QTest::qWait(10);
+
+ if(success)
+ {
+ //TODO rethink this and do the test properly if more metadata start to have related info attached
+ //Related metadata is returned with paused-thumbnail-uri.
+ if(name == "paused-thumbnail-uri")
+ {
+ values.append(QVariant(QString("http://2222.222.22")));
+ values.append(QVariant(0));
+ }
+ qDebug() << m_media_values;
+ qDebug() << values;
+ QCOMPARE(m_media_values, values);
+ }
+ else if(!success)
+ {
+ QVERIFY(success);
+ }
+ }
+
+ g_value_array_free(array);
+}
+
+void Ut_MafwGstRenderer::testGetCurrentMediaInfo_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QList<QVariant> >("values");
+
+ QTest::newRow("all") << "all" << QList<QVariant>();
+ QTest::newRow("title") << MAFW_METADATA_KEY_TITLE << ( QList<QVariant>() << QVariant("test-title") );
+ QTest::newRow("artist") << MAFW_METADATA_KEY_ARTIST << ( QList<QVariant>() << QVariant("test-artist") << QVariant("test-artist 2") );
+ QTest::newRow("audio-codec") << MAFW_METADATA_KEY_AUDIO_CODEC << ( QList<QVariant>() << QVariant("test-audio-codec") );
+ QTest::newRow("video-codec") << MAFW_METADATA_KEY_VIDEO_CODEC << ( QList<QVariant>() << QVariant("test-video-codec") );
+ QTest::newRow("bitrate") << MAFW_METADATA_KEY_BITRATE << ( QList<QVariant>() << QVariant(256) );
+ QTest::newRow("encoding") << MAFW_METADATA_KEY_ENCODING << ( QList<QVariant>() << QVariant("test-encoding") );
+ QTest::newRow("album") << MAFW_METADATA_KEY_ALBUM << ( QList<QVariant>() << QVariant("test-album") );
+ QTest::newRow("genre") << MAFW_METADATA_KEY_GENRE << ( QList<QVariant>() << QVariant("test-genre") );
+ QTest::newRow("track") << MAFW_METADATA_KEY_TRACK << ( QList<QVariant>() << QVariant(1) );
+ QTest::newRow("organization") << MAFW_METADATA_KEY_ORGANIZATION << ( QList<QVariant>() << QVariant("test-organization") );
+ QTest::newRow("renderer-art-uri") << MAFW_METADATA_KEY_RENDERER_ART_URI << ( QList<QVariant>() << QVariant("http://test.renderer.art.uri") );
+ QTest::newRow("res-x") << MAFW_METADATA_KEY_RES_X << ( QList<QVariant>() << QVariant(480) );
+ QTest::newRow("res-y") << MAFW_METADATA_KEY_RES_Y << ( QList<QVariant>() << QVariant(640) );
+ QTest::newRow("video-framerate") << MAFW_METADATA_KEY_VIDEO_FRAMERATE << ( QList<QVariant>() << QVariant(float(30/1)) );
+ QTest::newRow("duration") << MAFW_METADATA_KEY_DURATION << ( QList<QVariant>() << QVariant(5) );
+ QTest::newRow("is-seekable") << MAFW_METADATA_KEY_IS_SEEKABLE << ( QList<QVariant>() << QVariant(true) );
+ QTest::newRow("paused-thumbnail-uri") << MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI << ( QList<QVariant>() << QVariant("file:///test.thumbnail.paused.uri") );// << QVariant("http://test.play.uri") << QVariant(666) );
+ QTest::newRow("uri") << MAFW_METADATA_KEY_URI << ( QList<QVariant>() << QVariant("http://test.play.uri") );
+}
+
+void Ut_MafwGstRenderer::testErrorCodeScenarios()
+{
+ m_renderer->m_playingPlaylistFile = false;
+
+ QFETCH(QString, uri);
+ QFETCH(int, workerError);
+ QFETCH(MafwError::Code, emittedError);
+
+ global_worker_uri = g_strdup(uri.toAscii().constData());
+
+ QSignalSpy errorSpy(m_renderer, SIGNAL(rendererError(MafwError)));
+
+ GError* gerror = g_error_new_literal(1, workerError, "Media not found");
+ m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, gerror);
+
+ QCOMPARE(errorSpy.size(), 1);
+
+ QVariantList params = errorSpy.takeFirst();
+ MafwError mafwError = params.at(0).value<MafwError>();
+
+ QCOMPARE(mafwError.code(), MafwError::Code(emittedError));
+
+ g_error_free(gerror);
+}
+
+void Ut_MafwGstRenderer::testErrorCodeScenarios_data()
+{
+ QTest::addColumn<QString>("uri");
+ QTest::addColumn<int>("workerError");
+ QTest::addColumn<MafwError::Code>("emittedError");
+
+ QTest::newRow("Local file not found") << "file:///donotexits.mp3" << int(WORKER_ERROR_MEDIA_NOT_FOUND) << MafwError::RendererError_MediaNotFound;
+ QTest::newRow("Stream could not be connected") << "mms:///donotexits.mp3" << int(WORKER_ERROR_MEDIA_NOT_FOUND) << MafwError::RendererError_URINotAvailable;
+}
+
+void Ut_MafwGstRenderer::testBlankingPreventer()
+{
+ m_renderer->m_worker->blanking__control_handler(m_renderer->m_worker, m_renderer, TRUE );
+ QCOMPARE( global_qmsystemstub_setBlankingPauseCalled, 1 );
+ QTest::qWait( 50*1000 ); // >45 secs
+ QCOMPARE( global_qmsystemstub_setBlankingPauseCalled, 2 );
+ global_qmsystemstub_setBlankingPauseCalled = 0;
+
+ m_renderer->m_worker->blanking__control_handler(m_renderer->m_worker, m_renderer, FALSE );
+ QTest::qWait( 50*1000 ); // >45 secs
+ // no more calls arrived
+ QCOMPARE( global_qmsystemstub_setBlankingPauseCalled, 0 );
+}
+
+void Ut_MafwGstRenderer::testPolicyPropertyHandler()
+{
+ m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, true);
+ QVERIFY(global_ready_timeout == 0);
+
+ m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, false);
+ QCOMPARE(global_ready_timeout, (guint)MAFW_GST_RENDERER_WORKER_READY_TIMEOUT);
+
+ m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, true);
+ QVERIFY(global_ready_timeout == 0);
+
+ m_renderer->setMafwProperty(MafwRenderer::MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE, false);
+ QCOMPARE(global_ready_timeout, (guint)MAFW_GST_RENDERER_WORKER_READY_TIMEOUT);
+
+}
+
+void Ut_MafwGstRenderer::testMediaRouting()
+{
+
+ QVERIFY(global_audio_route_property);
+ QVERIFY(global_video_route_property);
+
+ global_audio_route = "tvout";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 3);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "tvout";
+ global_video_route = "tvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 2);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "null";
+ global_video_route = "builtin";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 2);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+ global_audio_route = "headset";
+ global_video_route = "kjkjkjfg";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 2);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+
+ MafwMediaInfo content("test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing == TRUE); //should be playing now
+ global_audio_route = "ihf";
+ global_video_route = "builtin";
+ m_renderer->m_audioRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_length(global_worker_destinations) == 2);
+
+ global_audio_route = "earpiece";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 3);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "bthsp";
+ global_video_route = "kjkjkjfg";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 2);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+
+ global_audio_route = "bta2dp";
+ global_video_route = "builtin";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 2);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+ global_audio_route = "lkglklkgh";
+ global_video_route = "bugvfdd";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 1);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+
+ global_audio_route = "fmtx";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 3);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_FM_RADIO)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "ihfandfmtx";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 4);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_FM_RADIO)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "earpieceandtvout";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 3);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "headphone";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 3);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "ihfandheadset";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 4);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "ihfandheadphone";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 4);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "ihfandbthsp";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 4);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "tvoutandbthsp";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 4);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ global_audio_route = "tvoutandbta2dp";
+ global_video_route = "builtinandtvout";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(global_worker_destinations);
+ QVERIFY(g_slist_length(global_worker_destinations) == 4);
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BLUETOOTH_AUDIO)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_TVOUT)));
+
+ // provider dies
+ global_audio_route = "earpiece";
+ global_video_route = "builtin";
+ m_renderer->m_audioRoute->ignoreCommander();
+ m_renderer->m_videoRoute->ignoreCommander();
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+ QList<QVariant> args;
+ args << "name" << "old" << "";
+ QDBusMessage dbusMsg;
+ dbusMsg.setArguments(args);
+ m_renderer->handleContextProviderRemoval( dbusMsg );
+ QVERIFY(g_slist_find(global_worker_destinations, GINT_TO_POINTER(WORKER_OUTPUT_NULL)));
+}
+
+void Ut_MafwGstRenderer::testStamping()
+{
+ // start playing
+ MafwMediaInfo content("MafwTrackerSource::test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file:///home/user/MyDocs/test.play.uri";
+ content.setMetaData(map);
+
+ m_renderer->doPlay(content);
+
+ QVERIFY( m_renderer->m_playedStamped==false );
+ QTest::qWait(5200);
+ QVERIFY( m_renderer->m_playedStamped==true );
+ m_renderer->doStop();
+
+ //http uri
+ MafwMediaInfo content2("MafwTrackerSource::test_uuid2");
+ QMap<QString,QList<QVariant> > map2;
+ map2[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content2.setMetaData(map2);
+
+ m_renderer->doPlay(content2);
+
+ QVERIFY( m_renderer->m_playedStamped==false );
+ QTest::qWait(5200);
+ QVERIFY( m_renderer->m_playedStamped==false );
+ m_renderer->doStop();
+
+ // play uri case (no uuid)
+ MafwMediaInfo content3;
+ QMap<QString,QList<QVariant> > map3;
+ map3[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file://test.play.uri";
+ content3.setMetaData(map3);
+
+ m_renderer->doPlay(content3);
+
+ QVERIFY( m_renderer->m_playedStamped==false );
+ QTest::qWait(5200);
+ QVERIFY( m_renderer->m_playedStamped==true );
+ m_renderer->doStop();
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWhenPlaying()
+{
+ MafwMediaInfo content("test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing); //should be playing now
+
+ NetworkStubHelper::currentCreatedConfigIsValid = true;
+ QNetworkConfiguration config;
+
+ global_worker_stop_called = 0;
+ networkStub.emitConfigurationChange(config,
+ QNetworkConfiguration::Active);
+ QVERIFY(global_worker_playing);
+ QCOMPARE(global_worker_uri, "http://test.play.uri");
+ QCOMPARE(global_worker_stop_called, 1);
+
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file://test.play.uri";
+ content.setMetaData(map);
+
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing); //should be playing now
+
+ //another network config is activated
+ QNetworkConfiguration config2;
+ networkStub.emitConfigurationChange(config2,
+ QNetworkConfiguration::Active);
+
+ QVERIFY(global_worker_playing); //should keep playing as URI is file://
+
+ m_renderer->doStop();
+ QVERIFY(!global_worker_playing);
+
+ //checks that activating new network config stops play when streaming
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing);
+
+ QNetworkConfiguration config3;
+ global_worker_stop_called = 0;
+ networkStub.emitConfigurationChange(config3, QNetworkConfiguration::Active);
+ QCOMPARE(global_worker_uri, "http://test.play.uri");
+ QCOMPARE(global_worker_stop_called, 1);
+ QVERIFY(global_worker_playing);
+
+ //checks that deactivating the current configuration stops playback
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing);
+ networkStub.emitConfigurationChange(config3, QNetworkConfiguration::Discovered);
+ QVERIFY(!global_worker_playing);
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWithNoPlaylistFileUtil()
+{
+ delete m_renderer->m_playlistFileUtil;
+ m_renderer->m_playlistFileUtil = 0;
+ testNetworkChangesWhenPlaying();
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWhenPaused()
+{
+ MafwMediaInfo content("test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+
+ QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+ QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+ QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+ QSignalSpy resumeSpy(m_renderer, SIGNAL(rendererResumed()));
+
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing); //should be playing now
+
+ m_renderer->doPause();
+
+ QCOMPARE(playSpy.size(), 1);
+ playSpy.clear();
+ QCOMPARE(pauseSpy.size(), 1);
+ pauseSpy.clear();
+ QVERIFY(!global_worker_playing); //should be playing now
+
+ global_position = 313;
+ QNetworkConfiguration config;
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+
+ QVERIFY(!global_worker_playing);
+ QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+
+ QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Paused);
+ QCOMPARE(m_renderer->m_haltState.m_position, 313);
+ QCOMPARE(m_renderer->m_haltState.m_uri, QString("http://test.play.uri"));
+
+ QCOMPARE(stopSpy.size(), 0);
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 0);
+
+ global_worker_seek_request = 0;
+
+ m_renderer->doResume();
+
+ QCOMPARE(stopSpy.size(), 0);
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 1);
+
+ QVERIFY(global_worker_playing);
+
+ QCOMPARE(QString(global_worker_uri), QString("http://test.play.uri"));
+ QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+ QVERIFY(!m_renderer->m_haltState.isSet());
+
+ QCOMPARE(global_worker_seek_request, 313);
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWhenPausedAndRendererStopped()
+{
+ MafwMediaInfo content("test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.play.uri";
+ content.setMetaData(map);
+
+ QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+ QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+ QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing); //should be playing now
+
+ m_renderer->doPause();
+
+ QCOMPARE(playSpy.size(), 1);
+ playSpy.clear();
+ QCOMPARE(pauseSpy.size(), 1);
+ pauseSpy.clear();
+ QVERIFY(!global_worker_playing); //should be playing now
+
+ global_position = 313;
+ QNetworkConfiguration config;
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+
+ m_renderer->doStop();
+ QCOMPARE(stopSpy.size(), 1);
+ QVERIFY(!m_renderer->m_haltState.isSet());
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesToInactiveAndPauseResumeRequested()
+{
+ QFETCH(int, resumeDelay);
+ MafwGstRendererHaltState::DECAY_TIME = 3;
+
+ MafwMediaInfo content("test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.resume-pause.uri";
+ content.setMetaData(map);
+
+ QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+ QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+ QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing); //should be playing now
+
+ QCOMPARE(playSpy.size(), 1);
+ playSpy.clear();
+
+ global_position = 999;
+ QNetworkConfiguration config;
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+ m_renderer->doPause();
+ QCOMPARE(pauseSpy.size(), 1);
+ pauseSpy.clear();
+
+ QVERIFY(m_renderer->m_haltState.isSet());
+ QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Paused);
+ QCOMPARE(m_renderer->m_haltState.m_position, 999);
+ QCOMPARE(m_renderer->m_haltState.m_uri, QString("http://test.resume-pause.uri"));
+
+ global_worker_seek_request = 0;
+
+ QTest::qWait(resumeDelay);
+
+ m_renderer->doResume();
+ QCOMPARE(global_worker_seek_request, 999);
+ QVERIFY(global_worker_playing); //should be playing yeah there's no network but it will try
+ QVERIFY(!m_renderer->m_haltState.isSet());
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesToInactiveAndPauseResumeRequested_data()
+{
+ QTest::addColumn<int>("resumeDelay");
+ QTest::newRow("short delay") << 1000;
+ QTest::newRow("same as decay") << 3000;
+ QTest::newRow("longer than decay") << 5000;
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesWithPlaylistURI()
+{
+ QStringList playlistUris = QStringList() << "http://test.uriplaylist.item/1" << "http://test.uriplaylist.item/2";
+ stubPlaylistFileUtilityUris.clear();
+ stubPlaylistFileUtilityUris = playlistUris;
+
+ MafwMediaInfo content("test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.playlist.m3u"; //does not matter
+ map[MAFW_METADATA_KEY_MIME] = QList<QVariant>() << "audio/x-scpls";
+ content.setMetaData(map);
+
+ QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+ QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+ QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+ QSignalSpy resumeSpy(m_renderer, SIGNAL(rendererResumed()));
+
+ m_renderer->doPlay(content);
+
+ //time to parse the playlist
+ QTest::qWait(75);
+
+ QVERIFY(global_worker_playing); //should be playing now
+
+ QCOMPARE(playSpy.size(), 1);
+ playSpy.clear();
+
+ global_position = 007;
+ global_worker_stop_called = 0;
+
+ NetworkStubHelper::currentCreatedConfigIsValid = false;
+ QNetworkConfiguration config;
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+ QVERIFY(!global_worker_playing);
+ QCOMPARE(global_worker_stop_called, 1);
+ QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+
+ QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Playing);
+ QCOMPARE(m_renderer->m_haltState.m_position, 007);
+ QCOMPARE(m_renderer->m_haltState.m_uri, playlistUris.at(0));
+
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(stopSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 0);
+
+ global_worker_seek_request = 0;
+
+ NetworkStubHelper::currentCreatedConfigIsValid = true;
+ QNetworkConfiguration configActive;
+ networkStub.emitConfigurationChange(configActive, QNetworkConfiguration::Active);
+
+ QVERIFY(global_worker_playing);
+ QCOMPARE(global_worker_seek_request, 007);
+
+ QCOMPARE(stopSpy.size(), 0);
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 0);
+
+ QCOMPARE(QString(global_worker_uri), playlistUris.at(0));
+ QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+ QVERIFY(!m_renderer->m_haltState.isSet());
+
+ //Test that next uri is started to play if playing first stops because of an error
+ GError* error = g_error_new_literal(1, 2, "Playlist uri playback error");
+ m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, m_renderer, error);
+ QTest::qWait(10);
+
+ QVERIFY(global_worker_playing);
+ QCOMPARE(stopSpy.size(), 0);
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 0);
+
+ QCOMPARE(QString(global_worker_uri), playlistUris.at(1));
+
+ m_renderer->doStop();
+ QVERIFY(!global_worker_playing);
+ QCOMPARE(stopSpy.size(), 1);
+
+ g_error_free(error);
+}
+
+void Ut_MafwGstRenderer::testNetworkChangesHaltStateDecay()
+{
+ MafwGstRendererHaltState::DECAY_TIME = 4;
+
+ MafwMediaInfo content("test_uuid");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "http://test.decay.uri";
+ content.setMetaData(map);
+
+ QSignalSpy pauseSpy(m_renderer, SIGNAL(rendererPaused()));
+ QSignalSpy stopSpy(m_renderer, SIGNAL(rendererStopped()));
+ QSignalSpy playSpy(m_renderer, SIGNAL(rendererPlaying(int)));
+ QSignalSpy resumeSpy(m_renderer, SIGNAL(rendererResumed()));
+
+ m_renderer->doPlay(content);
+ QVERIFY(global_worker_playing); //should be playing now
+
+ QCOMPARE(playSpy.size(), 1);
+ playSpy.clear();
+
+ global_position = 313;
+ NetworkStubHelper::currentCreatedConfigIsValid = false;
+ QNetworkConfiguration config;
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+ QVERIFY(!global_worker_playing);
+ QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::CurrentUri);
+
+ QCOMPARE(m_renderer->m_haltState.m_state, MafwRenderer::Playing);
+ QCOMPARE(m_renderer->m_haltState.m_position, 313);
+ QCOMPARE(m_renderer->m_haltState.m_uri, QString("http://test.decay.uri"));
+
+ QCOMPARE(stopSpy.size(), 0);
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 0);
+
+ global_worker_stop_called = 0;
+ QTest::qWait(MafwGstRendererHaltState::DECAY_TIME * 1000 + 1000);
+
+ global_worker_stop_called = 1;
+ QCOMPARE(stopSpy.size(), 1);
+ stopSpy.clear();
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 0);
+
+ QVERIFY(!m_renderer->m_haltState.isSet());
+
+ global_worker_seek_request = 0;
+ global_worker_stop_called = 0;
+ NetworkStubHelper::currentCreatedConfigIsValid = true;
+ QNetworkConfiguration config2;
+ networkStub.emitConfigurationChange(config2, QNetworkConfiguration::Active);
+
+ QCOMPARE(stopSpy.size(), 0);
+ QCOMPARE(pauseSpy.size(), 0);
+ QCOMPARE(playSpy.size(), 0);
+ QCOMPARE(resumeSpy.size(), 0);
+
+ QVERIFY(!global_worker_playing);
+
+ global_worker_stop_called = 0;
+ QCOMPARE(m_renderer->m_playingItem, MafwBasicRenderer::UnknownUri);
+ QVERIFY(!m_renderer->m_haltState.isSet());
+
+ QCOMPARE(global_worker_seek_request, 0);
+}
+
+void Ut_MafwGstRenderer::testMmc()
+{
+ QVERIFY(!global_worker_playing);
+
+ MafwGstRenderer *rnd = new MafwGstRenderer("renderer_uuid", "renderer-plugin", "rendere_name");
+ m_stubHelper->expect("initialize", true);
+ QVERIFY(rnd->initialize(0) == true);
+
+ // MMC not mounted at first case
+
+ QSignalSpy errorSpy( rnd, SIGNAL( rendererError(const MafwError&) ) );
+ stubMmcMounted = false;
+ MafwMediaInfo content("test_uuid_xyz");
+ QMap<QString,QList<QVariant> > map;
+ map[MAFW_METADATA_KEY_URI] = QList<QVariant>() << "file:///home/user/MyDocs/rock.mp3";
+ content.setMetaData(map);
+
+ rnd->doPlay(content);
+ QVERIFY(!global_worker_playing);
+ QCOMPARE( errorSpy.size(), 1 );
+ MafwError err=errorSpy[0][0].value<MafwError>();
+ QVERIFY( err.code()==MafwError::RendererError_MmcNotAvailable );
+
+ // MMC unmounted during play
+
+ stubMmcMounted = true;
+ errorSpy.clear();
+
+ rnd->doPlay(content);
+ QVERIFY(global_worker_playing);
+
+ Q_EMIT stubMmcMonitor->preUnmountEvent("pre-unmount");
+ QTest::qWait(100);
+ QVERIFY(!global_worker_playing);
+ QVERIFY( errorSpy.size()==1 );
+
+ // Playlist first not available
+
+ stubPlaylistFileUtilityUris.clear();
+ stubPlaylistFileUtilityUris << "file:///home/user/MyDocs/rock.mp3";
+ stubPlaylistFileUtilityUris << "file:///home/user/MyDocs/rock2.mp3";
+ errorSpy.clear();
+ stubMmcMounted = false;
+
+ MafwMediaInfo mediaInfo;
+ QMap<QString, QVariant> testUri;
+ QMap<QString, QVariant> testMimeType;
+ testUri.insert(MAFW_METADATA_KEY_URI, "file:///var/tmp/tunein-station.pls");
+ testMimeType.insert(MAFW_METADATA_KEY_MIME, "audio/x-scpls");
+ mediaInfo.setMetaData(testUri);
+ mediaInfo.setMetaData(testMimeType);
+
+ rnd->doPlay(mediaInfo);
+ QTest::qWait(10);
+ QVERIFY(!global_worker_playing);
+ QCOMPARE( errorSpy.size(), 1 );
+ err=errorSpy[0][0].value<MafwError>();
+ QVERIFY( err.code()==MafwError::RendererError_MmcNotAvailable );
+
+ // Playlist play first, second not available
+
+ errorSpy.clear();
+ stubMmcMounted = true;
+
+ rnd->doPlay(mediaInfo);
+ QTest::qWait(10);
+ QVERIFY(global_worker_playing);
+
+ stubMmcMounted = false;
+ // cause next
+ GError* error = g_error_new_literal(1, 2, "Playlist uri playback error");
+ m_renderer->m_worker->notify_error_handler(m_renderer->m_worker, rnd, error);
+ errorSpy.clear();
+
+ QTest::qWait(10);
+ QCOMPARE( errorSpy.size(), 1 );
+ err=errorSpy[0][0].value<MafwError>();
+ QVERIFY( err.code()==MafwError::RendererError_MmcNotAvailable );
+ QVERIFY(!global_worker_playing);
+
+ g_error_free(error);
+
+ delete rnd;
+}
+
+void Ut_MafwGstRenderer::play_result(const MafwError& /*error*/, MafwRenderer& /*rndr*/)
+{
+ qDebug() << "Ut_MafwGstRenderer::play_result";
+
+}
+
+void Ut_MafwGstRenderer::positionChanged(uint position)
+{
+ m_position = position;
+}
+
+void Ut_MafwGstRenderer::positionError(const MafwError& error)
+{
+ m_error = error;
+}
+
+void Ut_MafwGstRenderer::propertyChanged(const QString& name, const QVariant& value)
+{
+ m_name = name;
+ m_value = value;
+}
+
+void Ut_MafwGstRenderer::media_info_result(const MafwMediaInfo& mediaInfo)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+ qDebug() << "m_name:" << m_name;
+
+ m_media_values.clear();
+
+ if(m_name == "all")
+ {
+ m_media_values = mediaInfo.metaData(MAFW_METADATA_KEY_URI);
+ }
+ else
+ {
+ m_media_values = mediaInfo.metaData(m_name);
+ }
+
+ qDebug() << "m_media_values.size():" << m_media_values.size();
+ Q_FOREACH(QVariant v, m_media_values)
+ {
+ qDebug() << "value:" << v;
+ }
+}
+
+void gst_init(int *argc, char **argv[])
+{
+ Q_UNUSED(argc);
+ Q_UNUSED(argv);
+}
+
+QTEST_MAIN(Ut_MafwGstRenderer)
+
+//Volume stub
+MafwGstRendererVolume::MafwGstRendererVolume()
+{
+ qDebug() << "Volume stub ctor";
+}
+
+void MafwGstRendererVolume::connectToPulseAudio()
+{
+}
+
+MafwGstRendererVolume::~MafwGstRendererVolume()
+{
+}
+
+uint MafwGstRendererVolume::getVolume()
+{
+ qDebug(__PRETTY_FUNCTION__);
+ return (uint)1;
+}
+
+bool MafwGstRendererVolume::setVolume (uint value)
+{
+ Q_UNUSED(value);
+ return true;
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERER_H_
+#define UT_MAFWGSTRENDERER_H_
+
+#include <QtTest/QtTest>
+#include <MafwError.h>
+#include <contextsubscriber/contextproperty.h>
+
+class MafwInternalRegistry;
+class MafwGstRenderer;
+class MafwRenderer;
+class MafwStubHelper;
+class MafwRendererPolicyStub;
+class MafwMediaInfo;
+
+Q_DECLARE_METATYPE(QVariant)
+Q_DECLARE_METATYPE(MafwError::Code)
+
+class Ut_MafwGstRenderer: public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void testPlayURI();
+ void testPlayPlaylistFile();
+ void testStop();
+ void testPause();
+ void testResume();
+ void testSeek();
+ void testErrorCodeScenarios();
+ void testErrorCodeScenarios_data();
+ void testNextHint();
+ void testPosition();
+ void testProperty();
+ void testProperty_data();
+ void testPlaybackSpeedProperty();
+ void testCallbacks();
+ void testDefaultConfiguration();
+ void testConfiguration();
+ void testGetCurrentMediaInfo();
+ void testGetCurrentMediaInfo_data();
+ void testBlankingPreventer();
+ void testPolicyPropertyHandler();
+ void testMediaRouting();
+ void testStamping();
+ void testNetworkChangesWhenPlaying();
+ void testNetworkChangesWithNoPlaylistFileUtil();
+ void testNetworkChangesWhenPaused();
+ void testNetworkChangesWhenPausedAndRendererStopped();
+ void testNetworkChangesToInactiveAndPauseResumeRequested();
+ void testNetworkChangesToInactiveAndPauseResumeRequested_data();
+ void testNetworkChangesHaltStateDecay();
+ void testNetworkChangesWithPlaylistURI();
+ void testMmc();
+
+ /**
+ * @param error The status of the completed request.
+ * @param rndr Reference to instance of MafwRenderer invoked the callback slot
+ */
+ void play_result(const MafwError& error, MafwRenderer& rndr);
+
+ void positionChanged(uint position);
+ void positionError(const MafwError& error);
+ void media_info_result(const MafwMediaInfo& mediaInfo);
+
+protected Q_SLOTS:
+ void propertyChanged(const QString& name, const QVariant& value);
+
+private:
+
+ MafwGstRenderer* m_renderer;
+ MafwStubHelper* m_stubHelper;
+ MafwRendererPolicyStub* m_rendererPolicy;
+ MafwError m_error;
+ uint m_position;
+ QVariant m_value;
+ QString m_name;
+ QList<QVariant> m_media_values;
+ int m_metadataCount;
+ ContextProperty *m_videoRoute;
+};
+
+#endif /*UT_MAFWGSTRENDERER_H_*/
--- /dev/null
+TEMPLATE = app
+TARGET =
+INCLUDEPATH += .
+QT += network
+QT -= gui
+
+CONFIG = console
+
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR \
+ $$UT_COMMONDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG += qtestlib no_keywords
+CONFIG += qt link_pkgconfig debug
+
+PKGCONFIG += qmafw glib-2.0 gobject-2.0
+PKGCONFIG += contextprovider-1.0 x11 gq-gconf gstreamer-tag-0.10 libpulse-mainloop-glib
+PKGCONFIG += qmsystem2 contextsubscriber-1.0
+
+LIBS += -lgcov
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror $$system(pkg-config --cflags-only-I QtSparql)
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += Ut_MafwGstRenderer.h \
+ MafwGstRenderer.h \
+ MafwGstRendererVolume.h \
+ MafwGstRendererDolby.h \
+ MafwBlankingPreventer.h \
+ MafwGstRendererNetworkMonitor.h \
+ mafw-gst-renderer-worker.h \
+ mafw-gst-renderer-utils.h \
+ MafwGstRendererPlaylistFileUtility.h \
+ $$UT_COMMONDIR/MafwStubHelper.h \
+ $$UT_COMMONDIR/MafwRendererPolicyStub.h \
+ $$UT_COMMONDIR/QNetworkStubs.h \
+ /usr/include/qt4/QtNetwork/qnetworkconfigmanager.h \
+ MafwMmcMonitor.h \
+ MafwGstScreenshot.h \
+ MafwGstRendererHaltState.h
+
+SOURCES += QmSystemStub.cpp \
+ QSettingsStub.cpp \
+ Ut_MafwGstRenderer.cpp \
+ MafwGstRenderer.cpp \
+ MafwGstRendererDolbyStub.cpp \
+ MafwBlankingPreventer.cpp \
+ MafwGstRendererNetworkMonitor.cpp \
+ mafw-gst-renderer-utils.c \
+ $$UT_COMMONDIR/MafwStubHelper.cpp \
+ $$UT_COMMONDIR/renderer-worker-stub.c \
+ $$UT_COMMONDIR/MafwBasicRendererStub.cpp \
+ $$UT_COMMONDIR/MafwRendererPolicyStub.cpp \
+ $$UT_COMMONDIR/LibCredsStub.cpp \
+ $$UT_COMMONDIR/MafwPlaylistFileUtilityStub.cpp \
+ ContextFWStub.cpp \
+ $$UT_COMMONDIR/QNetworkStubs.cpp \
+ MafwMmcMonitorStub.cpp \
+ MafwGstScreenshot.cpp \
+ MafwGstRendererHaltState.cpp
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include "ut_MafwGstRendererDolby.h"
+
+#include <QDebug>
+#include <QVariant>
+
+#include "MafwGstRendererDolby.h"
+
+void Ut_MafwGstRendererDolby::initTestCase()
+{
+ m_dolby = new MafwGstRendererDolby(this);
+ m_dolby->initialize();
+ delete m_dolby;
+ m_dolby = new MafwGstRendererDolby(this);
+ m_dolby->initialize();
+}
+
+void Ut_MafwGstRendererDolby::cleanupTestCase()
+{
+ delete m_dolby;
+}
+
+void Ut_MafwGstRendererDolby::testDolby()
+{
+ m_dolby->setMusicDolbyState(0);
+ QCOMPARE(m_dolby->getMusicDolbyState(), (uint)0);
+ m_dolby->setMusicDolbyState(1);
+ QCOMPARE(m_dolby->getMusicDolbyState(), (uint)1);
+ m_dolby->setMusicDolbyState(2);
+ QCOMPARE(m_dolby->getMusicDolbyState(), (uint)2);
+ m_dolby->setMusicDolbyState(3);
+ QCOMPARE(m_dolby->getMusicDolbyState(), (uint)0);
+
+ m_dolby->setMusicDolbyRoom(-1);
+ QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)0);
+ m_dolby->setMusicDolbyRoom(0);
+ QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)0);
+ m_dolby->setMusicDolbyRoom(1);
+ QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)1);
+ m_dolby->setMusicDolbyRoom(2);
+ QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)2);
+ m_dolby->setMusicDolbyRoom(3);
+ QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)3);
+ m_dolby->setMusicDolbyRoom(4);
+ QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)4);
+ m_dolby->setMusicDolbyRoom(5);
+ QCOMPARE(m_dolby->getMusicDolbyRoom(), (int)4);
+
+ m_dolby->setMusicDolbyColor(-1);
+ QCOMPARE(m_dolby->getMusicDolbyColor(), (int)0);
+ m_dolby->setMusicDolbyColor(0);
+ QCOMPARE(m_dolby->getMusicDolbyColor(), (int)0);
+ m_dolby->setMusicDolbyColor(1);
+ QCOMPARE(m_dolby->getMusicDolbyColor(), (int)1);
+ m_dolby->setMusicDolbyColor(2);
+ QCOMPARE(m_dolby->getMusicDolbyColor(), (int)2);
+ m_dolby->setMusicDolbyColor(3);
+ QCOMPARE(m_dolby->getMusicDolbyColor(), (int)3);
+ m_dolby->setMusicDolbyColor(4);
+ QCOMPARE(m_dolby->getMusicDolbyColor(), (int)4);
+ m_dolby->setMusicDolbyColor(5);
+ QCOMPARE(m_dolby->getMusicDolbyColor(), (int)4);
+
+ m_dolby->setVideoDolbyState(0);
+ QCOMPARE(m_dolby->getVideoDolbyState(), (uint)0);
+ m_dolby->setVideoDolbyState(1);
+ QCOMPARE(m_dolby->getVideoDolbyState(), (uint)1);
+ m_dolby->setVideoDolbyState(2);
+ QCOMPARE(m_dolby->getVideoDolbyState(), (uint)2);
+ m_dolby->setVideoDolbyState(3);
+ QCOMPARE(m_dolby->getVideoDolbyState(), (uint)0);
+
+ m_dolby->setVideoDolbyRoom(-1);
+ QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)0);
+ m_dolby->setVideoDolbyRoom(0);
+ QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)0);
+ m_dolby->setVideoDolbyRoom(1);
+ QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)1);
+ m_dolby->setVideoDolbyRoom(2);
+ QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)2);
+ m_dolby->setVideoDolbyRoom(3);
+ QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)3);
+ m_dolby->setVideoDolbyRoom(4);
+ QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)4);
+ m_dolby->setVideoDolbyRoom(5);
+ QCOMPARE(m_dolby->getVideoDolbyRoom(), (int)4);
+
+ m_dolby->setVideoDolbyColor(-1);
+ QCOMPARE(m_dolby->getVideoDolbyColor(), (int)0);
+ m_dolby->setVideoDolbyColor(0);
+ QCOMPARE(m_dolby->getVideoDolbyColor(), (int)0);
+ m_dolby->setVideoDolbyColor(1);
+ QCOMPARE(m_dolby->getVideoDolbyColor(), (int)1);
+ m_dolby->setVideoDolbyColor(2);
+ QCOMPARE(m_dolby->getVideoDolbyColor(), (int)2);
+ m_dolby->setVideoDolbyColor(3);
+ QCOMPARE(m_dolby->getVideoDolbyColor(), (int)3);
+ m_dolby->setVideoDolbyColor(4);
+ QCOMPARE(m_dolby->getVideoDolbyColor(), (int)4);
+ m_dolby->setVideoDolbyColor(5);
+ QCOMPARE(m_dolby->getVideoDolbyColor(), (int)4);
+}
+
+QTEST_MAIN(Ut_MafwGstRendererDolby)
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERDOLBY_H_
+#define UT_MAFWGSTRENDERERDOLBY_H_
+
+#include <QtTest/QtTest>
+
+class MafwGstRendererDolby;
+
+class Ut_MafwGstRendererDolby: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void testDolby();
+
+private:
+
+ MafwGstRendererDolby* m_dolby;
+};
+
+#endif /*UT_MAFWGSTRENDERERDOLBY_H_*/
--- /dev/null
+TEMPLATE = app
+TARGET =
+QT -= gui
+CONFIG = console
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+INCLUDEPATH += $$MAFW_GST_INCDIR \
+ $$UT_COMMONDIR
+DEPENDPATH += . \
+ ../../inc \
+ ../../src
+CONFIG += qtestlib \
+ qt \
+ link_pkgconfig \
+ debug
+PKGCONFIG += qmafw \
+ gq-gconf \
+ libpulse-mainloop-glib
+LIBS += -lgcov \
+ -ldbus-qeventloop
+QMAKE_CXXFLAGS += -fprofile-arcs \
+ -ftest-coverage \
+ -O0 -Werror
+QMAKE_CFLAGS += -fprofile-arcs \
+ -ftest-coverage \
+ -O0 -Werror
+
+# Input
+HEADERS += ut_MafwGstRendererDolby.h \
+ MafwGstRendererDolby.h
+SOURCES += ut_MafwGstRendererDolby.cpp \
+ MafwGstRendererDolby.cpp
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include "ut_MafwGstRendererNetworkMonitor.h"
+#include "MafwGstRendererNetworkMonitor.h"
+#include "QNetworkStubs.h"
+
+#include <QSignalSpy>
+#include <QDebug>
+
+extern NetworkStubHelper networkStub;
+
+void Ut_MafwGstRendererNetworkMonitor::initTestCase()
+{
+
+}
+
+void Ut_MafwGstRendererNetworkMonitor::cleanupTestCase()
+{
+
+}
+
+void Ut_MafwGstRendererNetworkMonitor::testPrepareNetworkChangeSignal()
+{
+ MafwGstRendererNetworkMonitor monitor;
+ QNetworkConfiguration config;
+
+ QSignalSpy networkChangeFinished(&monitor, SIGNAL(networkChangeFinished()));
+
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+
+ QCOMPARE(networkChangeFinished.size(), 1);
+}
+
+void Ut_MafwGstRendererNetworkMonitor::testOfflineSignal()
+{
+ networkStub.currentCreatedConfigIsValid = false;
+ MafwGstRendererNetworkMonitor monitor;
+ networkStub.currentCreatedConfigIsValid = true;
+
+ QSignalSpy prepareNetworkChangeSpy(&monitor, SIGNAL(prepareNetworkChange()));
+
+ QNetworkConfiguration config;
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+ QCOMPARE(prepareNetworkChangeSpy.size(), 1);
+
+ //first activate
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+ //then set it not active
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+ QCOMPARE(prepareNetworkChangeSpy.size(), 2);
+
+}
+
+void Ut_MafwGstRendererNetworkMonitor::testConfigChanges()
+{
+ MafwGstRendererNetworkMonitor monitor;
+ QSignalSpy networkChangeSpy(&monitor, SIGNAL(prepareNetworkChange()));
+ QSignalSpy networkChangeFinished(&monitor, SIGNAL(networkChangeFinished()));
+
+ QNetworkConfiguration config;
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Active);
+ QNetworkConfiguration config2;
+ networkStub.emitConfigurationChange(config2, QNetworkConfiguration::Active);
+ networkStub.emitConfigurationChange(config, QNetworkConfiguration::Discovered);
+
+ QCOMPARE(networkChangeFinished.size(), 2);
+ QCOMPARE(networkChangeSpy.size(), 0);
+
+ networkStub.emitConfigurationChange(config2, QNetworkConfiguration::Discovered);
+ QCOMPARE(networkChangeSpy.size(), 1);
+}
+
+QTEST_MAIN(Ut_MafwGstRendererNetworkMonitor)
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERNETWORKMONITOR_H_
+#define UT_MAFWGSTRENDERERNETWORKMONITOR_H_
+
+#include <QtTest/QtTest>
+
+
+class Ut_MafwGstRendererNetworkMonitor: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void testPrepareNetworkChangeSignal();
+ void testOfflineSignal();
+ void testConfigChanges();
+};
+
+#endif /*UT_MAFWGSTRENDERERNETWORKMONITOR_H_*/
--- /dev/null
+TEMPLATE = app
+TARGET =
+CONFIG = console
+QT -= gui
+
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR $$UT_COMMONDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG += qtestlib qt link_pkgconfig debug
+PKGCONFIG += qmafw
+LIBS += -lgcov
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+
+# Input
+HEADERS += ut_MafwGstRendererNetworkMonitor.h \
+ MafwGstRendererNetworkMonitor.h \
+ /usr/include/qt4/QtNetwork/qnetworkconfigmanager.h \
+ $$UT_COMMONDIR/QNetworkStubs.h
+
+SOURCES += ut_MafwGstRendererNetworkMonitor.cpp \
+ MafwGstRendererNetworkMonitor.cpp \
+ $$UT_COMMONDIR/QNetworkStubs.cpp
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <MafwInternalRegistry.h>
+#include <MafwRenderer.h>
+#include <QVariant>
+#include <QtTest/QtTest>
+#include <glib-object.h>
+#include <QSettings>
+
+#include "Ut_MafwGstRendererPlugin.h"
+#include "MafwGstRendererPlugin.h"
+#include "MafwGstRenderer.h"
+#include "MafwGstRendererVolume.h"
+#include "MafwGstRendererDolby.h"
+#include "../common/MafwStubHelper.h"
+
+Q_DECLARE_METATYPE(MafwRenderer*)
+
+extern void setStubHelper(MafwStubHelper* stubHlp);
+QMap<QString,QString> renderers;
+int renderer_index = 0;
+
+void Ut_MafwGstRendererPlugin::initTestCase()
+{
+ qRegisterMetaType<MafwRenderer*>();
+ m_stubHelper = new MafwStubHelper;
+ setStubHelper(m_stubHelper);
+
+ m_plugin = new MafwGstRendererPlugin();
+}
+
+void Ut_MafwGstRendererPlugin::testInProcess()
+{
+ QSignalSpy addedSpy( MafwRegistry::instance(), SIGNAL(rendererAdded(const QString&, const QString&)) );
+ QSignalSpy removedSpy( MafwRegistry::instance(), SIGNAL(rendererRemoved(const QString&, const QString&)) );
+ //MafwBasicRenderer::initialize is called twice:
+ //from its own constructor and from MafwGstRenderer::initialize
+
+ //Basic renderer initialize fails
+ m_stubHelper->expect("initialize", false);
+ m_stubHelper->expect("initialize", false);
+ m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+ QCOMPARE( addedSpy.size(), 0 );
+ addedSpy.clear();
+ removedSpy.clear();
+
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("initialize", true);
+ m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+ QCOMPARE( addedSpy.size(), 1 );
+ QCOMPARE( removedSpy.size(), 0 );
+ QVariantList arguments = addedSpy.takeFirst();
+
+ QString uuid = arguments.at(0).toString();
+ QCOMPARE(uuid, QString("mafw_gst_renderer"));
+ QCOMPARE(arguments.at(1).toString(), QString("QMAFW GStreamer Renderer"));
+
+ MafwRenderer* rnd = MafwRegistry::instance()->renderer(uuid);
+ QVERIFY(rnd != 0);
+ QCOMPARE(rnd->pluginName(), m_plugin->name());
+
+ MafwInternalRegistry::internalInstance()->removeExtension(uuid);
+ QCOMPARE( removedSpy.size(), 1 );
+}
+
+void Ut_MafwGstRendererPlugin::testOutProcess()
+{
+ QCoreApplication::setApplicationName("qmafw-dbus-wrapper");
+ //TODO empty settings case
+
+ renderers.insert("mafw-gst-renderer", "Mafw-GStreamer-Renderer");
+ renderers.insert("mafw-gst-video-suite-renderer", "Mafw-GStreamer-Renderer-For-Video");
+
+ QSignalSpy addedSpy( MafwRegistry::instance(), SIGNAL(rendererAdded(const QString&, const QString&)) );
+ QSignalSpy removedSpy( MafwRegistry::instance(), SIGNAL(rendererRemoved(const QString&, const QString&)) );
+ //MafwBasicRenderer::initialize is called twice:
+ //from its own constructor and from MafwGstRenderer::initialize
+
+ //Basic renderer initialize fails
+ m_stubHelper->expect("initialize", false);
+ m_stubHelper->expect("initialize", false);
+ m_stubHelper->expect("initialize", false);
+ m_stubHelper->expect("initialize", false);
+ m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+ QCOMPARE( addedSpy.size(), 0 );
+ addedSpy.clear();
+ removedSpy.clear();
+
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("initialize", true);
+ m_plugin->initialize( MafwInternalRegistry::internalInstance() );
+ QCOMPARE( addedSpy.size(), 2 );
+ QCOMPARE( removedSpy.size(), 0 );
+
+ QVariantList arguments = addedSpy.takeFirst();
+ QString uuid1 = arguments.at(0).toString();
+ QString name1 = arguments.at(1).toString();
+ arguments = addedSpy.takeFirst();
+ QString uuid2 = arguments.at(0).toString();
+ QString name2 = arguments.at(1).toString();
+
+ MafwRenderer* rnd1 = MafwRegistry::instance()->renderer(uuid1);
+ QVERIFY(rnd1 != 0);
+ QCOMPARE(rnd1->pluginName(), m_plugin->name());
+ MafwRenderer* rnd2 = MafwRegistry::instance()->renderer(uuid2);
+ QVERIFY(rnd2 != 0);
+ QCOMPARE(rnd2->pluginName(), m_plugin->name());
+
+ QCOMPARE(uuid1, rnd1->uuid());
+ QCOMPARE(name1, rnd1->name());
+ QCOMPARE(uuid2, rnd2->uuid());
+ QCOMPARE(name2, rnd2->name());
+
+ MafwInternalRegistry::internalInstance()->removeExtension(uuid1);
+ MafwInternalRegistry::internalInstance()->removeExtension(uuid2);
+
+ // Test huge amount of renderers
+ renderers.clear();
+ addedSpy.clear();
+ removedSpy.clear();
+ for(int i = 0; i < 100; i++)
+ {
+ QString rndId = QString("rndId %1").arg(i);
+ QString rndName = QString("rndName %1").arg(i);
+ renderers.insert(rndId, rndName);
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("initialize", true);
+ }
+ m_plugin->initialize( MafwInternalRegistry::internalInstance());
+ QCOMPARE(removedSpy.size(), 0);
+ QCOMPARE(addedSpy.size(), 100);
+
+ // Let's only remove 99 renderers
+ for(int i = 0; i < 99; i++)
+ {
+ QString rndId = QString("rndId %1").arg(i);
+ MafwInternalRegistry::internalInstance()->removeExtension(rndId);
+ }
+ QCOMPARE(removedSpy.size(), 99);
+ // Check that there is still one renderer left
+ MafwRenderer* rnd99 = MafwRegistry::instance()->renderer("rndId 99");
+ QVERIFY(rnd99 != 0);
+ MafwInternalRegistry::internalInstance()->removeExtension("rndId 99");
+
+ addedSpy.clear();
+ removedSpy.clear();
+
+ //Test no renderers
+ renderers.clear();
+ m_plugin->initialize(MafwInternalRegistry::internalInstance());
+ QCOMPARE(addedSpy.size(), 0);
+
+ //Test 2 renderers with same uuid and name
+ renderers.insert("rndId1", "rndName1");
+ renderers.insert("rndId1", "rndName1");
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("initialize", true);
+ m_stubHelper->expect("initialize", false);
+ m_stubHelper->expect("initialize", false);
+ m_plugin->initialize( MafwInternalRegistry::internalInstance());
+ QCOMPARE(addedSpy.size(), 1);
+
+}
+
+void Ut_MafwGstRendererPlugin::cleanupTestCase()
+{
+ delete m_plugin;
+ while(QCoreApplication::hasPendingEvents())
+ {
+ QCoreApplication::sendPostedEvents();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+ }
+}
+
+void gst_init(int *argc, char **argv[])
+{
+ Q_UNUSED(argc);
+ Q_UNUSED(argv);
+}
+
+QTEST_MAIN(Ut_MafwGstRendererPlugin)
+
+//Volume stub
+MafwGstRendererVolume::MafwGstRendererVolume()
+{
+ qDebug() << "Volume stub ctor";
+}
+
+void MafwGstRendererVolume::connectToPulseAudio()
+{
+}
+
+MafwGstRendererVolume::~MafwGstRendererVolume()
+{
+}
+
+uint MafwGstRendererVolume::getVolume()
+{
+ qDebug(__PRETTY_FUNCTION__);
+ return (uint)1;
+}
+
+bool MafwGstRendererVolume::setVolume (uint value)
+{
+ Q_UNUSED(value);
+ return true;
+}
+
+//QSettings stub
+QSettings::QSettings( const QString&, const QString&, QObject* ){}
+//Hope we will never need below ctor stub, because it is used somehow by unit test framework.
+//QSettings::QSettings(QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(QSettings::Format, QSettings::Scope, const QString&, const QString&, QObject*){}
+QSettings::QSettings(const QString&, QSettings::Format, QObject*){}
+QSettings::QSettings(QObject*){}
+QSettings::~QSettings(){}
+
+QVariant QSettings::value(const QString& key, const QVariant& ) const
+{
+ if(renderers.size() == 0)
+ {
+ return QString();
+ }
+ QMap<QString, QString>::const_iterator renderers_iterator = renderers.constBegin();
+ for(int i = 0; i < renderer_index; i++)
+ {
+ renderers_iterator++;
+ }
+
+ if(key == "Id")
+ {
+ return renderers_iterator.key();
+ }
+ else
+ {
+ return renderers_iterator.value();
+ }
+}
+
+int QSettings::beginReadArray(const QString&)
+{
+ return renderers.count();
+}
+
+void QSettings::setArrayIndex(int i)
+{
+ renderer_index = i;
+}
+
+void QSettings::endArray()
+{
+}
+
+void QSettings::beginGroup(const QString &prefix)
+{
+ Q_UNUSED(prefix);
+}
+
+void QSettings::endGroup()
+{
+
+}
+
+bool QSettings::contains(const QString &key) const
+{
+ return true;
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERPLUGIN_H
+#define UT_MAFWGSTRENDERERPLUGIN_H
+
+#include <QObject>
+
+class MafwBasicRenderer;
+class MafwGstRendererPlugin;
+class MafwRenderer;
+class MafwStubHelper;
+
+class Ut_MafwGstRendererPlugin: public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS: // tests
+
+ void initTestCase();
+ void testInProcess();
+ void testOutProcess();
+ void cleanupTestCase();
+
+private:
+ MafwGstRendererPlugin* m_plugin;
+ MafwStubHelper* m_stubHelper;
+
+};
+
+#endif // UT_MAFWGSTRENDERERPLUGIN_H
--- /dev/null
+######################################################################
+# Automatically generated by qmake (2.01a) Thu Nov 19 11:32:17 2009
+######################################################################
+
+TEMPLATE = app
+QT += network
+QT -=gui
+
+CONFIG = console
+
+TARGET =
+MAFW_GST_INCDIR = ../../inc
+DEPENDPATH += . $$MAFW_GST_INCDIR ../../src
+INCLUDEPATH += . $$MAFW_GST_INCDIR /usr/include/qmafw
+
+CONFIG += qtestlib no_keywords
+CONFIG += qt link_pkgconfig debug
+PKGCONFIG += qmafw glib-2.0 gobject-2.0 gio-2.0 gio-unix-2.0 usb_moded QtSparql
+PKGCONFIG += contextprovider-1.0 x11 gstreamer-tag-0.10 gq-gconf libpulse-mainloop-glib qmsystem2 contextsubscriber-1.0
+LIBS += -lgcov
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += Ut_MafwGstRendererPlugin.h \
+ MafwGstRendererPlugin.h \
+ MafwGstRenderer.h \
+ MafwGstRendererVolume.h \
+ MafwGstRendererDolby.h \
+ MafwBlankingPreventer.h \
+ MafwGstRendererNetworkMonitor.h \
+ MafwGstRendererPlaylistFileUtility.h \
+ MafwMmcMonitor.h \
+ MafwGstScreenshot.h \
+ MafwGstRendererHaltState.h \
+ mafw-gst-renderer-worker.h \
+ mafw-gst-renderer-utils.h \
+ ../common/MafwStubHelper.h \
+ ../common/MafwRendererPolicyStub.h
+
+SOURCES += Ut_MafwGstRendererPlugin.cpp \
+ MafwGstRendererPlugin.cpp \
+ MafwGstRenderer.cpp \
+ MafwGstRendererDolby.cpp \
+ MafwGstRendererNetworkMonitor.cpp \
+ MafwBlankingPreventer.cpp \
+ MafwMmcMonitor.cpp \
+ MafwGstScreenshot.cpp \
+ MafwGstRendererHaltState.cpp \
+ mafw-gst-renderer-utils.c \
+ ../common/renderer-worker-stub.c \
+ ../common/MafwStubHelper.cpp \
+ ../common/MafwBasicRendererStub.cpp \
+ ../common/MafwRendererPolicyStub.cpp \
+ ../common/MafwPlaylistFileUtilityStub.cpp
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "ut_MafwGstRendererSeeker.h"
+
+#include <QDebug>
+
+Q_DECLARE_METATYPE(QList<qint64>);
+
+extern gint64 g_currentPosition;
+extern gint64 g_duration;
+extern gint64 g_seekRequested;
+extern gint g_seeksCalled;
+
+void Ut_MafwGstRendererSeeker::initTestCase()
+{
+ g_type_init();
+}
+
+void Ut_MafwGstRendererSeeker::cleanupTestCase()
+{
+}
+
+void Ut_MafwGstRendererSeeker::init()
+{
+ m_seeker = mafw_gst_renderer_seeker_new();
+ mafw_gst_renderer_seeker_set_pipeline(m_seeker, (GstElement*)(313));
+}
+
+void Ut_MafwGstRendererSeeker::cleanup()
+{
+ mafw_gst_renderer_seeker_free(m_seeker);
+
+ g_currentPosition = -1;
+ g_duration = -1;
+ g_seekRequested = -1;
+ g_seeksCalled = 0;
+}
+
+
+
+void Ut_MafwGstRendererSeeker::testSeekSuccess()
+{
+ QFETCH(qint64, startPosition);
+ QFETCH(qint64, seekTo);
+ QFETCH(qint64, seekGoesTo);
+ QFETCH(qint64, mediaDuration);
+
+ g_duration = mediaDuration;
+ g_currentPosition = startPosition;
+
+ mafw_gst_renderer_seeker_seek_to(m_seeker, seekTo);
+ QCOMPARE(g_seekRequested, seekTo);
+
+ g_currentPosition = seekGoesTo;
+
+ gint64 newSeekPos = mafw_gst_renderer_seeker_process(m_seeker);
+
+ // only one seek operation should be called when successful
+ QCOMPARE(g_seeksCalled, 1);
+ QCOMPARE(newSeekPos, -1ll);
+}
+
+void Ut_MafwGstRendererSeeker::testSeekSuccess_data()
+{
+ QTest::addColumn<qint64>("startPosition");
+ QTest::addColumn<qint64>("seekTo");
+ QTest::addColumn<qint64>("seekGoesTo");
+ QTest::addColumn<qint64>("mediaDuration");
+
+ QTest::newRow("1") << 0ll << 20ll << 21ll << 30ll;
+ QTest::newRow("1a") << 0ll << 19ll << 21ll << 30ll;
+ QTest::newRow("2") << 5ll << 1ll << 2ll << 10ll;
+ QTest::newRow("3") << 100ll << 150ll << 119ll << 120ll;
+
+ //intentionally messed values
+ QTest::newRow("weird1") << 4ll << 1ll << 1ll << 2ll;
+ QTest::newRow("weird2") << -13ll << 13ll << 12ll << 0ll;
+ QTest::newRow("weird2") << 10ll << 5ll << 4ll << 1ll;
+}
+
+
+void Ut_MafwGstRendererSeeker::testSeekFails()
+{
+ QFETCH(qint64, startPosition);
+ QFETCH(qint64, seekTo);
+ QFETCH(QList<qint64>, processedSeekRequests);
+ QFETCH(QList<qint64>, seekGoesTo);
+ QFETCH(qint64, mediaDuration);
+
+ g_duration = mediaDuration;
+ g_currentPosition = startPosition;
+
+ mafw_gst_renderer_seeker_seek_to(m_seeker, seekTo);
+ QCOMPARE(g_seekRequested, seekTo);
+
+ qint64 newSeekPos = 0;
+ int i = 0;
+
+ while( true )
+ {
+ g_currentPosition = seekGoesTo.at(i);
+ newSeekPos = mafw_gst_renderer_seeker_process(m_seeker);
+
+ if( newSeekPos == -1 )
+ {
+ break;
+ }
+
+ QCOMPARE(newSeekPos, processedSeekRequests.at(i));
+ QCOMPARE(g_seekRequested, processedSeekRequests.at(i));
+ ++i;
+ }
+
+ qint64 lastSeekPos = mafw_gst_renderer_seeker_process(m_seeker);
+ QCOMPARE( lastSeekPos, -1ll);
+ QCOMPARE( g_seeksCalled, seekGoesTo.size());
+}
+
+void Ut_MafwGstRendererSeeker::testSeekFails_data()
+{
+ QTest::addColumn<qint64>("startPosition");
+ QTest::addColumn<qint64>("seekTo");
+ QTest::addColumn<QList<qint64> >("processedSeekRequests");
+ QTest::addColumn<QList<qint64> >("seekGoesTo");
+ QTest::addColumn<qint64>("mediaDuration");
+
+ QTest::newRow("Second seek is close enough")
+ << 0ll // position where seeking start
+ << 20ll // the seek request
+ << (QList<qint64>() << 30 ) // list of processed seek request affected by the seekGoesTo list
+ << (QList<qint64>() << 1 << 31 ) // list of resulting seeks to gst_element_seek()
+ << 35ll; //affects when seek processing should stop
+
+ QTest::newRow("Fourth seek forward required")
+ << 5ll // position where seeking start
+ << 20ll // the seek request
+ << (QList<qint64>() << 30 << 40 << 50 ) // list of processed seek request affected by the seekGoesTo list
+ << (QList<qint64>() << 1 << 2 << 6 << 15 ) // list of resulting positions after calling gst_element_seek()
+ << 70ll; //affects when seek processing should stop
+
+ // backward seeks assume that key_frame seeks will always seek at least to the requested position most likely earlier
+ // such backward seeks that would not reach at least the required position succeed anyway
+ QTest::newRow("backward seek fails")
+ << 20ll // position where seeking start
+ << 10ll // the seek request
+ << (QList<qint64>() ) // list of processed seek request affected by the seekGoesTo list
+ << (QList<qint64>() << 0 ) // list of resulting positions after calling gst_element_seek()
+ << 70ll; //affects when seek processing should stop
+
+ QTest::newRow("backward seek fails 2")
+ << 20ll // position where seeking start
+ << 10ll // the seek request
+ << (QList<qint64>() ) // list of processed seek request affected by the seekGoesTo list
+ << (QList<qint64>() << 15 ) // list of resulting positions after calling gst_element_seek()
+ << 70ll; //affects when seek processing should stop
+
+ QTest::newRow("Seek over media duration cancelled when processing")
+ << 5ll // position where seeking start
+ << 20ll // the seek request
+ << (QList<qint64>()) // list of processed seek request affected by the seekGoesTo list
+ << (QList<qint64>() << 5 ) // list of resulting positions after calling gst_element_seek()
+ << 25ll; //affects when seek processing should stop
+
+ QTest::newRow("Test accuracy, first fails just by an inch")
+ << 5ll // position where seeking start
+ << 20ll // the seek request
+ << (QList<qint64>() << 30) // list of processed seek request affected by the seekGoesTo list
+ << (QList<qint64>() << 6 << 7) // list of resulting positions after calling gst_element_seek()
+ << 35ll; //affects when seek processing should stop
+
+ QTest::newRow("Test accuracy 1, first fails just by an inch")
+ << 5ll // position where seeking start
+ << 20ll // the seek request
+ << (QList<qint64>() << 30) // list of processed seek request affected by the seekGoesTo list
+ << (QList<qint64>() << 6 << 7) // list of resulting seeks to gst_element_seek()
+ << 35ll; //affects when seek processing should stop
+
+}
+
+
+QTEST_MAIN(Ut_MafwGstRendererSeeker)
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERSEEKER_H_
+#define UT_MAFWGSTRENDERERSEEKER_H_
+
+#include <QtTest/QtTest>
+
+#include "mafw-gst-renderer-seeker.h"
+
+class Ut_MafwGstRendererSeeker : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+ void testSeekSuccess();
+ void testSeekSuccess_data();
+ void testSeekFails();
+ void testSeekFails_data();
+
+
+private:
+ MafwGstRendererSeeker *m_seeker;
+};
+
+#endif /*UT_MAFWGSTRENDERERSEEKER_H_*/
--- /dev/null
+TEMPLATE = app
+QT -= gui
+CONFIG = console
+
+isEmpty(PREFIX) {
+ PREFIX=/usr
+}
+
+CONFIG += qt link_pkgconfig debug
+CONFIG += qtestlib
+PKGCONFIG += glib-2.0 gobject-2.0
+
+LIBS += -lgcov
+
+DEPENDPATH += . ../../src ../../inc
+INCLUDEPATH += . ../../inc $$system(pkg-config --variable=includedir gstreamer-0.10)
+
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g $$system(pkg-config --cflags gstreamer-0.10)
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g $$system(pkg-config --cflags gstreamer-0.10)
+
+QMAKE_CLEAN += *.gcda *.gcno *.gcov ut_MafwGstRendererSeeker *.vg.xml vgcore.*
+
+HEADERS += mafw-gst-renderer-seeker.h \
+ ut_MafwGstRendererSeeker.h
+
+SOURCES += mafw-gst-renderer-seeker.c \
+ ut_MafwGstRendererSeeker_stubs.c \
+ ut_MafwGstRendererSeeker.cpp
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <glib.h>
+
+#include <gst/gstelement.h>
+
+gint64 g_currentPosition;
+gint64 g_duration;
+gint64 g_seekRequested;
+gint g_seeksCalled;
+
+gboolean gst_element_query_position(GstElement *element,
+ GstFormat *format,
+ gint64 *value)
+{
+ *value = g_currentPosition * GST_SECOND;
+ return TRUE;
+}
+
+gboolean gst_element_query_duration(GstElement *element,
+ GstFormat *format,
+ gint64 *value)
+{
+ *value = g_duration * GST_SECOND;
+ return TRUE;
+}
+
+gboolean gst_element_seek(GstElement *element,
+ gdouble rate,
+ GstFormat format,
+ GstSeekFlags flags,
+ GstSeekType cur_type,
+ gint64 cur,
+ GstSeekType stop_type,
+ gint64 stop)
+{
+ g_seekRequested = cur / GST_SECOND;
+ ++g_seeksCalled;
+ return TRUE;
+}
--- /dev/null
+#include <QDebug>
+#include <QVariant>
+#include <dbus/dbus.h>
+#include <dbusconnectioneventloop.h>
+#include "MafwStubHelper.h"
+
+char obj_path[] = "/org/pulseaudio/stream_restore1/entry7";
+
+MafwStubHelper* m_stubHelper = 0;
+void* m_user_data;
+DBusHandleMessageFunction m_signalCb;
+DBusPendingCallNotifyFunction m_restoreObjectCb = 0;
+DBusPendingCallNotifyFunction m_volumeCb = 0;
+DBusMessage* m_getVolumeMethodCall = 0;
+DBusMessage* m_setVolumeMethod = 0;
+
+QMap<uint, uint> m_volumes;
+
+void setStubHelper(MafwStubHelper* stubHlp)
+{
+ m_stubHelper = stubHlp;
+}
+
+dbus_bool_t dbus_error_is_set(const DBusError* error)
+{
+ Q_UNUSED(error);
+ return m_stubHelper->getReturn("dbus_error_is_set").toBool();
+}
+
+struct DBusConnection
+{
+ int aField;
+};
+
+DBusConnection* dbus_connection_open(const char *address, DBusError *error)
+{
+ DBusConnection* conn = 0;
+
+ if (m_stubHelper->getReturn("dbus_connection_open").toBool())
+ {
+ conn = static_cast<DBusConnection*>( malloc(sizeof(DBusConnection)) );
+ }
+ Q_UNUSED(address);
+ Q_UNUSED(error);
+ return conn;
+}
+
+void dbus_connection_unref(DBusConnection* conn)
+{
+ if (conn)
+ {
+ free(conn);
+ }
+}
+
+bool DBUSConnectionEventLoop::addConnection(DBusConnection* conn)
+{
+ Q_UNUSED(conn);
+
+ return m_stubHelper->getReturn("addConnection").toBool();
+}
+
+void DBUSConnectionEventLoop::removeConnection(DBusConnection* conn)
+{
+ Q_UNUSED(conn);
+
+ m_stubHelper->getReturn("removeConnection");
+}
+
+dbus_bool_t dbus_connection_add_filter(DBusConnection* connection,
+ DBusHandleMessageFunction function,
+ void* user_data,
+ DBusFreeFunction free_data_function)
+{
+ Q_UNUSED(connection);
+ Q_UNUSED(free_data_function);
+ m_signalCb = function;
+ m_user_data = user_data;
+ return true;
+}
+
+void dbus_pending_call_cancel(DBusPendingCall* pending)
+{
+ Q_UNUSED(pending);
+}
+
+dbus_bool_t dbus_set_error_from_message(DBusError* error, DBusMessage* message)
+{
+ Q_UNUSED(error);
+ Q_UNUSED(message);
+ return m_stubHelper->getReturn("dbus_set_error_from_message").toBool();
+}
+
+void signalVolumeUpdated(uint channel, uint value)
+{
+ DBusMessage* message = dbus_message_new_signal(obj_path, "org.PulseAudio.Ext.StreamRestore1.RestoreEntry", "VolumeUpdated");
+
+ DBusMessageIter argument_iterator, variant_iterator, struct_iterator;
+ dbus_message_iter_init_append (message, &argument_iterator);
+ dbus_message_iter_open_container (&argument_iterator,
+ DBUS_TYPE_VARIANT,
+ "(uu)",
+ &variant_iterator);
+ dbus_message_iter_open_container (&variant_iterator,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iterator);
+
+ dbus_message_iter_append_basic (&struct_iterator, DBUS_TYPE_UINT32, &channel);
+ dbus_message_iter_append_basic (&struct_iterator, DBUS_TYPE_UINT32, &value);
+
+ dbus_message_iter_close_container (&variant_iterator, &struct_iterator);
+ dbus_message_iter_close_container (&argument_iterator, &variant_iterator);
+
+ DBusConnection* conn = 0;
+ (*m_signalCb)(conn, message, m_user_data);
+ dbus_message_unref(message);
+}
+
+struct DBusPendingCall
+{
+ uint a;
+};
+
+dbus_bool_t dbus_connection_send_with_reply(DBusConnection* connection,
+ DBusMessage* message,
+ DBusPendingCall ** pending_return,
+ int timeout_milliseconds)
+{
+ DBusPendingCall pending;
+ *pending_return = &pending;
+ Q_UNUSED(connection);
+ m_getVolumeMethodCall = message;
+ Q_UNUSED(pending_return);
+ Q_UNUSED(timeout_milliseconds);
+ return true;
+}
+
+// Saves callback function pointer. Assumes that first call gives callback for
+// GetEntryByName and the second one gives callback for Get Volume
+dbus_bool_t dbus_pending_call_set_notify( DBusPendingCall* pending,
+ DBusPendingCallNotifyFunction function,
+ void* user_data,
+ DBusFreeFunction free_user_data)
+{
+ if (!m_restoreObjectCb)
+ {
+ m_restoreObjectCb = function;
+ }
+ else
+ {
+ m_volumeCb = function;
+ }
+
+ Q_UNUSED(pending);
+ Q_UNUSED(user_data);
+ Q_UNUSED(free_user_data);
+ return true;
+}
+
+void giveRestoreEntryReply()
+{
+ DBusPendingCall pending;
+ (*m_restoreObjectCb) (&pending, m_user_data);
+}
+
+void giveVolumeReply(QMap<uint, uint> volumes)
+{
+ DBusPendingCall pending;
+ m_volumes = volumes;
+ (*m_volumeCb) (&pending, m_user_data);
+}
+
+DBusMessage* dbus_pending_call_steal_reply(DBusPendingCall* pending)
+{
+ Q_UNUSED(pending);
+ bool replyForGetVolume = dbus_message_has_member (m_getVolumeMethodCall, "Get");
+ DBusMessage* message = dbus_message_new_method_return(m_getVolumeMethodCall);
+
+ qDebug() << "replyForGetVolume= " << replyForGetVolume;
+ qDebug() << "m_volumes.count()= " << m_volumes.count();
+ if (replyForGetVolume)
+ {
+ qDebug() << "Jee";
+ DBusMessageIter argument_iterator, variant_iterator, array_iterator;
+ dbus_message_iter_init_append (message, &argument_iterator);
+ dbus_message_iter_open_container (&argument_iterator,
+ DBUS_TYPE_VARIANT,
+ "a(uu)",
+ &variant_iterator);
+ dbus_message_iter_open_container (&variant_iterator,
+ DBUS_TYPE_ARRAY,
+ "(uu)",
+ &array_iterator);
+ if (m_volumes.isEmpty())
+ {
+ qDebug() << "Stub is giving an invalid reply";
+ }
+ else
+ {
+ QMapIterator<uint, uint> i(m_volumes);
+ i.toBack();
+ while (i.hasPrevious())
+ {
+ DBusMessageIter iterator;
+ dbus_message_iter_open_container (&array_iterator,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &iterator);
+ i.previous();
+ dbus_message_iter_append_basic (&iterator, DBUS_TYPE_UINT32, &i.key());
+ dbus_message_iter_append_basic (&iterator, DBUS_TYPE_UINT32, &i.value());
+ dbus_message_iter_close_container (&array_iterator, &iterator);
+ }
+ }
+ dbus_message_iter_close_container (&variant_iterator, &array_iterator);
+ dbus_message_iter_close_container (&argument_iterator, &variant_iterator);
+ }
+ return message;
+}
+
+dbus_uint32_t dbus_message_get_serial(DBusMessage* message)
+{
+ Q_UNUSED(message);
+ return 1;
+}
+
+dbus_bool_t dbus_message_get_args (DBusMessage* message,
+ DBusError* error,
+ int first_arg_type,
+ ...)
+{
+ qDebug() << "dbus_message_get_args";
+ va_list var_args;
+ va_start (var_args, first_arg_type);
+
+ while (first_arg_type != DBUS_TYPE_INVALID)
+ {
+ if (first_arg_type == DBUS_TYPE_OBJECT_PATH)
+ {
+ char** str_p;
+ str_p = va_arg (var_args, char**);
+ *str_p = obj_path;
+ }
+ first_arg_type = va_arg(var_args, int);
+ }
+ va_end(var_args);
+ Q_UNUSED(error);
+ Q_UNUSED(message);
+ return true;
+}
+
+dbus_bool_t dbus_connection_send( DBusConnection* connection,
+ DBusMessage* message,
+ dbus_uint32_t* serial)
+{
+ Q_UNUSED(connection);
+ Q_UNUSED(serial);
+
+ if (dbus_message_has_member (m_getVolumeMethodCall, "Set"))
+ {
+ m_setVolumeMethod = message;
+ }
+
+ return true;
+}
+
+void dbus_connection_flush( DBusConnection* connection)
+{
+ Q_UNUSED(connection);
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+#include "ut_MafwGstRendererVolume.h"
+
+#include <QDebug>
+#include <QVariant>
+#include <dbus/dbus.h>
+
+#include "MafwGstRendererVolume.h"
+#include "MafwStubHelper.h"
+
+extern void setStubHelper(MafwStubHelper* stubHlp);
+extern void signalVolumeUpdated(uint channel, uint value);
+extern void giveRestoreEntryReply();
+extern void giveVolumeReply(QMap<uint, uint> volumes);
+extern DBusMessage* m_setVolumeMethod;
+
+void Ut_MafwGstRendererVolume::initTestCase()
+{
+ m_stubHelper = new MafwStubHelper;
+ setStubHelper(m_stubHelper);
+
+ //Tests the case where first pulseaudio connect fails and
+ //DBUSConnectionEventLoop::addConnection fails.
+ m_stubHelper->expect("dbus_connection_open", false);
+ m_stubHelper->expect("dbus_error_is_set", true);
+ m_volume = new MafwGstRendererVolume();
+ QVERIFY(m_stubHelper->allCallsConsumed());
+ //Wait that connecting to pulseaudio is retried
+
+ m_stubHelper->expect("dbus_connection_open", true);
+ m_stubHelper->expect("dbus_error_is_set", false);
+ m_stubHelper->expect("addConnection", false);
+ QTest::qWait(3000);
+ QVERIFY(m_stubHelper->allCallsConsumed());
+
+ delete m_volume;
+ //Tests the successfull case
+ m_stubHelper->expect("dbus_connection_open", true);
+ m_stubHelper->expect("dbus_error_is_set", false);
+ m_stubHelper->expect("addConnection", true);
+ m_volume = new MafwGstRendererVolume();
+ QVERIFY(m_stubHelper->allCallsConsumed());
+}
+
+void Ut_MafwGstRendererVolume::cleanupTestCase()
+{
+ m_stubHelper->expect("removeConnection", false);
+ delete m_volume;
+ QVERIFY(m_stubHelper->allCallsConsumed());
+ delete m_stubHelper;
+}
+
+void Ut_MafwGstRendererVolume::testVolumeReply()
+{
+ QMap<uint, uint> map;
+//Error reply for "GetEntryByName"
+ m_stubHelper->expect("dbus_set_error_from_message", true);
+
+ //Pulseaudio reconnect is done
+ m_stubHelper->expect("removeConnection", false);
+ m_stubHelper->expect("dbus_connection_open", true);
+ m_stubHelper->expect("dbus_error_is_set", false);
+ m_stubHelper->expect("addConnection", true);
+ giveRestoreEntryReply();
+ QTest::qWait(500);
+ QVERIFY(m_stubHelper->allCallsConsumed());
+ QCOMPARE(m_volume->getVolume(), (uint)0);
+//Error reply for "Get Volume"
+ m_stubHelper->expect("dbus_set_error_from_message", false);
+ m_stubHelper->expect("dbus_set_error_from_message", true);
+ giveRestoreEntryReply();
+ giveVolumeReply(map);
+ QVERIFY(m_stubHelper->allCallsConsumed());
+ QCOMPARE(m_volume->getVolume(), (uint)0);
+//Invalid reply for "Get Volume"
+ m_stubHelper->expect("dbus_set_error_from_message", false);
+ m_stubHelper->expect("dbus_set_error_from_message", false);
+ giveRestoreEntryReply();
+ giveVolumeReply(map);
+ QVERIFY(m_stubHelper->allCallsConsumed());
+ QCOMPARE(m_volume->getVolume(), (uint)0);
+
+//Maximum value
+ giveRestoreEntryReply();
+ map[0] = 0x10000;
+ giveVolumeReply(map);
+ QCOMPARE(m_volume->getVolume(), (uint)100);
+//Maximum value-1
+ giveRestoreEntryReply();
+ map[0] = 0x10000;
+ giveVolumeReply(map);
+ QCOMPARE(m_volume->getVolume(), (uint)100);
+//Value above range
+ giveRestoreEntryReply();
+ map[0] = 0x10001;
+ giveVolumeReply(map);
+ QCOMPARE(m_volume->getVolume(), (uint)100);
+//Huge value
+ map[0] = 0xFF000;
+ giveRestoreEntryReply();
+ giveVolumeReply(map);
+ QCOMPARE(m_volume->getVolume(), (uint)100);
+//Zero
+ map[0] = 0;
+ giveRestoreEntryReply();
+ giveVolumeReply(map);
+ QCOMPARE(m_volume->getVolume(), (uint)0);
+//Many channels, containing mono channel
+ map[0] = 0x10000/2;
+ map[1] = 20;
+ map[2] = 30;
+ map[3] = 40;
+ giveRestoreEntryReply();
+ giveVolumeReply(map);
+ QCOMPARE(m_volume->getVolume(), (uint)50);
+//Many channels, without mono channel
+ map.remove(0);
+ map[1] = 0x10000/3;
+ map[2] = 0x10000/4;
+ map[3] = 0x10000/5;
+ giveRestoreEntryReply();
+ giveVolumeReply(map);
+ QCOMPARE(m_volume->getVolume(), (uint)(100/3));
+}
+
+void Ut_MafwGstRendererVolume::testSignal()
+{
+ QSignalSpy spy(m_volume, SIGNAL(volumeChanged(uint)));
+ QFETCH(uint, volume);
+ QFETCH(uint, channel);
+ // Volume updated signal gives volume level as pulse audio's native value
+ // Which has range 0 - 0x10000
+ signalVolumeUpdated(channel, 0x10000*volume/100);
+
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+
+ if (volume > 100) //Volume must not be set out of range
+ {
+ volume = 100;
+ }
+ QCOMPARE(arguments.at(0).toUInt(), volume);
+ QCOMPARE(m_volume->getVolume(), volume);
+}
+
+void Ut_MafwGstRendererVolume::testSignal_data()
+{
+ QTest::addColumn<uint>("volume");
+ QTest::addColumn<uint>("channel");
+
+ QTest::newRow("Maximum value") << (uint)100 << (uint)0;
+ QTest::newRow("Maximum value -1") << (uint)99 << (uint)0;
+ QTest::newRow("Value above range") << (uint)101 << (uint)0;
+ QTest::newRow("Huge value") << (uint)-1 << (uint)0;
+ QTest::newRow("Zero") << (uint)0 << (uint)0;
+ QTest::newRow("One") << (uint)1 << (uint)0;
+ QTest::newRow("Another channel") << (uint)2 << (uint)1;
+}
+
+//one MAFW volume step is 0x10000/100 = 655,36 native volume steps
+void Ut_MafwGstRendererVolume::testSetVolume()
+{
+ QFETCH(uint, volume);
+ quint32 value = 1;
+
+ m_volume->setVolume(volume);
+ QVERIFY(m_setVolumeMethod != 0);
+ DBusMessageIter iter, array_iterator, struct_iterator, value_iterator;
+ dbus_message_iter_init (m_setVolumeMethod, &iter);
+ QCOMPARE(dbus_message_iter_get_arg_type(&iter), DBUS_TYPE_STRING);//interface
+ dbus_message_iter_next(&iter);
+ QCOMPARE(dbus_message_iter_get_arg_type(&iter), DBUS_TYPE_STRING);//property
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_recurse (&iter, &array_iterator);
+ QCOMPARE(dbus_message_iter_get_arg_type(&array_iterator), DBUS_TYPE_ARRAY);
+ dbus_message_iter_recurse (&array_iterator, &struct_iterator);
+ QCOMPARE(dbus_message_iter_get_arg_type(&struct_iterator), DBUS_TYPE_STRUCT);
+
+ dbus_message_iter_recurse (&struct_iterator, &value_iterator);
+ QCOMPARE(dbus_message_iter_get_arg_type (&value_iterator), DBUS_TYPE_UINT32);
+ dbus_message_iter_get_basic (&value_iterator, &value);
+ QCOMPARE(value, (quint32)0); //mono channel
+ dbus_message_iter_next (&value_iterator);
+ QCOMPARE(dbus_message_iter_get_arg_type (&value_iterator), DBUS_TYPE_UINT32);
+ dbus_message_iter_get_basic (&value_iterator, &value);
+
+ if (volume > 100) //Volume must not be set out of range
+ {
+ volume = 100;
+ }
+
+ QCOMPARE(value, (quint32)(volume*0x10000/100));
+}
+
+
+void Ut_MafwGstRendererVolume::testSetVolume_data()
+{
+ QTest::addColumn<uint>("volume");
+
+ QTest::newRow("Set volume to 0") << (uint)0;
+ QTest::newRow("Set volume to 1") << (uint)1;
+ QTest::newRow("Set volume to 99") << (uint)99;
+ QTest::newRow("Set volume to 100") << (uint)100;
+ QTest::newRow("Set volume to huge value") << (uint)-1;
+}
+
+QTEST_MAIN(Ut_MafwGstRendererVolume)
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWGSTRENDERERVOLUME_H_
+#define UT_MAFWGSTRENDERERVOLUME_H_
+
+#include <QtTest/QtTest>
+
+class MafwGstRendererVolume;
+class MafwStubHelper;
+
+class Ut_MafwGstRendererVolume: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void testVolumeReply();
+ void testSignal();
+ void testSignal_data();
+ void testSetVolume();
+ void testSetVolume_data();
+
+private:
+
+ MafwGstRendererVolume* m_volume;
+ MafwStubHelper* m_stubHelper;
+};
+
+#endif /*UT_MAFWGSTRENDERERVOLUME_H_*/
--- /dev/null
+TEMPLATE = app
+TARGET =
+QT -= gui
+CONFIG = console
+
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR $$UT_COMMONDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG += qtestlib qt link_pkgconfig debug qdbus
+PKGCONFIG += qmafw dbus-1 libpulse-mainloop-glib
+LIBS += -lgcov -ldbus-qeventloop
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += ut_MafwGstRendererVolume.h \
+ MafwGstRendererVolume.h \
+ $$UT_COMMONDIR/MafwStubHelper.h
+
+SOURCES += ut_MafwGstRendererVolume.cpp \
+ MafwVolumeStubs.cpp \
+ MafwGstRendererVolume.cpp \
+ $$UT_COMMONDIR/MafwStubHelper.cpp \
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QDir>
+#include <QUrl>
+#include <QTimer>
+
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/tag/tag.h>
+#include <context_provider.h>
+
+#include "ut_MafwGstRendererWorker.h"
+#include "mafw-gst-renderer-worker.h"
+#include "mafw-gst-renderer-utils.h"
+
+static QUrl AUDIO_URI(QDir::currentPath() + QDir::separator() +
+ QString("media") + QDir::separator() +
+ QString("test.wav"));
+
+static QUrl VIDEO_URI(QDir::currentPath() + QDir::separator() +
+ QString("media") + QDir::separator() +
+ QString("test.avi"));
+
+static QUrl IMAGE_URI(QDir::currentPath() + QDir::separator() +
+ QString("media") + QDir::separator() +
+ QString("testframe.png"));
+
+static int WAIT_TIMEOUT = 3500;
+static int EOS_TIMEOUT = 7000;
+static int READY_DELAY = 65000;
+
+static bool NEVER_HAPPENING_EVENT = false;
+
+static int global_context_duration = 0;
+
+static QStringList globalGstFactoryRequests;
+static GstElement *globalGstPipeline;
+
+
+const gchar* g_getenv(const gchar *variable)
+{
+ Q_UNUSED(variable);
+ return NULL;
+}
+
+gboolean convert_utf8(const gchar *src, gchar **dst)
+{
+ *dst = g_strdup(src);
+ return TRUE;
+}
+
+gboolean uri_is_playlist(const gchar *uri)
+{
+ Q_UNUSED(uri);
+ return FALSE;
+}
+
+gboolean uri_is_stream(const gchar *uri)
+{
+ Q_UNUSED(uri);
+ return FALSE;
+}
+
+gint remap_gst_error_code(const GError *error)
+{
+ return error->code;
+}
+
+void context_provider_set_map(const char* key, void* map, int free_map)
+{
+ Q_UNUSED(key);
+ Q_UNUSED(map);
+ Q_UNUSED(free_map);
+}
+
+void *context_provider_map_new(void)
+{
+
+ return NULL;
+}
+
+void context_provider_map_free(void* map)
+{
+ Q_UNUSED(map);
+}
+
+void context_provider_map_set_integer(void* map, const char* key, int value)
+{
+ Q_UNUSED(map);
+
+ if( strcmp( key, "duration" )==0 )
+ {
+ global_context_duration = value;
+ }
+}
+
+void context_provider_map_set_double(void* map, const char* key, double value)
+{
+ Q_UNUSED(map);
+ Q_UNUSED(key);
+ Q_UNUSED(value);
+}
+
+void context_provider_map_set_boolean(void* map, const char* key, int value)
+{
+ Q_UNUSED(map);
+ Q_UNUSED(key);
+ Q_UNUSED(value);
+}
+
+void context_provider_map_set_string(void* map, const char* key, const char* value)
+{
+ Q_UNUSED(map);
+ Q_UNUSED(key);
+ Q_UNUSED(value);
+}
+
+void context_provider_map_set_map(void* map, const char* key, void* value)
+{
+ Q_UNUSED(map);
+ Q_UNUSED(key);
+ Q_UNUSED(value);
+}
+
+void context_provider_set_null(const char* key)
+{
+ Q_UNUSED(key);
+}
+
+gboolean context_provider_init(DBusBusType bus_type, const char* bus_name)
+{
+
+ Q_UNUSED(bus_type);
+ Q_UNUSED(bus_name);
+
+ return TRUE;
+
+}
+
+void context_provider_stop(void)
+{
+}
+
+void context_provider_install_key(
+ const char* key,
+ gboolean clear_values_on_subscribe,
+ ContextProviderSubscriptionChangedCallback subscription_changed_cb,
+ void* subscription_changed_cb_target)
+{
+ Q_UNUSED(key);
+ Q_UNUSED(clear_values_on_subscribe);
+ Q_UNUSED(subscription_changed_cb);
+ Q_UNUSED(subscription_changed_cb_target);
+}
+
+GstElement *gst_element_factory_make(const gchar *factoryname, const gchar *name)
+{
+ GstElementFactory *factory;
+ GstElement *element;
+ const gchar *use_factoryname;
+
+ g_return_val_if_fail(factoryname != NULL, NULL);
+
+ globalGstFactoryRequests.append(factoryname);
+
+ /* For testing, use playbin instead of playbin2 */
+ if (g_str_equal(factoryname, "playbin2"))
+ {
+ use_factoryname = "playbin";
+ }
+ else
+ {
+ use_factoryname = factoryname;
+ }
+
+ GST_LOG("gstelementfactory: make \"%s\" \"%s\"",
+ use_factoryname, GST_STR_NULL (name));
+
+ factory = gst_element_factory_find(use_factoryname);
+ if (factory == NULL)
+ {
+ /* No factory */
+ GST_INFO("no such element factory \"%s\"!", use_factoryname);
+ return NULL;
+ }
+
+ GST_LOG_OBJECT(factory, "found factory %p", factory);
+ if (g_str_equal(use_factoryname, "pulsesink"))
+ {
+ element = gst_element_factory_make("fakesink", "pulsesink");
+ g_object_set(G_OBJECT(element), "sync", TRUE, NULL);
+ }
+ else if (g_str_equal(use_factoryname, "alsasink"))
+ {
+ element = gst_element_factory_make("fakesink", "alsasink");
+ g_object_set(G_OBJECT(element), "sync", TRUE, NULL);
+ }
+ else if (g_str_equal(use_factoryname, "xvimagesink")
+ || g_str_equal(use_factoryname, "omapxvsink"))
+ {
+ element = gst_element_factory_make("fakesink", "xvimagesink");
+ g_object_set(G_OBJECT(element), "sync", TRUE, NULL);
+ }
+ else
+ {
+ element = gst_element_factory_create(factory, name);
+ if( !g_strcmp0(use_factoryname, "playbin") )
+ {
+ globalGstPipeline = element;
+ }
+ }
+ gst_object_unref(factory);
+
+ if (element == NULL)
+ {
+ /* Create failed */
+ GST_INFO_OBJECT(factory, "couldn't create instance!");
+ return NULL;
+ }
+
+ GST_LOG("gstelementfactory: make \"%s\" \"%s\"",use_factoryname,
+ GST_STR_NULL(name));
+
+ /* Playbin will use fake renderer */
+ if (g_str_equal(use_factoryname, "playbin"))
+ {
+ GstElement *audiorenderer = gst_element_factory_make("fakesink",
+ "audiorenderer");
+ g_object_set(G_OBJECT(audiorenderer), "sync", TRUE, NULL);
+ g_object_set(G_OBJECT(element), "audio-sink", audiorenderer, NULL);
+ g_object_set(G_OBJECT(element), "video-sink", audiorenderer, NULL);
+ }
+
+ return element;
+
+}
+/* END OF STUB DEFINITIONS */
+
+void ut_MafwGstRendererWorker::playCallback(MafwGstRendererWorker *worker,
+ gpointer owner)
+{
+
+ Q_UNUSED(worker);
+ Q_UNUSED(owner);
+ qDebug() << __PRETTY_FUNCTION__;
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_gotPlayCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::pauseCallback(MafwGstRendererWorker *worker,
+ gpointer owner)
+{
+ Q_UNUSED(worker);
+
+ qDebug() << __PRETTY_FUNCTION__;
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_gotPauseCallback = true;
+}
+
+void ut_MafwGstRendererWorker::bufferingCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ gdouble percent)
+{
+ Q_UNUSED(worker);
+
+ qDebug() << __PRETTY_FUNCTION__;
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_receivedBufferStatus = percent;
+ self->m_gotBufferStatusCallback = true;
+}
+
+void ut_MafwGstRendererWorker::eosCallback(MafwGstRendererWorker *worker,
+ gpointer owner)
+{
+
+ Q_UNUSED(worker);
+
+ qDebug() << __PRETTY_FUNCTION__;
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_gotEosCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::seekCallback(MafwGstRendererWorker *worker,
+ gpointer owner)
+{
+
+ Q_UNUSED(worker);
+
+ qDebug() << __PRETTY_FUNCTION__;
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_gotSeekCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::errorCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ const GError *error)
+{
+
+ Q_UNUSED(worker);
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_receivedErrorCode = error->code;
+
+ if (error)
+ {
+ qCritical() << "error code: " << error->code << " message: " <<
+ error->message;
+ }
+ self->m_gotErrorCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::propertyCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ gint id,
+ GValue *value)
+{
+
+ Q_UNUSED(worker);
+ Q_UNUSED(value);
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_receivedPropertyId = id;
+ self->m_gotPropertyCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::metadataCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ gint key,
+ GType type,
+ gpointer value)
+{
+
+ Q_UNUSED(worker);
+ Q_UNUSED(type);
+ Q_UNUSED(value);
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_receivedMetadata.append(key);
+ self->m_gotMetadataCallback = true;
+
+}
+
+void ut_MafwGstRendererWorker::blankingControlCallback(MafwGstRendererWorker *worker,
+ gpointer owner, gboolean prohibit)
+{
+ Q_UNUSED(worker);
+
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_blankingProhibited = prohibit;
+}
+
+void ut_MafwGstRendererWorker::screenshotCallback(MafwGstRendererWorker *worker,
+ gpointer owner, GstBuffer *buffer,
+ const char *filename, gboolean cancel)
+{
+ Q_UNUSED(worker);
+ Q_UNUSED(buffer);
+ Q_UNUSED(filename);
+ if(!cancel)
+ {
+ ut_MafwGstRendererWorker* self =
+ static_cast<ut_MafwGstRendererWorker*>(owner);
+ self->m_receivedMetadata.append(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI);
+ self->m_gotMetadataCallback = true;
+ }
+}
+
+void ut_MafwGstRendererWorker::basicPlaybackTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QCOMPARE( global_context_duration, 3 ); // 2.5 seconds is duration of test.wav
+ QVERIFY(m_blankingProhibited == false);
+
+ //video-sink should not be created unless XID has been set
+ QVERIFY(!m_worker->vsink);
+}
+
+void ut_MafwGstRendererWorker::basicVideoPlaybackTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+
+ QVERIFY(!m_worker->vsink);
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+ QVERIFY(m_worker->vsink);
+
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+ m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(m_blankingProhibited == true);
+}
+
+void ut_MafwGstRendererWorker::pauseFrameTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->notify_metadata_handler = &metadataCallback;
+ m_worker->notify_property_handler = &propertyCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ m_worker->screenshot_handler = screenshotCallback;
+
+ mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+ QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+ TRUE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+ QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+
+ /* post xwindow-id on bus since we are using fakesink instead of
+ * xvimagesink */
+ GstBus *bus;
+ GstStructure *structure;
+ GstMessage *message;
+ structure = gst_structure_new("prepare-xwindow-id", "width",
+ G_TYPE_INT, 64, "height", G_TYPE_INT, 32,
+ NULL);
+ message = gst_message_new_element(NULL, structure);
+ bus = m_worker->bus;
+ gst_bus_post(bus, message);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, NEVER_HAPPENING_EVENT);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotMetadataCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+}
+
+void ut_MafwGstRendererWorker::pauseFrameCancelTestCase()
+{
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->notify_metadata_handler = &metadataCallback;
+ m_worker->notify_property_handler = &propertyCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ m_worker->screenshot_handler = screenshotCallback;
+
+ mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+ QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+ TRUE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+ QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+
+ /* post xwindow-id on bus since we are using fakesink instead of
+ * xvimagesink */
+ GstBus *bus;
+ GstStructure *structure;
+ GstMessage *message;
+ structure = gst_structure_new("prepare-xwindow-id", "width",
+ G_TYPE_INT, 64, "height", G_TYPE_INT, 32,
+ NULL);
+ message = gst_message_new_element(NULL, structure);
+ bus = m_worker->bus;
+ gst_bus_post(bus, message);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+ mafw_gst_renderer_worker_resume(m_worker);
+ QTest::qWait(10);
+
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotMetadataCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(!m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+
+}
+
+void ut_MafwGstRendererWorker::redirectMessageTestCase()
+{
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+
+ /* We just give random uri to renderer, because we ignore the error */
+ /* We don't have to test with real RTSP stream, we just use local content */
+ char *control = qstrdup(VIDEO_URI.toString().toAscii());
+
+ GstStructure *structure;
+ GstMessage *message;
+ structure = gst_structure_new("redirect", "new-location",
+ G_TYPE_STRING, control, NULL);
+
+ // reset and construct the pipeline
+ mafw_gst_renderer_worker_stop(m_worker);
+
+ // when worker receives "redirect" message, it should start playing the uri contained in the message.
+ message = gst_message_new_element(GST_OBJECT_CAST(m_worker->pipeline), structure);
+ gst_element_post_message(m_worker->pipeline, message);
+
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(strcmp(control, m_worker->media.location) == 0);
+ QVERIFY(m_gotErrorCallback == false);
+
+ delete[] control;
+}
+
+void ut_MafwGstRendererWorker::slotTimeOut()
+{
+ qDebug() << "TIMEOUT!";
+}
+
+void ut_MafwGstRendererWorker::waitForEvent(gint ms, bool &hasEventOccurred)
+
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ if (hasEventOccurred)
+ {
+ return;
+ }
+
+ QTimer timer(this);
+ QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));
+ timer.setSingleShot(true);
+ timer.start(ms);
+
+ while (!hasEventOccurred && timer.isActive())
+ {
+ g_main_context_iteration(NULL, TRUE);
+ }
+}
+
+void ut_MafwGstRendererWorker::bufferingTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_buffer_status_handler = &bufferingCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ /* post the buffering msg on bus */
+ GstBus *bus = 0;
+ GstMessage *message = 0;
+
+ message = gst_message_new_buffering(NULL, 50);
+ bus = m_worker->bus;
+ gst_bus_post(bus, message);
+
+ waitForEvent(WAIT_TIMEOUT, m_gotBufferStatusCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_receivedBufferStatus == 50);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::rendererArtTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->notify_metadata_handler = &metadataCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+ /* post the renderer art tag on bus */
+ gsize image_length = 0;
+ gchar *image = 0;
+ GstCaps *caps = 0;
+ GstBuffer *buffer = 0;
+ GstMessage *message = 0;
+ GstTagList *list = 0;
+
+ QVERIFY(g_file_get_contents(IMAGE_URI.toLocalFile().toAscii(),
+ &image,
+ &image_length,
+ NULL));
+ buffer = gst_buffer_new();
+ gst_buffer_set_data(buffer, (guint8*)image, image_length);
+ caps = gst_caps_new_simple("image/png", "image-type",
+ GST_TYPE_TAG_IMAGE_TYPE,
+ GST_TAG_IMAGE_TYPE_FRONT_COVER, NULL);
+ gst_buffer_set_caps(buffer, caps);
+
+ list = gst_tag_list_new();
+ gst_tag_list_add(list, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, buffer, NULL);
+
+ message = gst_message_new_tag(NULL, list);
+ gst_bus_post(m_worker->bus, message);
+ mafw_gst_renderer_worker_resume(m_worker);
+
+ waitForEvent(WAIT_TIMEOUT, NEVER_HAPPENING_EVENT);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotMetadataCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(m_receivedMetadata.contains(WORKER_METADATA_KEY_RENDERER_ART_URI));
+
+ gst_buffer_unref(buffer);
+ gst_caps_unref(caps);
+ g_free(image);
+
+}
+
+void ut_MafwGstRendererWorker::eosTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_eos_handler = &eosCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+ waitForEvent(EOS_TIMEOUT, m_gotEosCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotEosCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::seekTestCase()
+{
+
+ GError *error = 0;
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_seek_handler = &seekCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+ mafw_gst_renderer_worker_set_position(m_worker,
+ GST_SEEK_TYPE_SET,
+ 1,
+ &error);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotSeekCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(error == 0);
+ QVERIFY(mafw_gst_renderer_worker_get_position(m_worker) == 1);
+
+}
+
+void ut_MafwGstRendererWorker::invalidUriTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, "vjmksbhdfghrejggv");
+
+ waitForEvent(WAIT_TIMEOUT, m_gotErrorCallback);
+
+ QVERIFY(m_gotPlayCallback == false);
+ QVERIFY(m_gotErrorCallback == true);
+ /* FIXME: new code for Gst errors? */
+ /*QVERIFY(m_receivedErrorCode == WORKER_ERROR_UNABLE_TO_PERFORM);*/
+
+}
+
+void ut_MafwGstRendererWorker::playAndStopTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+
+ mafw_gst_renderer_worker_stop(m_worker);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::playAndPauseTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+ m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == false);
+ QVERIFY(m_blankingProhibited == true);
+
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(m_blankingProhibited == false);
+}
+
+void ut_MafwGstRendererWorker::pauseQuicklyAfterPlayTestCase()
+{
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+ m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+ mafw_gst_renderer_worker_pause(m_worker);
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+ QVERIFY(m_gotPlayCallback == false);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_blankingProhibited == false);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+
+ mafw_gst_renderer_worker_resume(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ waitForEvent(WAIT_TIMEOUT, m_blankingProhibited);
+ QCOMPARE(m_gotPlayCallback, true);
+ QCOMPARE(m_blankingProhibited, true);
+}
+
+void ut_MafwGstRendererWorker::pauseAtTestCase()
+{
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+ m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+ //the video is only two seconds long
+ mafw_gst_renderer_worker_pause_at(m_worker, 1);
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+ QVERIFY(m_gotPlayCallback == false);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_blankingProhibited == false);
+
+ QVERIFY(mafw_gst_renderer_worker_get_position(m_worker) == 1);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+
+ mafw_gst_renderer_worker_resume(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ waitForEvent(WAIT_TIMEOUT, m_blankingProhibited);
+ QCOMPARE(m_gotPlayCallback, true);
+ QCOMPARE(m_blankingProhibited, true);
+}
+
+void ut_MafwGstRendererWorker::playAndPauseAndResumeTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == false);
+
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+ m_gotPlayCallback = false;
+ mafw_gst_renderer_worker_resume(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+
+void ut_MafwGstRendererWorker::resumeDelayedTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == false);
+
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+ /* pipeline goes to ready after 60 seconds */
+ waitForEvent(READY_DELAY, NEVER_HAPPENING_EVENT);
+
+ m_gotPlayCallback = false;
+ mafw_gst_renderer_worker_resume(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::getCurrentMetadataTestCase()
+{
+
+ GHashTable *metadata = 0;
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == false);
+
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+
+ metadata = mafw_gst_renderer_worker_get_current_metadata(m_worker);
+ QVERIFY(metadata);
+ QVERIFY(g_hash_table_size(metadata));
+
+ mafw_gst_renderer_worker_stop(m_worker);
+ metadata = mafw_gst_renderer_worker_get_current_metadata(m_worker);
+ QVERIFY(!metadata);
+
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::defaultConfigurationTestCase()
+{
+ QVERIFY2(sizeof(configuration) == 64, "You've (or somebody else) most likely changed the configuration struct! Update the unittests also!");
+
+ configuration * current_worker_conf = mafw_gst_renderer_worker_create_default_configuration(m_worker);
+
+ QCOMPARE(current_worker_conf->asink, "pulsesink");
+ QCOMPARE(current_worker_conf->vsink, "omapxvsink");
+ QCOMPARE(current_worker_conf->buffer_time, 600000LL);
+ QCOMPARE(current_worker_conf->latency_time, 100000LL);
+ QCOMPARE(current_worker_conf->flags, 67);
+
+ QCOMPARE(current_worker_conf->mobile_surround_music.state, 0U);
+ QCOMPARE(current_worker_conf->mobile_surround_music.color, 2);
+ QCOMPARE(current_worker_conf->mobile_surround_music.room, 2);
+ QCOMPARE(current_worker_conf->mobile_surround_video.state, 0U);
+ QCOMPARE(current_worker_conf->mobile_surround_video.color, 2);
+ QCOMPARE(current_worker_conf->mobile_surround_video.room, 2);
+
+ QCOMPARE(current_worker_conf->milliseconds_to_pause_frame, 700U);
+ QCOMPARE(current_worker_conf->seconds_to_pause_to_ready, 3U);
+ QCOMPARE(current_worker_conf->use_dhmmixer, 1);
+
+ //this well make valgrind happy. i.e. worker will handle memory cleanupping
+ mafw_gst_renderer_worker_set_configuration(m_worker, current_worker_conf);
+}
+
+void ut_MafwGstRendererWorker::configurabilityTestCase()
+{
+ MafwGstRendererWorker *configWorker = mafw_gst_renderer_worker_new(this);
+
+ configuration *config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+
+ g_free(config->asink);
+ config->asink = g_strdup("test-sink");
+
+ //audio sink
+ QVERIFY(!globalGstFactoryRequests.contains("test-sink"));
+ mafw_gst_renderer_worker_set_configuration(configWorker, config);
+ mafw_gst_renderer_worker_stop(configWorker);
+ QVERIFY(globalGstFactoryRequests.contains("test-sink"));
+ globalGstFactoryRequests.clear();
+
+ mafw_gst_renderer_worker_exit(configWorker);
+ g_free(configWorker);
+
+
+ //video sink
+ configWorker = mafw_gst_renderer_worker_new(this);
+ config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+ g_free(config->vsink);
+ config->vsink = g_strdup("test-video-sink");
+
+ QVERIFY(!globalGstFactoryRequests.contains("test-video-sink"));
+
+ mafw_gst_renderer_worker_set_configuration(configWorker, config);
+ //video-sink is not created unless xid has been set
+ mafw_gst_renderer_worker_set_xid(configWorker, 0xffff);
+
+ mafw_gst_renderer_worker_stop(configWorker);
+ QVERIFY(globalGstFactoryRequests.contains("test-video-sink"));
+
+ globalGstFactoryRequests.clear();
+ mafw_gst_renderer_worker_exit(configWorker);
+ g_free(configWorker);
+
+
+ //NO dhmmixer
+ configWorker = mafw_gst_renderer_worker_new(this);
+ config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+ config->use_dhmmixer = 0;
+
+ QVERIFY(!globalGstFactoryRequests.contains("nokiadhmmix"));
+ mafw_gst_renderer_worker_set_configuration(configWorker, config);
+ mafw_gst_renderer_worker_stop(configWorker);
+ QVERIFY(!globalGstFactoryRequests.contains("nokiadhmmix"));
+
+ globalGstFactoryRequests.clear();
+ mafw_gst_renderer_worker_exit(configWorker);
+ g_free(configWorker);
+
+ //YES dhmmixer
+ configWorker = mafw_gst_renderer_worker_new(this);
+ config = mafw_gst_renderer_worker_create_default_configuration(configWorker);
+ config->use_dhmmixer = 1;
+
+ QVERIFY(!globalGstFactoryRequests.contains("nokiadhmmix"));
+ mafw_gst_renderer_worker_set_configuration(configWorker, config);
+ mafw_gst_renderer_worker_stop(configWorker);
+ QVERIFY(globalGstFactoryRequests.contains("nokiadhmmix"));
+
+ globalGstFactoryRequests.clear();
+ mafw_gst_renderer_worker_exit(configWorker);
+ g_free(configWorker);
+}
+
+void ut_MafwGstRendererWorker::pauseFrameConfigurabilityTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->notify_metadata_handler = &metadataCallback;
+ m_worker->notify_property_handler = &propertyCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ m_worker->screenshot_handler = screenshotCallback;
+
+ //let's change timeout values
+ configuration *config = mafw_gst_renderer_worker_create_default_configuration(m_worker);
+ config->milliseconds_to_pause_frame = 3000;
+ config->seconds_to_pause_to_ready = 6;
+ mafw_gst_renderer_worker_set_configuration(m_worker, config);
+
+
+ mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+ QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+ TRUE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+ QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+
+ /* post xwindow-id on bus since we are using fakesink instead of
+ * xvimagesink */
+ GstBus *bus;
+ GstStructure *structure;
+ GstMessage *message;
+ structure = gst_structure_new("prepare-xwindow-id", "width",
+ G_TYPE_INT, 64, "height", G_TYPE_INT, 32,
+ NULL);
+ message = gst_message_new_element(NULL, structure);
+ bus = m_worker->bus;
+ gst_bus_post(bus, message);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+
+ mafw_gst_renderer_worker_pause(m_worker);
+ QTest::qWait(2000);
+
+ //no pause frame yet, let's make sure
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == true);
+ QVERIFY(m_gotMetadataCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(!m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+ waitForEvent(WAIT_TIMEOUT, NEVER_HAPPENING_EVENT);
+ QVERIFY(m_receivedMetadata.contains(WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI));
+
+ mafw_gst_renderer_worker_stop(m_worker);
+ QTest::qWait(100);
+ config = mafw_gst_renderer_worker_create_default_configuration(m_worker);
+ mafw_gst_renderer_worker_set_configuration(m_worker, config);
+
+}
+
+void ut_MafwGstRendererWorker::setAndGetPropertiesTestCase()
+{
+
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_property_handler = &propertyCallback;
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+ QVERIFY(mafw_gst_renderer_worker_get_xid(m_worker) == 0xffff);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_XID);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ mafw_gst_renderer_worker_set_force_aspect_ratio(m_worker, FALSE);
+ QVERIFY(mafw_gst_renderer_worker_get_force_aspect_ratio(m_worker) == FALSE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_FORCE_ASPECT_RATIO);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+ mafw_gst_renderer_worker_set_force_aspect_ratio(m_worker, TRUE);
+ QVERIFY(mafw_gst_renderer_worker_get_force_aspect_ratio(m_worker) == TRUE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_FORCE_ASPECT_RATIO);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, TRUE);
+ QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+ TRUE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+ mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker, FALSE);
+ QVERIFY(mafw_gst_renderer_worker_get_current_frame_on_pause(m_worker) ==
+ FALSE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ mafw_gst_renderer_worker_set_autopaint(m_worker, TRUE);
+ QVERIFY(mafw_gst_renderer_worker_get_autopaint(m_worker) == TRUE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_AUTOPAINT);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+ mafw_gst_renderer_worker_set_autopaint(m_worker, FALSE);
+ QVERIFY(mafw_gst_renderer_worker_get_autopaint(m_worker) == FALSE);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_AUTOPAINT);
+
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotPauseCallback == false);
+
+ mafw_gst_renderer_worker_set_playback_speed(m_worker, 2);
+ QVERIFY(mafw_gst_renderer_worker_get_playback_speed(m_worker) == 2);
+ QVERIFY(m_gotPropertyCallback == true);
+ QVERIFY(m_receivedPropertyId == WORKER_PROPERTY_PLAYBACK_SPEED);
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+ mafw_gst_renderer_worker_set_playback_speed(m_worker, float(-1));
+ QCOMPARE(mafw_gst_renderer_worker_get_playback_speed(m_worker), float(-1));
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+ mafw_gst_renderer_worker_set_playback_speed(m_worker, float(2.5));
+ QCOMPARE(mafw_gst_renderer_worker_get_playback_speed(m_worker), float(2.5));
+
+ render_rectangle rect = {1,2,3,4};
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ mafw_gst_renderer_worker_set_render_rectangle(m_worker, &rect);
+ QVERIFY(m_gotPropertyCallback);
+ QVERIFY(m_receivedPropertyId != -1);
+ const render_rectangle *storedRect = mafw_gst_renderer_worker_get_render_rectangle(m_worker);
+ //the pointer value should not be used, copy must be made
+ QVERIFY(&rect != storedRect );
+ QCOMPARE(rect.x, storedRect->x);
+ QCOMPARE(rect.y, storedRect->y);
+ QCOMPARE(rect.width, storedRect->width);
+ QCOMPARE(rect.height, storedRect->height);
+
+ m_gotPropertyCallback = false;
+ m_receivedPropertyId = -1;
+
+ QVERIFY(m_gotErrorCallback == false);
+}
+
+void ut_MafwGstRendererWorker::gettersTestCase()
+{
+
+ m_worker->notify_error_handler = &errorCallback;
+
+ QVERIFY(mafw_gst_renderer_worker_get_colorkey(m_worker) == -1);
+ QVERIFY(mafw_gst_renderer_worker_get_seekable(m_worker) == TRUE);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::mediaRouteTestCase()
+{
+
+ GSList *list = NULL;
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_eos_handler = &eosCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+ mafw_gst_renderer_worker_set_xid(m_worker, 0xffff);
+
+ /* normal audio playback */
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+ list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS));
+ list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY));
+ mafw_gst_renderer_worker_notify_media_destination(m_worker, list);
+ g_slist_free(list);
+ list = NULL;
+ QVERIFY(g_slist_length(m_worker->destinations) == 2);
+ QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_SPEAKERS)));
+ QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+ waitForEvent(EOS_TIMEOUT, m_gotEosCallback);
+
+ QVERIFY(m_gotEosCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+ /* normal video playback */
+ m_gotPlayCallback = false;
+ m_gotEosCallback = false;
+ m_gotErrorCallback = false;
+ QVERIFY(m_blankingProhibited == false);
+ mafw_gst_renderer_worker_play(m_worker, VIDEO_URI.toString().toAscii());
+ m_worker->media.has_visual_content = true; // normally gst sets this but not in unittest for some reason
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ QVERIFY(m_blankingProhibited == true);
+
+ list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK));
+ list = g_slist_append(list, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY));
+ mafw_gst_renderer_worker_notify_media_destination(m_worker, list);
+ g_slist_free(list);
+ list = NULL;
+ QVERIFY(g_slist_length(m_worker->destinations) == 2);
+ QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_HEADPHONE_JACK)));
+ QVERIFY(g_slist_find(m_worker->destinations, GINT_TO_POINTER(WORKER_OUTPUT_BUILTIN_DISPLAY)));
+
+ waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+ QVERIFY(m_gotEosCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+}
+
+void ut_MafwGstRendererWorker::setReadyTimeoutTestCase()
+{
+
+ m_worker->notify_play_handler = &playCallback;
+ m_worker->notify_error_handler = &errorCallback;
+ m_worker->notify_pause_handler = &pauseCallback;
+ m_worker->notify_eos_handler = &eosCallback;
+ m_worker->blanking__control_handler = &blankingControlCallback;
+
+ /* do some basic set calls first */
+ mafw_gst_renderer_worker_set_ready_timeout(m_worker, 0);
+ QVERIFY(m_worker->config->seconds_to_pause_to_ready == 0);
+ mafw_gst_renderer_worker_set_ready_timeout(m_worker, 60);
+ QVERIFY(m_worker->config->seconds_to_pause_to_ready == 60);
+
+ /* set timeout to 0, pause in the middle of the playback */
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+ mafw_gst_renderer_worker_set_ready_timeout(m_worker, 0);
+ QVERIFY(m_worker->config->seconds_to_pause_to_ready == 0);
+ QTest::qWait(1500);
+ QVERIFY(m_worker->state == GST_STATE_PLAYING);
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+ QVERIFY(m_worker->state == GST_STATE_PAUSED);
+ QTest::qWait(500);
+ QVERIFY(m_worker->state == GST_STATE_READY);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+
+ mafw_gst_renderer_worker_resume(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_worker->state == GST_STATE_PLAYING);
+ waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+ QVERIFY(m_gotEosCallback == true);
+
+ /* set timeout to 3, pause in the middle of the playback */
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+ mafw_gst_renderer_worker_set_ready_timeout(m_worker, 3);
+ QVERIFY(m_worker->config->seconds_to_pause_to_ready == 3);
+ QTest::qWait(1500);
+ QVERIFY(m_worker->state == GST_STATE_PLAYING);
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+ QVERIFY(m_worker->state == GST_STATE_PAUSED);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+ QTest::qWait(4000);
+ QVERIFY(m_worker->state == GST_STATE_READY);
+
+ mafw_gst_renderer_worker_resume(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_worker->state == GST_STATE_PLAYING);
+ waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+ QVERIFY(m_gotEosCallback == true);
+
+ /* set timeout to 0, pause in the middle of the playback after setting the
+ * timeout value --> we should go to ready immediately */
+ mafw_gst_renderer_worker_play(m_worker, AUDIO_URI.toString().toAscii());
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_gotErrorCallback == false);
+ mafw_gst_renderer_worker_set_ready_timeout(m_worker, 60);
+ QVERIFY(m_worker->config->seconds_to_pause_to_ready == 60);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+ QTest::qWait(1500);
+ QVERIFY(m_worker->state == GST_STATE_PLAYING);
+ mafw_gst_renderer_worker_pause(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPauseCallback);
+ QVERIFY(m_worker->state == GST_STATE_PAUSED);
+ mafw_gst_renderer_worker_set_ready_timeout(m_worker, 0);
+ QVERIFY(m_worker->config->seconds_to_pause_to_ready == 0);
+ QTest::qWait(500);
+ QVERIFY(m_worker->state == GST_STATE_READY);
+
+ m_gotPlayCallback = false;
+ m_gotPauseCallback = false;
+
+ mafw_gst_renderer_worker_resume(m_worker);
+ waitForEvent(WAIT_TIMEOUT, m_gotPlayCallback);
+ QVERIFY(m_gotPlayCallback == true);
+ QVERIFY(m_worker->state == GST_STATE_PLAYING);
+ waitForEvent(WAIT_TIMEOUT, m_gotEosCallback);
+ QVERIFY(m_gotEosCallback == true);
+
+}
+
+void ut_MafwGstRendererWorker::initTestCase()
+{
+ gst_init(0,0);
+}
+
+void ut_MafwGstRendererWorker::init()
+{
+
+ qDebug() << __PRETTY_FUNCTION__;
+
+ m_worker = 0;
+ m_receivedErrorCode = -1;
+ m_receivedPropertyId = -1;
+ m_receivedBufferStatus = -1.0;
+ m_receivedMetadata.clear();
+ m_gotPlayCallback = false;
+ m_gotEosCallback = false;
+ m_gotErrorCallback = false;
+ m_gotPauseCallback = false;
+ m_gotSeekCallback = false;
+ m_gotMetadataCallback = false;
+ m_gotPropertyCallback = false;
+ m_gotBufferStatusCallback = false;
+ m_blankingProhibited = false;
+
+ global_context_duration = 0;
+
+ bool ok;
+ QByteArray tmo = qgetenv("WAIT_TIMEOUT");
+ int val = tmo.toInt(&ok, 10);
+ if (ok)
+ {
+ WAIT_TIMEOUT = val;
+ qDebug() << "WAIT_TIMEOUT is set to" << WAIT_TIMEOUT;
+ }
+ else
+ {
+ qDebug() << "Using default WAIT_TIMEOUT" << WAIT_TIMEOUT;
+ }
+
+ const QString scheme("file");
+ AUDIO_URI.setScheme(scheme);
+ VIDEO_URI.setScheme(scheme);
+ IMAGE_URI.setScheme(scheme);
+
+ m_worker = mafw_gst_renderer_worker_new(this);
+
+ QVERIFY(m_worker != 0);
+
+ globalGstFactoryRequests.clear();
+}
+
+void ut_MafwGstRendererWorker::cleanup()
+{
+ QVERIFY(m_worker != 0);
+
+ mafw_gst_renderer_worker_exit(m_worker);
+ g_free(m_worker);
+
+ QVERIFY(m_blankingProhibited == false);
+
+ m_gotPlayCallback = false;
+ m_gotErrorCallback = false;
+}
+
+QTEST_MAIN(ut_MafwGstRendererWorker)
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFW_GST_RENDERER_WORKER_H_
+#define UT_MAFW_GST_RENDERER_WORKER_H_
+
+#include <QObject>
+#include <QtTest/QtTest>
+
+#include "mafw-gst-renderer-worker.h"
+
+class ut_MafwGstRendererWorker: public QObject
+{
+ Q_OBJECT
+
+private slots: // tests
+
+ void basicPlaybackTestCase();
+ void basicVideoPlaybackTestCase();
+ void eosTestCase();
+ void playAndPauseTestCase();
+ void playAndStopTestCase();
+ void setAndGetPropertiesTestCase();
+ void gettersTestCase();
+ void playAndPauseAndResumeTestCase();
+ void pauseQuicklyAfterPlayTestCase();
+ void pauseAtTestCase();
+ void resumeDelayedTestCase();
+ void getCurrentMetadataTestCase();
+ void invalidUriTestCase();
+ void seekTestCase();
+ void defaultConfigurationTestCase();
+ void configurabilityTestCase();
+ void pauseFrameTestCase();
+ void pauseFrameConfigurabilityTestCase();
+ void pauseFrameCancelTestCase();
+ void rendererArtTestCase();
+ void bufferingTestCase();
+ void mediaRouteTestCase();
+ void setReadyTimeoutTestCase();
+ void redirectMessageTestCase();
+
+ void initTestCase();
+ void init();
+ void cleanup();
+
+protected slots:
+ void slotTimeOut();
+
+protected:
+ static void playCallback(MafwGstRendererWorker *worker, gpointer owner);
+ static void eosCallback(MafwGstRendererWorker *worker, gpointer owner);
+ static void errorCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ const GError *error);
+ static void pauseCallback(MafwGstRendererWorker *worker, gpointer owner);
+ static void propertyCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ gint id,
+ GValue *value);
+ static void seekCallback(MafwGstRendererWorker *worker, gpointer owner);
+ static void metadataCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ gint key,
+ GType type,
+ gpointer value);
+ static void bufferingCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ gdouble percent);
+ static void blankingControlCallback(MafwGstRendererWorker *worker,
+ gpointer owner, gboolean prohibit);
+ static void screenshotCallback(MafwGstRendererWorker *worker,
+ gpointer owner,
+ GstBuffer *buffer,
+ const char *filename,
+ gboolean cancel);
+
+ void waitForEvent(gint ms, bool &hasEventOccurred);
+
+private: //data
+ MafwGstRendererWorker *m_worker;
+ bool m_gotPlayCallback;
+ bool m_gotEosCallback;
+ bool m_gotErrorCallback;
+ bool m_gotPauseCallback;
+ bool m_gotSeekCallback;
+ bool m_gotMetadataCallback;
+ bool m_gotPropertyCallback;
+ bool m_gotBufferStatusCallback;
+ bool m_blankingProhibited;
+ int m_receivedErrorCode;
+ int m_receivedPropertyId;
+ gdouble m_receivedBufferStatus;
+ QList<int> m_receivedMetadata;
+};
+
+#endif
--- /dev/null
+TEMPLATE = app
+QT -= gui
+CONFIG = console
+
+isEmpty(PREFIX) {
+ PREFIX=/usr
+}
+
+CONFIG += qt link_pkgconfig debug
+CONFIG += qtestlib
+PKGCONFIG += glib-2.0 gobject-2.0 gstreamer-0.10 gstreamer-plugins-base-0.10
+PKGCONFIG += contextprovider-1.0 x11 gstreamer-tag-0.10
+
+LIBS += -lgstinterfaces-0.10 -lgstpbutils-0.10 -lgcov
+
+DEPENDPATH += . ../../inc ../../src
+INCLUDEPATH += . ../../inc
+
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+
+QMAKE_CLEAN += *.gcda *.gcno *.gcov ut_MafwGstRendererWorker *.vg.xml vgcore.*
+
+HEADERS += ut_MafwGstRendererWorker.h \
+ mafw-gst-renderer-worker.h \
+ mafw-gst-renderer-seeker.c
+
+SOURCES += ut_MafwGstRendererWorker.cpp \
+ mafw-gst-renderer-worker.c \
+ mafw-gst-renderer-seeker.c
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include "ut_MafwMmcMonitor.h"
+
+#include <usb_moded-dbus.h>
+
+#include <QDebug>
+#include <QSignalSpy>
+
+#define private public // access private slots
+#include "MafwMmcMonitor.h"
+
+extern QStringList stubMounts;
+extern QStringList g_dbusConnectionParams;
+
+void Ut_MafwMmcMonitor::initTestCase()
+{
+}
+
+void Ut_MafwMmcMonitor::cleanupTestCase()
+{
+}
+
+void Ut_MafwMmcMonitor::testConstruction()
+{
+ QFETCH(QStringList, mounts);
+ QFETCH(bool, mmcMounted);
+
+ stubMounts = mounts;
+
+ MafwMmcMonitor monitor(this);
+
+ QVERIFY( monitor.isMounted()==mmcMounted );
+
+ QCOMPARE(g_dbusConnectionParams.at(0), QString(USB_MODE_SERVICE));
+ QCOMPARE(g_dbusConnectionParams.at(1), QString(USB_MODE_OBJECT));
+ QCOMPARE(g_dbusConnectionParams.at(2), QString(USB_MODE_INTERFACE));
+ QCOMPARE(g_dbusConnectionParams.at(3), QString(USB_MODE_SIGNAL_NAME));
+ QVERIFY(g_dbusConnectionParams.at(4).toUInt() > static_cast<uint>(0));
+ QVERIFY(g_dbusConnectionParams.at(5).length() > 0);
+
+}
+
+void Ut_MafwMmcMonitor::testConstruction_data()
+{
+ QTest::addColumn<QStringList>("mounts");
+ QTest::addColumn<bool>("mmcMounted");
+
+ QTest::newRow("none") << (QStringList()) << false;
+ QTest::newRow("nommc") << (QStringList() << "file:///home/user/.mms/private" << "file:///home/user/.nokiamessaging/IM") << false;
+ QTest::newRow("mmc") << (QStringList() << "file:///home/user/MyDocs" << "file:///home/user/.nokiamessaging/IM") << true;
+}
+
+void Ut_MafwMmcMonitor::testMounts()
+{
+ stubMounts.clear();
+ MafwMmcMonitor monitor(this);
+
+ QVERIFY( !monitor.isMounted() );
+
+ stubMounts << "file:///home/user/.mms/private" << "file:///home/user/MyDocs";
+ monitor.mountEvent( 0, (GMount*)1, &monitor );
+ QVERIFY( !monitor.isMounted() );
+ monitor.mountEvent( 0, (GMount*)2, &monitor );
+ QVERIFY( monitor.isMounted() );
+
+ monitor.unmountEvent( 0, (GMount*)1, &monitor );
+ QVERIFY( monitor.isMounted() );
+ monitor.unmountEvent( 0, (GMount*)2, &monitor );
+ QVERIFY( !monitor.isMounted() );
+}
+
+void Ut_MafwMmcMonitor::testPreUnmount()
+{
+ MafwMmcMonitor monitor(this);
+ QSignalSpy spy( &monitor, SIGNAL( preUnmount() ) );
+
+ monitor.preUnmountEvent("pre-unmount");
+ QVERIFY( spy.size()==1 );
+}
+
+QTEST_MAIN(Ut_MafwMmcMonitor)
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_MAFWMMCMONITOR_H_
+#define UT_MAFWMMCMONITOR_H_
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <gio/gunixmounts.h>
+
+#include <QtTest/QtTest>
+
+
+class Ut_MafwMmcMonitor : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void testConstruction();
+ void testConstruction_data();
+
+ void testMounts();
+ void testPreUnmount();
+
+};
+
+#endif /*UT_MAFWMMCMONITOR_H_*/
--- /dev/null
+TEMPLATE = app
+TARGET =
+QT -= gui
+CONFIG = console
+
+INCLUDEPATH += .
+MAFW_GST_INCDIR = ../../inc
+#UT_COMMONDIR = ../common
+
+INCLUDEPATH += $$MAFW_GST_INCDIR
+DEPENDPATH += . ../../inc ../../src
+
+CONFIG += qtestlib
+CONFIG += qt qdbus link_pkgconfig debug
+
+PKGCONFIG += glib-2.0 gio-2.0 gio-unix-2.0 usb_moded dbus-1
+
+LIBS += -lgcov
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -O0 -Werror
+
+# Input
+HEADERS += MafwMmcMonitor.h \
+ ut_MafwMmcMonitor.h
+
+SOURCES += MafwMmcMonitor.cpp \
+ ut_MafwMmcMonitor.cpp \
+ ut_MafwMmcMonitorStubs.cpp
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <gio/gio.h>
+#include <QStringList>
+#include <QDBusConnection>
+
+QStringList stubMounts;
+
+QStringList g_dbusConnectionParams;
+
+// GVolumeMonitor
+
+GVolumeMonitor *g_volume_monitor_get(void)
+{
+ return (GVolumeMonitor*)1;
+}
+
+GList * g_volume_monitor_get_mounts(GVolumeMonitor *volume_monitor)
+{
+ return (GList*)1;
+}
+
+// GObject
+
+gulong g_signal_connect_data (gpointer instance,
+ const gchar *detailed_signal,
+ GCallback c_handler,
+ gpointer data,
+ GClosureNotify destroy_data,
+ GConnectFlags connect_flags)
+{
+ return 0;
+}
+
+void g_object_unref(gpointer object)
+{
+}
+
+// GList
+
+guint g_list_length(GList *list)
+{
+ return stubMounts.size();
+}
+
+gpointer g_list_nth_data(GList *list, guint n)
+{
+ return (void*)(n+1);
+}
+
+void g_list_free(GList *list)
+{
+}
+
+// GMount
+
+GFile * g_mount_get_root(GMount *mount)
+{
+ return (GFile*)mount;
+}
+
+// GFile
+
+char* g_file_get_uri(GFile *file)
+{
+ return g_strdup(stubMounts[(int)file-1].toAscii().constData());
+}
+
+
+//QDBusConnection
+
+QDBusConnection::QDBusConnection(const QString& /*name*/)
+{
+}
+
+QDBusConnection QDBusConnection::sessionBus()
+{
+ return QDBusConnection("...");
+}
+
+bool QDBusConnection::connect(const QString &service,
+ const QString &path,
+ const QString &interface,
+ const QString &name,
+ QObject *receiver,
+ const char *slot)
+{
+ g_dbusConnectionParams << service;
+ g_dbusConnectionParams << path;
+ g_dbusConnectionParams << interface;
+ g_dbusConnectionParams << name;
+ g_dbusConnectionParams << QString::number(reinterpret_cast<uint>(receiver));
+ g_dbusConnectionParams << slot;
+
+ return true;
+}
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QTimer>
+
+#include <string.h>
+#include <glib.h>
+#include <gst/gst.h>
+
+#include "ut_Others.h"
+#include "mafw-gst-renderer-utils.h"
+#include "mafw-gst-renderer-worker.h"
+
+#define UNUSED(x) (void)(x)
+
+/* START OF STUB DEFINITIONS */
+gboolean g_utf8_validate(const gchar *str,
+ gssize max_len,
+ const gchar **end)
+{
+
+ UNUSED(max_len);
+ UNUSED(end);
+
+ if (g_str_equal("valid", str))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+}
+
+gchar* g_locale_to_utf8(const gchar *opsysstring,
+ gssize len,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ GError **error)
+{
+
+ UNUSED(len);
+ UNUSED(bytes_read);
+ UNUSED(bytes_written);
+
+ if (g_str_equal("non-valid", opsysstring))
+ {
+ return g_strdup(opsysstring);
+ }
+ else
+ {
+ g_set_error(error,
+ g_quark_from_string("test"),
+ 100,
+ "%s", "SIMULATED ERROR");
+ return NULL;
+ }
+}
+
+
+/* END OF STUB DEFINITIONS */
+
+void ut_Others::testUtils()
+{
+ QVERIFY(uri_is_stream("file:///file.m3u") == FALSE);
+ QVERIFY(uri_is_stream("http:///joojoo.com") == TRUE);
+ QVERIFY(uri_is_stream(NULL) == FALSE);
+
+ gchar *dst = NULL;
+ QVERIFY(convert_utf8(NULL, NULL) == FALSE);
+ QVERIFY(convert_utf8("valid", NULL) == FALSE);
+ QVERIFY(convert_utf8(NULL, &dst) == FALSE);
+ QVERIFY(convert_utf8("valid", &dst) == TRUE);
+ g_free(dst);
+ QVERIFY(convert_utf8("non-valid", &dst) == TRUE);
+ QVERIFY(dst);
+ QVERIFY(g_str_equal(dst, "non-valid") == TRUE);
+ g_free(dst);
+ QVERIFY(convert_utf8("error", &dst) == FALSE);
+
+}
+
+void ut_Others::testGstErrorRemapping()
+{
+
+ GQuark domain = g_quark_from_string("test_error_domain");
+
+ GError* error = g_error_new_literal(domain, 999, "error_message");
+ QVERIFY(remap_gst_error_code(error) == 999);
+
+ error->domain = GST_RESOURCE_ERROR;
+ error->code = GST_RESOURCE_ERROR_READ;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_STREAM_DISCONNECTED);
+ error->code = GST_RESOURCE_ERROR_NOT_FOUND;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_MEDIA_NOT_FOUND);
+ error->code = GST_RESOURCE_ERROR_OPEN_READ_WRITE;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_MEDIA_NOT_FOUND);
+ error->code = GST_RESOURCE_ERROR_NO_SPACE_LEFT;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNABLE_TO_PERFORM);
+ error->code = GST_RESOURCE_ERROR_WRITE;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CORRUPTED_FILE);
+ error->code = GST_RESOURCE_ERROR_SEEK;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CANNOT_SET_POSITION);
+ error->code = 999999;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNABLE_TO_PERFORM);
+
+ error->domain = GST_STREAM_ERROR;
+ error->code = GST_STREAM_ERROR_TYPE_NOT_FOUND;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_TYPE_NOT_AVAILABLE);
+ error->code = GST_STREAM_ERROR_FORMAT;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNSUPPORTED_TYPE);
+ error->code = GST_STREAM_ERROR_DECODE;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CORRUPTED_FILE);
+ error->code = GST_STREAM_ERROR_CODEC_NOT_FOUND;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_CODEC_NOT_FOUND);
+ error->code = GST_STREAM_ERROR_DECRYPT;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_DRM_NOT_ALLOWED);
+ error->code = 999999;
+ QVERIFY(remap_gst_error_code(error) == WORKER_ERROR_UNABLE_TO_PERFORM);
+
+ g_error_free(error);
+
+}
+
+void ut_Others::init()
+{
+
+}
+
+void ut_Others::cleanup()
+{
+
+}
+
+QTEST_APPLESS_MAIN(ut_Others)
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_OTHERS_H_
+#define UT_OTHERS_H_
+
+#include <QObject>
+#include <QtTest/QtTest>
+
+class ut_Others: public QObject
+{
+ Q_OBJECT
+
+private slots: // tests
+
+ void testUtils();
+ void testGstErrorRemapping();
+
+ void init();
+ void cleanup();
+
+protected slots:
+
+protected:
+
+private: //data
+
+};
+
+#endif
--- /dev/null
+TEMPLATE = app
+
+isEmpty(PREFIX) {
+ PREFIX=/usr
+}
+
+CONFIG += qt link_pkgconfig release
+CONFIG += qtestlib
+PKGCONFIG += glib-2.0 gobject-2.0 gstreamer-0.10
+
+LIBS += -lgcov
+
+DEPENDPATH += . ../../inc ../../src
+INCLUDEPATH += . ../../inc
+
+QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+QMAKE_CFLAGS += -fprofile-arcs -ftest-coverage -Wall -Werror -g
+
+QMAKE_CLEAN += *.gcda *.gcno *.gcov ut_Others *.vg.xml vgcore.*
+
+HEADERS += ut_Others.h \
+ mafw-gst-renderer-utils.h
+
+SOURCES += ut_Others.cpp \
+ mafw-gst-renderer-utils.c
+
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#include <QtTest/QtTest>
+#include <QDebug>
+#include <QSignalSpy>
+
+#include "Ut_PlaylistFileUtility.h"
+#include "../common/MafwStubHelper.h"
+#include "MafwGstRendererPlaylistFileUtility.h"
+
+void Ut_PlaylistFileUtility::initTestCase()
+{
+ m_stubHelper = new MafwStubHelper;
+ m_utility = new MafwGstRendererPlaylistFileUtility(this);
+}
+
+void Ut_PlaylistFileUtility::testParsing()
+{
+ QString file("/test-station.pls");
+ file.prepend(QDir::currentPath());
+ file.prepend("file://");
+
+ QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+ QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+ m_utility->parsePlaylistFile(QUrl(file));
+ QTest::qWait(1000);
+
+ QCOMPARE(readySpy.count(), 1);
+ QList<QVariant> arguments = readySpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == true);
+ QCOMPARE(parsingSpy.count(), 1);
+
+ //There is 19 entries in test-station.pls file
+ for (int i=0; i<19; i++)
+ {
+ QVERIFY(m_utility->takeFirstUri().length() > 0);
+ }
+
+ QVERIFY(m_utility->takeFirstUri().length() == 0);
+}
+
+void Ut_PlaylistFileUtility::testParsingForNotExistingFile()
+{
+ QString file("/not-existing.pls");
+ file.prepend(QDir::currentPath());
+ file.prepend("file://");
+ QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+ QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+
+ m_utility->parsePlaylistFile(QUrl(file));
+ QTest::qWait(1000);
+ QCOMPARE(readySpy.count(), 1);
+ QCOMPARE(parsingSpy.count(), 0);
+ QList<QVariant> arguments = readySpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == false);
+}
+
+void Ut_PlaylistFileUtility::testParsingInvalidFileUri()
+{
+//No scheme
+ QString file("/test-station.pls");
+ file.prepend(QDir::currentPath());
+ QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+ QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+ m_utility->parsePlaylistFile(QUrl(file));
+ QTest::qWait(1000);
+ QCOMPARE(parsingSpy.count(), 0);
+ QCOMPARE(readySpy.count(), 1);
+ QList<QVariant> arguments = readySpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == false);
+
+//Contains only path
+ QString file2(QDir::currentPath());
+ file2.prepend("file://");
+ m_utility->parsePlaylistFile(file2);
+ QTest::qWait(1000);
+ QCOMPARE(parsingSpy.count(), 0);
+ QCOMPARE(readySpy.count(), 1);
+ arguments = readySpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == false);
+}
+
+void Ut_PlaylistFileUtility::testParsingInvalidFile()
+{
+ QString file("/test-station_invalid.pls");
+ file.prepend(QDir::currentPath());
+ file.prepend("file://");
+
+ QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+ QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+ m_utility->parsePlaylistFile(QUrl(file));
+ QTest::qWait(1000);
+
+ QCOMPARE(readySpy.count(), 1);
+ QList<QVariant> arguments = readySpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == true);
+ QCOMPARE(parsingSpy.count(), 0);
+
+ QVERIFY(m_utility->takeFirstUri().length() == 0);
+}
+
+void Ut_PlaylistFileUtility::testParsingASFFile()
+{
+ QString file("/test.asf");
+ file.prepend(QDir::currentPath());
+ file.prepend("file://");
+
+ QSignalSpy readySpy(m_utility, SIGNAL(parsingReady(bool)));
+ QSignalSpy parsingSpy(m_utility, SIGNAL(firstItemParsed()));
+ m_utility->parsePlaylistFile(QUrl(file));
+ QTest::qWait(1000);
+
+ QCOMPARE(readySpy.count(), 1);
+ QList<QVariant> arguments = readySpy.takeFirst();
+ QVERIFY(arguments.at(0).toBool() == true);
+ QCOMPARE(parsingSpy.count(), 1);
+
+ for (int i=0; i < 1; i++)
+ {
+ QString test = m_utility->takeFirstUri();
+ QVERIFY(test.length() > 0);
+ QVERIFY(test.startsWith("mmsh://195"));
+ QVERIFY(test.endsWith(".asf"));
+ }
+
+ QVERIFY(m_utility->takeFirstUri().length() == 0);
+}
+
+void Ut_PlaylistFileUtility::cleanupTestCase()
+{
+ delete m_stubHelper;
+}
+
+QTEST_MAIN(Ut_PlaylistFileUtility)
--- /dev/null
+/*
+ * This file is part of QMAFW
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights
+ * reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This software, including documentation, is protected by copyright controlled
+ * by Nokia Corporation. All rights are reserved. Copying, including
+ * reproducing, storing, adapting or translating, any or all of this material
+ * requires the prior written consent of Nokia Corporation. This material also
+ * contains confidential information which may not be disclosed to others
+ * without the prior written consent of Nokia.
+ *
+ */
+
+#ifndef UT_PLAYLISTFILEUTILITY_H
+#define UT_PLAYLISTFILEUTILITY_H
+
+#include <QObject>
+
+class MafwStubHelper;
+class MafwGstRendererPlaylistFileUtility;
+
+class Ut_PlaylistFileUtility: public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS: // tests
+
+ void initTestCase();
+ void testParsing();
+ void testParsingForNotExistingFile();
+ void testParsingInvalidFileUri();
+ void testParsingInvalidFile();
+ void testParsingASFFile();
+ void cleanupTestCase();
+
+private:
+ MafwStubHelper* m_stubHelper;
+ MafwGstRendererPlaylistFileUtility* m_utility;
+
+};
+
+#endif // UT_PLAYLISTFILEUTILITY_H
--- /dev/null
+######################################################################
+# Automatically generated by qmake (2.01a) Mon Aug 23 09:32:17 2010
+######################################################################
+TEMPLATE = app
+TARGET =
+QT -= gui
+CONFIG = console
+
+MAFW_GST_INCDIR = ../../inc
+DEPENDPATH += . $$MAFW_GST_INCDIR ../../src
+INCLUDEPATH += . $$MAFW_GST_INCDIR /usr/include/qmafw
+
+CONFIG += qtestlib no_keywords
+CONFIG += qt link_pkgconfig debug
+PKGCONFIG += qmafw glib-2.0 gobject-2.0
+PKGCONFIG += contextprovider-1.0 x11 libpulse-mainloop-glib contextsubscriber-1.0
+LIBS += -lgcov -ltotem-plparser
+
+QMAKE_CXXFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+QMAKE_CFLAGS +=-fprofile-arcs -ftest-coverage -O0 -Wall -Werror
+
+# Input
+HEADERS += Ut_PlaylistFileUtility.h \
+ ../common/MafwStubHelper.h \
+ MafwGstRendererPlaylistFileUtility.h
+
+SOURCES += Ut_PlaylistFileUtility.cpp \
+ ../common/MafwStubHelper.cpp \
+ MafwGstRendererPlaylistFileUtility.cpp \
+ #totemParserStub.c
+
--- /dev/null
+[playlist]
+numberofentries=19
+File1=http://188.165.211.147:8002
+Title1=(#1 - 7/19) RMF FM
+Length1=-1
+File2=http://188.165.12.66:8006
+Title2=(#2 - 524/950) RMF FM
+Length1=-1
+File3=http://91.121.124.91:8002
+Title3=(#3 - 543/950) RMF FM
+Length1=-1
+File4=http://188.165.12.67:8004
+Title4=(#4 - 547/950) RMF FM
+Length1=-1
+File5=http://188.165.12.67:8000
+Title5=(#5 - 554/950) RMF FM
+Length1=-1
+File6=http://188.165.12.66:8002
+Title6=(#6 - 562/950) RMF FM
+Length1=-1
+File7=http://188.165.12.66:8000
+Title7=(#7 - 573/950) RMF FM
+Length1=-1
+File8=http://188.165.12.66:8004
+Title8=(#8 - 596/950) RMF FM
+Length1=-1
+File9=http://91.121.125.91:8000
+Title9=(#9 - 614/950) RMF FM
+Length1=-1
+File10=http://188.165.12.67:8002
+Title10=(#10 - 647/950) RMF FM
+Length1=-1
+File11=http://188.165.12.66:8008
+Title11=(#11 - 655/950) RMF FM
+Length1=-1
+File12=http://188.165.12.67:8006
+Title12=(#12 - 658/950) RMF FM
+Length1=-1
+File13=http://91.121.125.91:8002
+Title13=(#13 - 670/950) RMF FM
+Length1=-1
+File14=http://91.121.124.91:8000
+Title14=(#14 - 714/950) RMF FM
+Length1=-1
+File15=http://87.98.222.167:8000
+Title15=(#15 - 779/950) RMF FM
+Length1=-1
+File16=http://87.98.223.167:8000
+Title16=(#16 - 869/950) RMF FM
+Length1=-1
+File17=http://188.165.12.67:8008
+Title17=(#17 - 887/950) RMF FM
+Length1=-1
+File18=http://87.98.222.167:8002
+Title18=(#18 - 896/950) RMF FM
+Length1=-1
+File19=http://87.98.223.167:8002
+Title19=(#19 - 901/950) RMF FM
+Length1=-1
+Version=2
--- /dev/null
+[playlist]
+numberofentries=19
+Version=2
--- /dev/null
+[Reference]\r
+Ref1=http://195.134.228.177:443/data/ByContainer/Video/ASF/VC1/CIF/WMA/ASF_VC-1_CIF_29.7FPS_356Kbps_WMA8_44.1KHz_64Kbps_60sec(3Mb)_BBB.asf\r
+Ref2=http://195.134.228.177:443/data/ByContainer/Video/ASF/VC1/CIF/WMA/ASF_VC-1_CIF_29.7FPS_356Kbps_WMA8_44.1KHz_64Kbps_60sec(3Mb)_BBB.asf\r
--- /dev/null
+<?xml version="1.0"?>
+
+<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+xmlns:check="http://check.sourceforge.net/ns">
+
+<xsl:template match="/">
+ <h2>Executed Test Programs</h2>
+ <xsl:for-each select="valgrindresults/valgrindoutput">
+ <xsl:sort select="args/argv/exe"/>
+ <a href="#{generate-id()}"><xsl:value-of select="args/argv/exe"/></a><br/>
+ </xsl:for-each>
+
+ <h2>Errors</h2>
+ <xsl:for-each select="valgrindresults/valgrindoutput">
+ <xsl:sort select="args/argv/exe"/>
+ <a name="{generate-id()}"/>
+ <table border="1">
+ <tr bgcolor="#9acd32">
+ <th align="left"><xsl:value-of select="args/argv/exe"/></th>
+ </tr>
+ <xsl:for-each select="error">
+ <tr>
+ <td><a href="#{generate-id()}">
+ <xsl:choose>
+ <xsl:when test="kind='InvalidRead'">
+ <span style="color:#ff0000"><xsl:value-of select="what"/></span>
+ </xsl:when>
+ <xsl:when test="kind='InvalidWrite'">
+ <span style="color:#ff0000"><xsl:value-of select="what"/></span>
+ </xsl:when>
+ <xsl:when test="kind='InvalidFree'">
+ <span style="color:#ff0000"><xsl:value-of select="what"/></span>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="xwhat"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </a></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <p/>
+ </xsl:for-each>
+ <h2>Stack frames</h2>
+ <xsl:for-each select="valgrindresults/valgrindoutput/error">
+ <a name="{generate-id()}"/>
+ <b>call stack (<xsl:value-of select="../args/argv/exe"/>): <span style="color:#ff0000"><xsl:value-of select="what"/></span></b>
+ <table border="1" >
+ <tr bgcolor="#9acd32">
+ <th align="left">function</th>
+ <th align="left">file</th>
+ <th align="left">line</th>
+ <th align="left">directory</th>
+ </tr>
+ <xsl:for-each select="stack[1]/frame">
+ <tr>
+ <td><xsl:value-of select="fn"/></td>
+ <td><xsl:value-of select="file"/></td>
+ <td><xsl:value-of select="line"/></td>
+ <td><xsl:value-of select="dir"/></td>
+ </tr>
+ </xsl:for-each>
+ <xsl:apply-templates select="auxwhat"/>
+ <xsl:for-each select="stack[2]/frame">
+ <tr>
+ <td><xsl:value-of select="fn"/></td>
+ <td><xsl:value-of select="file"/></td>
+ <td><xsl:value-of select="line"/></td>
+ <td><xsl:value-of select="dir"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <p/>
+ </xsl:for-each>
+</xsl:template>
+<xsl:template match="auxwhat">
+<span style="color:#ff0000"><xsl:value-of select="."/> (call stack):</span>
+</xsl:template>
+</xsl:stylesheet>
--- /dev/null
+#!/bin/sh
+
+valgrind_results_file=valgrind.results
+
+files=`find . -name "*.vg.xml"`
+
+rm -f $valgrind_results_file
+
+if [ -z "$files" ]
+then
+ echo "Valgrind results not generated."
+ exit 0
+fi
+
+echo '<?xml version="1.0"?>' > $valgrind_results_file
+echo '<valgrindresults>' >> $valgrind_results_file
+for file in $files; do
+ grep -v \<\/\valgrindoutput\> $file | tail --quiet --lines=+2 >> $valgrind_results_file;
+ echo '</valgrindoutput>' >> $valgrind_results_file;
+done
+echo '</valgrindresults>' >> $valgrind_results_file