<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="FeedCreator 1.7.6(BH)" -->
<rss version="2.0">
    <channel xmlns:g="http://base.google.com/ns/1.0">
        <title>Planet Maemo: category &quot;feed:218abbb3f30ed17e36476558d8bce9b5&quot;</title>
        <description>Blog entries from Maemo community</description>
        <link>http://maemo.org/news/planet-maemo/</link>
        <lastBuildDate>Sun, 24 May 2026 05:30:58 +0000</lastBuildDate>
        <generator>FeedCreator 1.7.6(BH)</generator>
        <language>en</language>
        <managingEditor>planet@maemo.org</managingEditor>
        <item>
            <title>Igalia Multimedia contributions in 2025</title>
            <link>https://eocanha.org/blog/2026/01/26/igalia-multimedia-contributions-in-2025/</link>
            <description><![CDATA[

<p>Now that 2025 is over, it&#8217;s time to look back and feel proud of the path we&#8217;ve walked. Last year has been really exciting in terms of contributions to GStreamer and WebKit for the Igalia Multimedia team.</p>



<p>With more than 459 contributions along the year, we&#8217;ve been one of the top contributors to the GStreamer project, in areas like Vulkan Video, GstValidate, VA, GStreamer Editing Services, WebRTC or H.266 support.</p>



<figure class="wp-block-image size-full"><a href="https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-contributions.jpg"><img loading="lazy" width="943" height="530" src="https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-contributions.jpg" alt="Pie chart of Igalia's contributions to different areas of the GStreamer project:
other (30%)
vulkan (24%)
validate (7%)
va (6%)
ges (4%)
webrtc (3%)
h266parse (3%)
python (3%)
dots-viewer (3%)
tests (2%)
docs (2%)
devtools (2%)
webrtcbin (1%)
tracers (1%)
qtdemux (1%)
gst (1%)
ci (1%)
y4menc (1%)
videorate (1%)
gl (1%)
alsa (1%)" class="wp-image-706" srcset="https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-contributions.jpg 943w, https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-contributions-300x169.jpg 300w, https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-contributions-768x432.jpg 768w" sizes="(max-width: 943px) 100vw, 943px" /></a><figcaption>Igalia&#8217;s contributions to the GStreamer project</figcaption></figure>



<p>In Vulkan Video we&#8217;ve worked on the VP9 video decoder, and cooperated with other contributors to push the AV1 decoder as well. There&#8217;s now an H.264 base class for video encoding that is designed to support general hardware-accelerated processing.</p>



<p>GStreaming Editing Services, the framework to build video editing applications, has gained time remapping support, which now allows to include fast/slow motion effects in the videos. Video transformations (scaling, cropping, rounded corners, etc) are now hardware-accelerated thanks to the addition of new Skia-based GStreamer elements and integration with OpenGL. Buffer pool tuning and pipeline improvements have helped to optimize memory usage and performance, enabling the edition of 4K video at 60 frames per second. Much of this work to improve and ensure quality in GStreamer Editing Services has also brought improvements in the GstValidate testing framework, which will be useful for other parts of GStreamer.</p>



<p>Regarding H.266 (VVC), full playback support (with decoders such as <code>vvdec</code> and <code>avdec_h266</code>, demuxers and muxers for Matroska, MP4 and TS, and parsers for the <code>vvc1</code> and <code>vvi1</code> formats) is now available in GStreamer 1.26 thanks to Igalia&#8217;s work. This allows user applications such as the WebKitGTK web browser to leverage the hardware accelerated decoding provided by VAAPI to play H.266 video using GStreamer.</p>



<p>Igalia has also been one of the top contributors to GStreamer Rust, with 43 contributions. Most of the commits there have been related to Vulkan Video.</p>



<figure class="wp-block-image size-full"><a href="https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-rs-contributions.jpg"><img loading="lazy" width="943" height="530" src="https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-rs-contributions.jpg" alt="Pie chart of Igalia's contributions to different areas of the GStreamer Rust project:
vulkan (28%)
other (26%)
gstreamer (12%)
ci (12%)
tracer (7%)
validate (5%)
ges (7%)
examples (5%)" class="wp-image-708" srcset="https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-rs-contributions.jpg 943w, https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-rs-contributions-300x169.jpg 300w, https://eocanha.org/blog/wp-content/uploads/2026/01/gstreamer-rs-contributions-768x432.jpg 768w" sizes="(max-width: 943px) 100vw, 943px" /></a><figcaption>Igalia&#8217;s contributions to the GStreamer Rust project</figcaption></figure>



<p>In addition to GStreamer, the team also has a strong presence in WebKit, where we leverage our GStreamer knowledge to implement many features of the web engine related to multimedia. From the 1739 contributions to the WebKit project done last year by Igalia, the Multimedia team has made 323 of them. Nearly one third of those have been related to generic multimedia playback, and the rest have been on areas such as WebRTC, MediaStream, MSE, WebAudio, a new Quirks system to provide adaptations for specific hardware multimedia platforms at runtime, WebCodecs or MediaRecorder.</p>



<figure class="wp-block-image size-full"><a href="https://eocanha.org/blog/wp-content/uploads/2026/01/webkit-contributions.jpg"><img loading="lazy" width="943" height="530" src="https://eocanha.org/blog/wp-content/uploads/2026/01/webkit-contributions.jpg" alt="Pie chart of Igalia's contributions to different areas of the WebKit project:
Generic Gstreamer work (33%)
WebRTC (20%)
Regression bugfixing (9%)
Other (7%)
MSE (6%)
BuildStream SDK (4%)
MediaStream (3%)
WPE platform (3%)
WebAudio (3%)
WebKitGTK platform (2%)
Quirks (2%)
MediaRecorder (2%)
EME (2%)
Glib (1%)
WTF (1%)
WebCodecs (1%)
GPUProcess (1%)
Streams (1%) " class="wp-image-709" srcset="https://eocanha.org/blog/wp-content/uploads/2026/01/webkit-contributions.jpg 943w, https://eocanha.org/blog/wp-content/uploads/2026/01/webkit-contributions-300x169.jpg 300w, https://eocanha.org/blog/wp-content/uploads/2026/01/webkit-contributions-768x432.jpg 768w" sizes="(max-width: 943px) 100vw, 943px" /></a><figcaption>Igalia Multimedia Team&#8217;s contributions to different areas of the WebKit project</figcaption></figure>



<p>We&#8217;re happy about what we&#8217;ve achieved along the year and look forward to maintaining this success and bringing even more exciting features and contributions in 2026.</p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1f0faa7f51dc2ccfaa711f09da6c17f3257e139e139&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1f0faa7f51dc2ccfaa711f09da6c17f3257e139e139/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1f0faa7f51dc2ccfaa711f09da6c17f3257e139e139&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1f0faa7f51dc2ccfaa711f09da6c17f3257e139e139/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Mon, 26 Jan 2026 09:34:37 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1f0faa7f51dc2ccfaa711f09da6c17f3257e139e139</guid>
        </item>
        <item>
            <title>Meow: Process log text files as if you could make cat speak</title>
            <link>https://eocanha.org/blog/2025/12/05/meow-process-log-text-files-as-if-you-could-make-cat-speak/</link>
            <description><![CDATA[

<p>Some years ago I had mentioned <a href="https://eocanha.org/blog/2021/05/25/gstreamer-webkit-debugging-by-using-external-tools-2-2/" data-type="URL" data-id="https://eocanha.org/blog/2021/05/25/gstreamer-webkit-debugging-by-using-external-tools-2-2/">some command line tools</a> I used to analyze and find useful information on GStreamer logs. I&#8217;ve been using them consistently along all these years, but some weeks ago I thought about unifying them in a single tool that could provide more flexibility in the mid term, and also as an excuse to unrust my Rust knowledge a bit. That&#8217;s how I wrote Meow, a tool to make <code>cat</code> speak (that is, to provide meaningful information).</p>



<p>The idea is that you can <code>cat</code> a file through <code>meow</code> and apply the filters, like this:</p>



<p><code>cat /tmp/log.txt | meow appsinknewsample n:V0 n:video ht: \<br>  ft:-0:00:21.466607596 's:#([A-za-z][A-Za-z]*/)*#'</code></p>



<p>which means &#8220;select those lines that contain <code>appsinknewsample</code> (with case insensitive matching), but don&#8217;t contain <code>V0</code> nor <code>video</code> (that is, by exclusion, only that contain audio, probably because we&#8217;ve analyzed both and realized that we should focus on audio for our specific problem), highlight the different thread ids, only show those lines with timestamp lower than 21.46 sec, and change strings like <code>Source/WebCore/platform/graphics/gstreamer/mse/AppendPipeline.cpp</code> to become just <code>AppendPipeline.cpp</code>&#8220;, to get an output as shown in this terminal screenshot:</p>



<figure class="wp-block-image size-large"><a href="https://eocanha.org/blog/wp-content/uploads/2025/12/image.png"><img loading="lazy" width="1024" height="254" src="https://eocanha.org/blog/wp-content/uploads/2025/12/image-1024x254.png" alt="Screenshot of a terminal output showing multiple log lines. Some of them have the word &quot;appsinkNewSample&quot; highlighted in red. Some lines have the hexadecimal id of the thread that printed them highlighed (purple for one thread, brown for the other)" class="wp-image-686" srcset="https://eocanha.org/blog/wp-content/uploads/2025/12/image-1024x254.png 1024w, https://eocanha.org/blog/wp-content/uploads/2025/12/image-300x74.png 300w, https://eocanha.org/blog/wp-content/uploads/2025/12/image-768x190.png 768w, https://eocanha.org/blog/wp-content/uploads/2025/12/image-1536x381.png 1536w, https://eocanha.org/blog/wp-content/uploads/2025/12/image.png 1899w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<p>Cool, isn&#8217;t it? After all, I&#8217;m convinced that the answer to any GStreamer bug is always hidden in the logs (or will be, as soon as I add &#8220;<em>just a couple of log lines more, bro</em>&#8221; <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f92d.png" alt="<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1f0d1d1e898aff2d1d111f0a5182bb29e09f3bcf3bc&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1f0d1d1e898aff2d1d111f0a5182bb29e09f3bcf3bc/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1f0d1d1e898aff2d1d111f0a5182bb29e09f3bcf3bc&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1f0d1d1e898aff2d1d111f0a5182bb29e09f3bcf3bc/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Fri, 05 Dec 2025 11:16:07 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1f0d1d1e898aff2d1d111f0a5182bb29e09f3bcf3bc</guid>
        </item>
        <item>
            <title>Adding buffering hysteresis to the WebKit GStreamer video player</title>
            <link>https://eocanha.org/blog/2024/10/16/adding-buffering-hysteresis-to-the-webkit-gstreamer-video-player/</link>
            <description><![CDATA[

<p>The <code>&lt;video&gt;</code> element implementation in WebKit does its job by using a multiplatform player that relies on a platform-specific implementation. In the specific case of glib platforms, which base their multimedia on GStreamer, that&#8217;s <a href="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4%5E/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp" data-type="URL" data-id="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4%5E/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp">MediaPlayerPrivateGStreamer</a>. </p>



<div class="wp-block-image"><figure class="aligncenter size-full is-resized"><a href="https://eocanha.org/blog/wp-content/uploads/2024/10/regular-multimedia.svg"><img loading="lazy" src="https://eocanha.org/blog/wp-content/uploads/2024/10/regular-multimedia.svg" alt="WebKit GStreamer regular playback class diagram" class="wp-image-671" width="394" height="239"/></a></figure></div>



<p>The player private can have 3 buffering modes:</p>



<ul><li>On-disk buffering: This is the typical mode on desktop systems, but is frequently disabled on purpose on embedded devices to avoid wearing out their flash storage memories. All the video content is downloaded to disk, and the buffering percentage refers to the total size of the video. A GstDownloader element is present in the pipeline in this case. Buffering level monitoring is done by polling the pipeline every second, using the <code><a rel="noreferrer noopener" href="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4%5E/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L1300" data-type="URL" data-id="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4%5E/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L1300" target="_blank">fillTimerFired()</a></code> method.</li><li>In-memory buffering: This is the typical mode on embedded systems and on desktop systems in case of streamed (live) content. The video is downloaded progressively and only the part of it ahead of the current playback time is buffered. A GstQueue2 element is present in the pipeline in this case. Buffering level monitoring is done by <a rel="noreferrer noopener" href="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4%5E/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L2023" data-type="URL" data-id="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4%5E/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L2023" target="_blank">listening to GST_MESSAGE_BUFFERING bus messages</a> and using the buffering level stored on them. This is the case that motivates the refactoring described in this blog post, what we actually wanted to correct in Broadcom platforms, and what motivated the addition of hysteresis working on all the platforms.</li><li>Local files: Files, MediaStream sources and other special origins of video don&#8217;t do buffering at all (no GstDownloadBuffering nor GstQueue2 element is present on the pipeline). They work like the on-disk buffering mode in the sense that <code>fillTimerFired()</code> is used, but the reported level is relative, much like in the streaming case. In the initial version of the refactoring I was unaware of this third case, and only realized about it when tests triggered the assert that I added to ensure that the on-disk buffering method was working in GST_BUFFERING_DOWNLOAD mode.</li></ul>



<p>The current implementation (actually, <a rel="noreferrer noopener" href="https://github.com/WebPlatformForEmbedded/WPEWebKit/blob/95664cfc09608b8f6ee252f27bbfe6849d4441ab/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp" data-type="URL" data-id="https://github.com/WebPlatformForEmbedded/WPEWebKit/blob/95664cfc09608b8f6ee252f27bbfe6849d4441ab/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp" target="_blank">its wpe-2.38 version</a>) was showing some buffering problems on some Broadcom platforms when doing in-memory buffering. The buffering levels monitored by MediaPlayerPrivateGStreamer weren&#8217;t accurate because the Nexus multimedia subsystem used on Broadcom platforms was doing its own internal buffering. Data wasn&#8217;t being accumulated in the GstQueue2 element of playbin, because BrcmAudFilter/BrcmVidFilter was accepting all the buffers that the queue could provide. Because of that, the player private buffering logic was erratic, leading to many transitions between &#8220;buffer completely empty&#8221; and &#8220;buffer completely full&#8221;. This, it turn, caused many transitions between the HaveEnoughData, HaveFutureData and HaveCurrentData readyStates in the player, leading to frequent pauses and unpauses on Broadcom platforms.</p>



<figure class="wp-block-image size-large"><a href="https://eocanha.org/blog/wp-content/uploads/2024/10/0.00.03.621786886-video-player-0_PAUSED_PLAYING.png"><img loading="lazy" width="1024" height="137" src="https://eocanha.org/blog/wp-content/uploads/2024/10/0.00.03.621786886-video-player-0_PAUSED_PLAYING-1024x137.png" alt="" class="wp-image-672" srcset="https://eocanha.org/blog/wp-content/uploads/2024/10/0.00.03.621786886-video-player-0_PAUSED_PLAYING-1024x137.png 1024w, https://eocanha.org/blog/wp-content/uploads/2024/10/0.00.03.621786886-video-player-0_PAUSED_PLAYING-300x40.png 300w, https://eocanha.org/blog/wp-content/uploads/2024/10/0.00.03.621786886-video-player-0_PAUSED_PLAYING-768x103.png 768w, https://eocanha.org/blog/wp-content/uploads/2024/10/0.00.03.621786886-video-player-0_PAUSED_PLAYING-1536x205.png 1536w, https://eocanha.org/blog/wp-content/uploads/2024/10/0.00.03.621786886-video-player-0_PAUSED_PLAYING-2048x273.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<p>So, one of the first thing I tried to solve this issue was to ask the Nexus PlayPump (the subsystem in charge of internal buffering in Nexus) about its internal levels, and add that to the levels reported by GstQueue2. There&#8217;s also a GstMultiqueue in the pipeline that can hold a significant amount of buffers, so I also asked it for its level. Still, the buffering level unstability was too high, so I added a moving average implementation to try to smooth it.</p>



<p>All these tweaks only make sense on Broadcom platforms, so they were guarded by ifdefs in a first version of the patch. Later, I migrated those dirty ifdefs to <a rel="noreferrer noopener" href="https://github.com/WebKit/WebKit/commit/5813c1e253b04bd1912f1729bc4cf7eae4efa3b1" data-type="URL" data-id="https://github.com/WebKit/WebKit/commit/5813c1e253b04bd1912f1729bc4cf7eae4efa3b1" target="_blank">the new quirks abstraction</a> added by Phil. A challenge of this migration was that I needed to store some attributes that were considered part of MediaPlayerPrivateGStreamer before. They still had to be somehow linked to the player private but only accessible by the platform specific code of the quirks. A special HashMap attribute stores those quirks attributes in an opaque way, so that only the specific quirk they belong to knows how to interpret them (using downcasting). I tried to use move semantics when storing the data, but <a rel="noreferrer noopener" href="https://eocanha.org/blog/2024/09/10/dont-shoot-yourself-in-the-foot-with-the-c-move-constructor/" data-type="URL" data-id="https://eocanha.org/blog/2024/09/10/dont-shoot-yourself-in-the-foot-with-the-c-move-constructor/" target="_blank">was bitten by object slicing</a> when trying to move instances of the superclass. In the end, moving the responsibility of creating the unique_ptr that stored the concrete subclass to the caller did the trick.</p>



<p>Even with all those changes, undesirable swings in the buffering level kept happening, and when doing a careful analysis of the causes I noticed that the monitoring of the buffering level was being done from different places (in different moments) and sometimes the level was regarded as &#8220;enough&#8221; and the moment right after, as &#8220;insufficient&#8221;. This was because the buffering level threshold was one single value. That&#8217;s something that a hysteresis mechanism (with low and high watermarks) can solve. So, a logical level change to &#8220;full&#8221; would only happen when the level goes above the high watermark, and a logical level change to &#8220;low&#8221; when it goes under the low watermark level.</p>



<p>For the threshold change detection to work, we need to know the previous buffering level. There&#8217;s a problem, though: the current code checked the levels from several scattered places, so only one of those places (the first one that detected the threshold crossing at a given moment) would properly react. The other places would miss the detection and operate improperly, because the &#8220;previous buffering level value&#8221; had been overwritten with the new one when the evaluation had been done before. To solve this, I centralized the detection in a single place &#8220;per cycle&#8221; (in <a rel="noreferrer noopener" href="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L2270" data-type="URL" data-id="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L2270" target="_blank">updateBufferingStatus()</a>), and then used the detection conclusions from <a rel="noreferrer noopener" href="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L2622" data-type="URL" data-id="https://github.com/WebKit/WebKit/blob/aededeb7ddd9e55b53d9eda0be721ab3fd8180e4/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp#L2622" target="_blank">updateStates()</a>.</p>



<p>So, with all this in mind, I refactored the buffering logic as <a href="https://commits.webkit.org/284072@main">https://commits.webkit.org/284072@main</a>, so now WebKit GStreamer has a buffering code much more robust than before. The unstabilities observed in Broadcom devices were gone and I could, at last, close <a rel="noreferrer noopener" href="https://github.com/WebPlatformForEmbedded/WPEWebKit/issues/1309" data-type="URL" data-id="https://github.com/WebPlatformForEmbedded/WPEWebKit/issues/1309" target="_blank">Issue 1309</a>.</p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ef9f961162240a9f9611efac1245afeb00d6e8d6e8&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ef9f961162240a9f9611efac1245afeb00d6e8d6e8/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ef9f961162240a9f9611efac1245afeb00d6e8d6e8&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ef9f961162240a9f9611efac1245afeb00d6e8d6e8/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Wed, 16 Oct 2024 06:12:00 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ef9f961162240a9f9611efac1245afeb00d6e8d6e8</guid>
        </item>
        <item>
            <title>Don’t shoot yourself in the foot with the C++ move constructor</title>
            <link>https://eocanha.org/blog/2024/09/10/dont-shoot-yourself-in-the-foot-with-the-c-move-constructor/</link>
            <description><![CDATA[

<p>Move semantics can be very useful to transfer ownership of resources, but as many other C++ features, it&#8217;s one more double edge sword that can harm yourself in new and interesting ways if you don&#8217;t read the small print.</p>



<p>For instance, if object moving involves super and subclasses, you have to keep an extra eye on what&#8217;s actually happening. Consider the following classes A and B, where the latter inherits from the former:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="cpp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#include &lt;stdio.h>
#include &lt;utility>

#define PF printf("%s %p\n", __PRETTY_FUNCTION__, this)

class A {
 public:
 A() { PF; }
 virtual ~A() { PF; }
 A(A&amp;&amp; other)
 {
  PF;
  std::swap(i, other.i);
 }

 int i = 0;
};

class B : public A {
 public:
 B() { PF; }
 virtual ~B() { PF; }
 B(B&amp;&amp; other)
 {
  PF;
  std::swap(i, other.i);
  std::swap(j, other.j);
 }

 int j = 0;
};</pre>



<p>If your project is complex, it would be natural that your code involves abstractions, with part of the responsibility held by the superclass, and some other part by the subclass. Consider also that some of that code in the superclass involves move semantics, so a subclass object must be moved to become a superclass object, then perform some action, and then moved back to become the subclass again. That&#8217;s a <strong>really bad idea</strong>!</p>



<p>Consider this usage of the classes defined before:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="cpp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">int main(int, char* argv[]) {
 printf("Creating B b1\n");
 B b1;
 b1.i = 1;
 b1.j = 2;
 printf("b1.i = %d\n", b1.i);
 printf("b1.j = %d\n", b1.j);
 printf("Moving (B)b1 to (A)a. Which move constructor will be used?\n");
 A a(std::move(b1));
 printf("a.i = %d\n", a.i);
 // This may be reading memory beyond the object boundaries, which may not be
 // obvious if you think that (A)a is sort of a (B)b1 in disguise, but it's not!
 printf("(B)a.j = %d\n", reinterpret_cast&lt;B&amp;>(a).j);
 printf("Moving (A)a to (B)b2. Which move constructor will be used?\n");
 B b2(reinterpret_cast&lt;B&amp;&amp;>(std::move(a)));
 printf("b2.i = %d\n", b2.i);
 printf("b2.j = %d\n", b2.j);
 printf("^^^ Oops!! Somebody forgot to copy the j field when creating (A)a. Oh, wait... (A)a never had a j field in the first place\n");
 printf("Destroying b2, a, b1\n");
 return 0;
}</pre>



<p>If you&#8217;ve read the code, those printfs will have already given you some hints about the harsh truth: if you move a subclass object to become a superclass object, you&#8217;re losing all the subclass specific data, because <strong>no matter if the original instance was one from a subclass, only the superclass move constructor will be used</strong>. And that&#8217;s bad, very bad. This problem is called <a rel="noreferrer noopener" href="https://en.wikipedia.org/wiki/Object_slicing" data-type="URL" data-id="https://en.wikipedia.org/wiki/Object_slicing" target="_blank">object slicing</a>. It&#8217;s specific to C++ and can also happen with copy constructors. See it with your own eyes:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="cpp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Creating B b1
A::A() 0x7ffd544ca690
B::B() 0x7ffd544ca690
b1.i = 1
b1.j = 2
Moving (B)b1 to (A)a. Which move constructor will be used?
A::A(A&amp;&amp;) 0x7ffd544ca6a0
a.i = 1
(B)a.j = 0
Moving (A)a to (B)b2. Which move constructor will be used?
A::A() 0x7ffd544ca6b0
B::B(B&amp;&amp;) 0x7ffd544ca6b0
b2.i = 1
b2.j = 0
^^^ Oops!! Somebody forgot to copy the j field when creating (A)a. Oh, wait... (A)a never had a j field in the first place
Destroying b2, a, b1
virtual B::~B() 0x7ffd544ca6b0
virtual A::~A() 0x7ffd544ca6b0
virtual A::~A() 0x7ffd544ca6a0
virtual B::~B() 0x7ffd544ca690
virtual A::~A() 0x7ffd544ca690</pre>



<p>Why can something that seems so obvious become such a problem, you may ask? Well, it depends on the context. It&#8217;s not unusual for the codebase of a long lived project to have started using raw pointers for everything, then switching to using references as a way to get rid of null pointer issues when possible, and finally switch to whole objects and copy/move semantics to get rid or pointer issues (references are just pointers in disguise after all, and there are ways to produce null and dangling references by mistake). But this last step of moving from references to copy/move semantics on whole objects comes with the small object slicing nuance explained in this post, and when the size and all the different things to have into account about the project steals your focus, it&#8217;s easy to forget about this.</p>



<p>So, please remember: <strong>never use move semantics that convert your precious subclass instance to a superclass instance</strong> thinking that the subclass data will survive. You can regret about it and create difficult to debug problems inadvertedly.</p>



<p>Happy coding!</p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ef9f960e2112ce9f9611efac1245afeb00d6e8d6e8&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ef9f960e2112ce9f9611efac1245afeb00d6e8d6e8/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ef9f960e2112ce9f9611efac1245afeb00d6e8d6e8&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ef9f960e2112ce9f9611efac1245afeb00d6e8d6e8/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Tue, 10 Sep 2024 07:58:47 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ef9f960e2112ce9f9611efac1245afeb00d6e8d6e8</guid>
        </item>
        <item>
            <title>Dissecting GstSegments</title>
            <link>https://eocanha.org/blog/2024/04/30/dissecting-gstsegments/</link>
            <description><![CDATA[

<p>During all these years using GStreamer, I&#8217;ve been having to deal with GstSegments in many situations. I&#8217;ve always have had an intuitive understanding of the meaning of each field, but never had the time to properly write a good reference explanation for myself, ready to be checked at those times when the task at hand stops being so intuitive and nuisances start being important. I used the notes I took during an interesting conversation with <a rel="noreferrer noopener" href="https://gitlab.freedesktop.org/mildsunrise" data-type="URL" data-id="https://gitlab.freedesktop.org/mildsunrise" target="_blank">Alba</a> and <a rel="noreferrer noopener" href="https://gitlab.freedesktop.org/ntrrgc" data-type="URL" data-id="https://gitlab.freedesktop.org/ntrrgc" target="_blank">Alicia</a> about those nuisances, during the <a rel="noreferrer noopener" href="https://wiki.gnome.org/Hackfests/GstAutumnHackfest2023" data-type="URL" data-id="https://wiki.gnome.org/Hackfests/GstAutumnHackfest2023" target="_blank">GStreamer Hackfest in A Coruña</a>, as the seed that evolved into this post.</p>



<p>But what are actually <a rel="noreferrer noopener" href="https://gstreamer.freedesktop.org/documentation/gstreamer/gstsegment.html" target="_blank">GstSegments</a>? They are the structures that track the values needed to <a rel="noreferrer noopener" href="https://gstreamer.freedesktop.org/documentation/application-development/advanced/clocks.html" target="_blank">synchronize</a> the playback of a region of interest in a media file.</p>



<p>GstSegments are used to coordinate the translation between Presentation Timestamps (<strong>PTS</strong>), supplied by the media, and <strong>Runtime</strong>.</p>



<p><strong>PTS</strong> is the timestamp that specifies, in buffer time, when the frame must be displayed on screen. This <strong>buffer time</strong> concept (called buffer running-time in the docs) refers to the ideal time flow where rate isn&#8217;t being had into account.</p>



<p>Decode Timestamp (<strong>DTS</strong>) is the timestamp that specifies, in buffer time, when the frame must be supplied to the decoder. On decoders supporting <a rel="noreferrer noopener" href="https://en.wikipedia.org/wiki/Video_compression_picture_types#Summary" data-type="URL" data-id="https://en.wikipedia.org/wiki/Video_compression_picture_types#Summary" target="_blank">P-frames</a> (forward-predicted) and B-frames (bi-directionally predicted), the PTS of the frames reaching the decoder may not be monotonic, but the PTS of the frames reaching the sinks are (the decoder outputs monotonic PTSs).</p>



<p><strong>Runtime</strong> (called clock running time in the docs) is the amount of physical time that the pipeline has been playing back. More specifically, the Runtime of a specific frame indicates the physical time that has passed or must pass until that frame is displayed on screen. It starts from zero.</p>



<p><strong>Base time</strong> is the point when the Runtime starts with respect to the input timestamp in buffer time (PTS or DTS). It&#8217;s the Runtime of the PTS=0.</p>



<p><strong>Start</strong>, <strong>stop</strong>, <strong>duration</strong>: Those fields are buffer timestamps that specify when the piece of media that is going to be played starts, stops and how long that portion of the media is (the absolute difference between start and stop, and I mean absolute because a segment being played backwards may have a higher start buffer timestamp than what its stop buffer timestamp is).</p>



<p><strong>Position</strong> is like the Runtime, but in buffer time. This means that in a video being played back at 2x, Runtime would flow at 1x (it&#8217;s physical time after all, and reality goes at 1x pace) and Position would flow at 2x (the video moves twice as fast than physical time).</p>



<p>The <strong>Stream Time</strong> is the position in the stream. Not exactly the same concept as buffer time. When handling multiple streams, some of them can be offset with respect to each other, not starting to be played from the begining, or even can have loops (eg: repeating the same sound clip from PTS=100 until PTS=200 intefinitely). In this case of repeating, the Stream time would flow from PTS=100 to PTS=200 and then go back again to the start position of the sound clip (PTS=100). There&#8217;s <a rel="noreferrer noopener" href="https://gstreamer.freedesktop.org/documentation/application-development/advanced/clocks.html?gi-language=c#time-overview" data-type="URL" data-id="https://gstreamer.freedesktop.org/documentation/application-development/advanced/clocks.html?gi-language=c#time-overview" target="_blank">a nice graphic in the docs</a> illustrating this, so I won&#8217;t repeat it here.</p>



<p><strong>Time</strong> is the base of Stream Time. It&#8217;s the Stream time of the PTS of the first frame being played. In our previous example of the repeating sound clip, it would be 100.</p>



<p>There are also concepts such as <strong>Rate</strong> and <strong>Applied Rate</strong>, but we didn&#8217;t get into them during the discussion that motivated this post.</p>



<p>So, for translating between Buffer Time (PTS, DTS) and Runtime, we would apply this formula:</p>



<p class="has-text-align-center">Runtime = BufferTime * ( Rate * AppliedRate ) + BaseTime</p>



<p>And for translating between Buffer Time (PTS, DTS) and Stream Time, we would apply this other formula:</p>



<p class="has-text-align-center">StreamTime = BufferTime * AppliedRate + Time</p>



<p>And that&#8217;s it. I hope these notes in the shape of a post serve me as reference in the future. Again, thanks to Alicia, and especially to Alba, for the valuable clarifications during the discussion we had that day in the <a rel="noreferrer noopener" href="https://www.igalia.com/" target="_blank">Igalia</a> office. This post wouldn&#8217;t have been possible without them.</p>



<p></p>



<p></p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ef06cee0a8413806ce11ef8e4b5d47feddd02fd02f&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ef06cee0a8413806ce11ef8e4b5d47feddd02fd02f/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ef06cee0a8413806ce11ef8e4b5d47feddd02fd02f&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ef06cee0a8413806ce11ef8e4b5d47feddd02fd02f/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Tue, 30 Apr 2024 06:00:00 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ef06cee0a8413806ce11ef8e4b5d47feddd02fd02f</guid>
        </item>
        <item>
            <title>Cat’s Panic</title>
            <link>https://eocanha.org/blog/2023/01/06/cats-panic/</link>
            <description><![CDATA[

<p>It&#8217;s been 8 years since the last time I wrote a videogame just for personal fun. As it&#8217;s now become a tradition, I took advantage of the extra focused personal time I usually have on the Christmas season and gave a try to <a href="https://processing.org/" data-type="URL" data-id="https://processing.org/">Processing</a> to do my own &#8220;advent of code&#8221;. It&#8217;s a programming environment based on Java that offers a similar visual, canvas-based experience to the one I enjoyed as a child in 8 bit computers. I certainly found coding there to be a pleasant and fun experience.</p>



<p>So, what I coded is called Cat&#8217;s Panic, my own version of a known arcade game with a similar name. In this version, the player has to unveil the outline of a hidden cute cat on each stage.</p>



<figure class="wp-block-image size-large"><a href="https://eocanha.org/blog/wp-content/uploads/2023/01/screenshot.png"><img loading="lazy" width="1024" height="724" src="https://eocanha.org/blog/wp-content/uploads/2023/01/screenshot-1024x724.png" alt="" class="wp-image-634" srcset="https://eocanha.org/blog/wp-content/uploads/2023/01/screenshot-1024x724.png 1024w, https://eocanha.org/blog/wp-content/uploads/2023/01/screenshot-300x212.png 300w, https://eocanha.org/blog/wp-content/uploads/2023/01/screenshot-768x543.png 768w, https://eocanha.org/blog/wp-content/uploads/2023/01/screenshot-1536x1086.png 1536w, https://eocanha.org/blog/wp-content/uploads/2023/01/screenshot.png 1640w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<p>The player uses the arrow keys to control a cursor that can freely move inside a border line. When pressing space, the cursor can start an excursion to try to cover a new area of the image to be unveiled. If any of the enemies touches the excursion path, the player loses a life. The excursion can be canceled at any time by releasing the space key. Enemies can be killed by trapping them in a released area. A stage is completed when 85% of the outline is unveiled.</p>



<p>Although this game is released under GPLv2, I don&#8217;t recommend anybody to look at its source code. It breaks all principles of good software design, it&#8217;s messy, ugly, and it&#8217;s only purpose was to make the developing process entertaining for me. You&#8217;ve been warned.</p>



<p>I&#8217;m open to contributions in the way of new cat pictures that add more stages to the already existing ones, though.</p>



<p>You can <a href="https://github.com/eocanha/CatsPanic" data-type="URL" data-id="https://github.com/eocanha/CatsPanic">get the source code in the GitHub repository</a> and <a href="https://github.com/eocanha/CatsPanic/releases" data-type="URL">a binary release for Linux here</a> (with all the Java dependencies, which weight a lot).</p>



<p>Meow, enjoy!</p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ed8d848e198c988d8411edb7798f3b3657845c845c&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ed8d848e198c988d8411edb7798f3b3657845c845c/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ed8d848e198c988d8411edb7798f3b3657845c845c&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ed8d848e198c988d8411edb7798f3b3657845c845c/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Fri, 06 Jan 2023 03:32:09 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ed8d848e198c988d8411edb7798f3b3657845c845c</guid>
        </item>
        <item>
            <title>Beyond Google Bookmarks</title>
            <link>https://eocanha.org/blog/2021/08/07/beyond-google-bookmarks/</link>
            <description><![CDATA[

<p>I was a happy user of Del.icio.us for many years until the service closed. Then I moved my links to <a href="https://www.google.com/bookmarks">Google Bookmarks</a>, which offered basically the same functionality (at least for my needs): link storage with title, tags and comments. I&#8217;ve carefully tagged and filed more than 2500 links since I started, and I&#8217;ve learnt to appreciate the usefulness of searching by tag to find again some precious information that was valuable to me in the past.</p>



<p>Google Bookmarks is a very old and simple service that &#8220;just works&#8221;. Sometimes it looked as if Google had just forgotten about it and let it run for years without anybody noticing&#8230; until now. It&#8217;s closing on September 2021.</p>



<p>I didn&#8217;t want to lose all my links, still need a link database searchable by tags and don&#8217;t want to be locked-in again in a similar service that might close in some years, so I wrote <a href="https://github.com/eocanha/bookmark-search" data-type="URL" data-id="https://github.com/eocanha/bookmark-search">my own super-simple alternative to it</a>. It&#8217;s called <code><a href="https://github.com/eocanha/bookmark-search/blob/main/bs" data-type="URL" data-id="https://github.com/eocanha/bookmark-search/blob/main/bs">bs</a></code>, sort of bookmark search.</p>



<p>The usage can&#8217;t be simpler, just add the tag you want to look for and it will print a list of links that have that tag:</p>



<pre class="wp-block-preformatted">$ bs webassembly
 &nbsp;title = Canvas filled three ways: JS, WebAssembly and WebGL | Compile
 &nbsp;&nbsp;&nbsp;url = https://compile.fi/canvas-filled-three-ways-js-webassembly-and-webgl/
 &nbsp;&nbsp;tags = canvas,graphics,html5,wasm,webassembly,webgl
 &nbsp;&nbsp;date = 2020-02-18 16:48:56
comment = &nbsp;

 &nbsp;title = Compiling to WebAssembly: It’s Happening! ★ Mozilla Hacks – the Web developer blog
 &nbsp;&nbsp;&nbsp;url = https://hacks.mozilla.org/2015/12/compiling-to-webassembly-its-happening/
 &nbsp;&nbsp;tags = asm.js,asmjs,emscripten,llvm,toolchain,web,webassembly
 &nbsp;&nbsp;date = 2015-12-18 09:14:35
comment = </pre>



<p>If you call the tools without parameters, it will prompt data to insert a new link or edit it if the entered url matches a preexisting one:</p>



<pre class="wp-block-preformatted">$ bs
url: https://compile.fi/canvas-filled-three-ways-js-webassembly-and-webgl/
title: Canvas filled three ways: JS, WebAssembly and WebGL | Compile
tags: canvas,graphics,html5,wasm,webassembly,webgl
comment:
</pre>



<p>The data is stored in an sqlite database and I&#8217;ve written some JavaScript snippets to <a href="https://github.com/eocanha/bookmark-search/blob/main/import/delicious-bookmarks-to-sqlite.txt">import the Delicious exported bookmarks file</a> and the <a href="https://github.com/eocanha/bookmark-search/blob/main/import/google-bookmarks-to-sqlite.txt" data-type="URL" data-id="https://github.com/eocanha/bookmark-search/blob/main/import/google-bookmarks-to-sqlite.txt">Google Bookmarks exported bookmarks file</a>. Those snippets are meant to be copypasted in the JavaScript console of your browser while you have the exported bookmarks html file open on it. They&#8217;ll generate SQL sentences that will populate the database for the first time with your preexisting data.</p>



<p>By now the tool doesn&#8217;t allow to delete bookmarks (I haven&#8217;t had the need yet) and I still need to find a way to simplify its usage through the browser with a bookmarklet to ease adding new bookmarks automatically. But that&#8217;s a task for other day. By now I have enough just by knowing that my bookmarks are now safe.</p>



<p>Enjoy!</p>



<p>[UPDATE: 2020-09-08]</p>



<p>I&#8217;ve now coded an <a href="https://github.com/eocanha/bookmark-search/blob/main/bs.php" data-type="URL" data-id="https://github.com/eocanha/bookmark-search/blob/main/bs.php">alternate variant of the database client</a> that can be hosted on any web server with PHP and SQLite3. The bookmarks can now be managed from a browser in a centralized way, in a similar fashion as you could before with Google Bookmarks and Delicious. As you can see in the screenshot, the style resembles Google Bookmarks in some way.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://eocanha.org/blog/wp-content/uploads/2021/09/image.png"><img loading="lazy" width="800" height="400" src="https://eocanha.org/blog/wp-content/uploads/2021/09/image.png" alt="" class="wp-image-626" srcset="https://eocanha.org/blog/wp-content/uploads/2021/09/image.png 800w, https://eocanha.org/blog/wp-content/uploads/2021/09/image-300x150.png 300w, https://eocanha.org/blog/wp-content/uploads/2021/09/image-768x384.png 768w" sizes="(max-width: 800px) 100vw, 800px" /></a></figure></div>



<p></p>



<p>You can easily create a quick search / search engine link in Firefox and Chrome (I use &#8220;d&#8221; as keyword, a tradition from the Delicious days, so that if I type &#8220;d debug&#8221; in the browser search bar it will look for that tag in the bookmark search page). Also, the <img src="https://s.w.org/images/core/emoji/13.1.0/72x72/1f516.png" alt="<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ebf7826045d1eef78211eb826f31726902ab12ab12&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ebf7826045d1eef78211eb826f31726902ab12ab12/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ebf7826045d1eef78211eb826f31726902ab12ab12&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ebf7826045d1eef78211eb826f31726902ab12ab12/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Sat, 07 Aug 2021 12:29:16 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ebf7826045d1eef78211eb826f31726902ab12ab12</guid>
        </item>
        <item>
            <title>GStreamer WebKit debugging by using external tools (2/2)</title>
            <link>https://eocanha.org/blog/2021/05/25/gstreamer-webkit-debugging-by-using-external-tools-2-2/</link>
            <description><![CDATA[

<p>This is the last post of the series showing interesting debugging tools, I hope you have found it useful. Don&#8217;t miss the custom scripts at the bottom to process GStreamer logs, help you highlight the interesting parts and find the root cause of difficult bugs. Here are also the previous posts of the series:</p>



<ul id="block-b42f86ed-cff9-42e2-b084-bd3cfb76f92c"><li><a href="https://eocanha.org/blog/2021/04/13/gstreamer-webkit-debugging-tricks-using-gdb-1-2/">GStreamer WebKit debugging tricks using GDB (1/2)</a></li><li><a href="https://eocanha.org/blog/2021/04/20/gstreamer-webkit-debugging-tricks-using-gdb-2-2/">GStreamer WebKit debugging tricks using GDB (2/2)</a></li><li><a href="https://eocanha.org/blog/2021/04/27/gstreamer-webkit-debugging-by-instrumenting-source-code-1-3/">GStreamer WebKit debugging by instrumenting source code (1/3)</a></li><li><a href="https://eocanha.org/blog/2021/05/04/gstreamer-webkit-debugging-by-instrumenting-source-code-2-3/">GStreamer WebKit debugging by instrumenting source code (2/3)</a></li><li><a href="https://eocanha.org/blog/2021/05/11/gstreamer-webkit-debugging-by-instrumenting-source-code-3-3/">GStreamer WebKit debugging by instrumenting source code (3/3)</a></li><li><a href="https://eocanha.org/blog/2021/05/18/gstreamer-webkit-debugging-by-using-external-tools-1-2/">GStreamer WebKit debugging by using external tools (1/2)</a></li></ul>



<h2>How to debug pkgconfig</h2>



<p>When <code>pkg-config</code> finds the <code>PKG_CONFIG_DEBUG_SPEW</code> env var, it explains all the steps used to resolve the packages:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">PKG_CONFIG_DEBUG_SPEW=1 /usr/bin/pkg-config --libs x11</pre>



<p>This is useful to know why a particular package isn&#8217;t found and what are the default values for <code>PKG_CONFIG_PATH</code> when it&#8217;s not defined. For example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Adding directory '/usr/local/lib/x86_64-linux-gnu/pkgconfig' from PKG_CONFIG_PATH
Adding directory '/usr/local/lib/pkgconfig' from PKG_CONFIG_PATH
Adding directory '/usr/local/share/pkgconfig' from PKG_CONFIG_PATH
Adding directory '/usr/lib/x86_64-linux-gnu/pkgconfig' from PKG_CONFIG_PATH
Adding directory '/usr/lib/pkgconfig' from PKG_CONFIG_PATH
Adding directory '/usr/share/pkgconfig' from PKG_CONFIG_PATH</pre>



<p>If we have tuned <code>PKG_CONFIG_PATH</code>, maybe we also want to add the default paths. For example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">SYSROOT=~/sysroot-x86-64
export PKG_CONFIG_PATH=${SYSROOT}/usr/local/lib/pkgconfig:${SYSROOT}/usr/lib/pkgconfig
# Add also the standard pkg-config paths to find libraries in the system
export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/lib/x86_64-linux-gnu/pkgconfig:\
/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib/x86_64-linux-gnu/pkgconfig:\
/usr/lib/pkgconfig:/usr/share/pkgconfig
# This tells pkg-config where the "system" pkg-config dir is. This is useful when cross-compiling for other
# architecture, to avoid pkg-config using the system .pc files and mixing host and target libraries
export PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib
# This could have been used for cross compiling:
#export PKG_CONFIG_SYSROOT_DIR=${SYSROOT}</pre>



<h2>Man in the middle proxy for WebKit</h2>



<p>Sometimes it&#8217;s useful to use our own modified/unminified files with a 3rd party service we don&#8217;t control. <a href="https://mitmproxy.org/">Mitmproxy</a> can be used as a man-in-the-middle proxy, but I haven&#8217;t tried it personally yet. What I have tried (with WPE) is this:</p>



<ol><li>Add an <code>/etc/hosts</code> entry to point the host serving the files we want to change to an IP address controlled by us.</li><li>Configure a web server to provide the files in the expected path.</li><li>Modify the <a href="https://github.com/WebKit/WebKit/blob/main/Source/WebCore/platform/network/ResourceRequestBase.h#L215">ResourceRequestBase constructor</a> to change the HTTPS requests to HTTP when the hostname matches the target:</li></ol>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">ResourceRequestBase(const URL&amp; url, ResourceRequestCachePolicy policy)
    : m_url(url)
    , m_timeoutInterval(s_defaultTimeoutInterval)
    ...
    , m_isAppBound(false)
{
    if (m_url.host().toStringWithoutCopying().containsIgnoringASCIICase(String("out-of-control-service.com"))
        &amp;&amp; m_url.protocol().containsIgnoringASCIICase(String("https"))) {
        printf("### %s: URL %s detected, changing from https to http\n",
            __PRETTY_FUNCTION__, m_url.string().utf8().data());
        fflush(stdout);
        m_url.setProtocol(String("http"));
    }
}</pre>



<p>:bulb: Pro tip: If you have to debug minified/obfuscated JavaScript code and don&#8217;t have a deobfuscated version to use in a man-in-the-middle fashion, use http://www.jsnice.org/ to deobfuscate it and get meaningful variable names.</p>



<h2>Bandwidth control for a dependent device</h2>



<p>If your computer has a &#8220;shared internet connection&#8221; enabled in Network Manager and provides access to a dependent device , you can control the bandwidth offered to that device. This is useful to trigger quality changes on adaptive streaming videos from services out of your control.</p>



<p>This can be done using <code>tc</code>, the Traffic Control tool from the Linux kernel. You can use <a href="https://pastebin.com/E2iVctCw">this script</a> to automate the process (edit it to suit to your needs).</p>



<h2>Useful scripts to process GStreamer logs</h2>



<p>I use these scripts in my daily job to look for strange patterns in GStreamer logs that help me to find the cause of the bugs I&#8217;m debugging:</p>



<ul><li><a href="https://github.com/paoloantinori/hhighlighter"><code>h</code></a>: Highlights each expression in the command line in a different color.</li><li><a href="https://pastebin.com/PrF2Gk2d"><code>mgrep</code></a>: Greps (only) for the lines with the expressions in the command line and highlights each expression in a different color.</li><li><a href="https://pastebin.com/2P6fHMS1"><code>filter-time</code></a>: Gets a subset of the log lines between a start and (optionally) an end GStreamer log timestamp.</li><li><a href="https://pastebin.com/fhzikUgK"><code>highlight-threads</code></a>: Highlights each thread in a GStreamer log with a different color. That way it&#8217;s easier to follow a thread with the naked eye.</li><li><a href="https://pastebin.com/G3fW3PGU"><code>remove-ansi-colors</code></a>: Removes the color codes from a colored GStreamer log.</li><li><code>aha</code>: ANSI-HTML-Adapter converts plain text with color codes to HTML, so you can share your GStreamer logs from a web server (eg: for bug discussion). Available in most distros.</li><li><a href="https://pastebin.com/1gqC6BKY"><code>gstbuffer-leak-analyzer</code></a>: Analyzes a GStreamer log and shows unbalances in the creation/destruction of GstBuffer and GstMemory objects.</li></ul>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ebbd326eb72cd0bd3211eb9d93dfba988cb754b754&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ebbd326eb72cd0bd3211eb9d93dfba988cb754b754/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ebbd326eb72cd0bd3211eb9d93dfba988cb754b754&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ebbd326eb72cd0bd3211eb9d93dfba988cb754b754/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Tue, 25 May 2021 06:00:00 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ebbd326eb72cd0bd3211eb9d93dfba988cb754b754</guid>
        </item>
        <item>
            <title>GStreamer WebKit debugging by using external tools (1/2)</title>
            <link>https://eocanha.org/blog/2021/05/18/gstreamer-webkit-debugging-by-using-external-tools-1-2/</link>
            <description><![CDATA[

<p>In this new post series, I&#8217;ll show you how both existing and ad-hoc tools can be helpful to find the root cause of some problems. Here are also the older posts of this series in case you find them useful:</p>



<ul id="block-b42f86ed-cff9-42e2-b084-bd3cfb76f92c"><li><a href="https://eocanha.org/blog/2021/04/13/gstreamer-webkit-debugging-tricks-using-gdb-1-2/">GStreamer WebKit debugging tricks using GDB (1/2)</a></li><li><a href="https://eocanha.org/blog/2021/04/20/gstreamer-webkit-debugging-tricks-using-gdb-2-2/">GStreamer WebKit debugging tricks using GDB (2/2)</a></li><li><a href="https://eocanha.org/blog/2021/04/27/gstreamer-webkit-debugging-by-instrumenting-source-code-1-3/">GStreamer WebKit debugging by instrumenting source code (1/3)</a></li><li><a href="https://eocanha.org/blog/2021/05/04/gstreamer-webkit-debugging-by-instrumenting-source-code-2-3/">GStreamer WebKit debugging by instrumenting source code (2/3)</a></li><li><a href="https://eocanha.org/blog/2021/05/11/gstreamer-webkit-debugging-by-instrumenting-source-code-3-3/">GStreamer WebKit debugging by instrumenting source code (3/3)</a></li></ul>



<h2>Use strace to know which config/library files are used by a program</h2>



<p>If you&#8217;re becoming crazy supposing that the program should use some config and it seems to ignore it, just use strace to check what config files, libraries or other kind of files is the program actually using. Use the grep rules you need to refine the search:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$ strace -f -e trace=%file nano 2> >(grep 'nanorc')
access("/etc/nanorc", R_OK)             = 0
access("/usr/share/nano/javascript.nanorc", R_OK) = 0
access("/usr/share/nano/gentoo.nanorc", R_OK) = 0
...</pre>



<h2>Know which process is killing another one</h2>



<p>First, try to <code>strace -e trace=signal -p 1234</code> the killed process.</p>



<p>If that doesn&#8217;t work (eg: because it&#8217;s being killed with the uncatchable SIGKILL signal), then you can resort to modifying the kernel source code (<a href="https://github.com/torvalds/linux/blob/6fb8f43cede0e4bd3ead847de78d531424a96be9/kernel/signal.c#L3677">signal.c</a>) to log the calls to <code>kill()</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
{
    struct task_struct *tsk_p;
    ...
    /* Log SIGKILL */
    if (sig &amp; 0x1F == 9) {
        tsk_p = find_task_by_vpid(pid);

        if (tsk_p) {
            printk(KERN_DEBUG "Sig: %d from pid: %d (%s) to pid: %d (%s)\n",
                sig, current->pid, current->comm, pid, tsk_p->comm);
        } else {
            printk(KERN_DEBUG "Sig: %d from pid: %d (%s) to pid: %d\n",
                sig, current->pid, current->comm, pid);
        }
    }
    ...
}</pre>



<h2>Wrap gcc/ld/make to tweak build parameters</h2>



<p>If you ever find yourself with little time in front of a stubborn build system and, no matter what you try, you can&#8217;t get the right flags to the compiler, think about putting something (a wrapper) between the build system and the compiler. Example for <code>g++</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/bin/bash
main() {
    # Build up arg[] array with all options to be passed
    # to subcommand.
    i=0
    for opt in "$@"; do
        case "$opt" in
        -O2) ;; # Removes this option
        *)
            arg[i]="$opt" # Keeps the others
            i=$((i+1))
            ;;
        esac
    done
    EXTRA_FLAGS="-O0" # Adds extra option
    echo "g++ ${EXTRA_FLAGS} ${arg[@]}" # >> /tmp/build.log # Logs the command
    /usr/bin/ccache g++ ${EXTRA_FLAGS} "${arg[@]}" # Runs the command
}
main "$@"</pre>



<p>Make sure that the wrappers appear earlier than the real commands in your PATH.</p>



<p>The <code>make</code> wrapper can also call <code>remake</code> instead. Remake is fully compatible with make but has features to help debugging compilation and makefile errors.</p>



<h2>Analyze the structure of MP4 data</h2>



<p>The <a href="https://gpac.github.io/mp4box.js/test/filereader.html">ISOBMFF Box Structure Viewer online tool</a> allows you to upload an MP4 file and explore its structure.</p>



<figure class="wp-block-image"><img src="https://i.imgur.com/XCFoez9.png" alt=""/></figure>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ebb7a1d846e212b7a111eb8af8e18e4d6ded65ed65&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ebb7a1d846e212b7a111eb8af8e18e4d6ded65ed65/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ebb7a1d846e212b7a111eb8af8e18e4d6ded65ed65&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ebb7a1d846e212b7a111eb8af8e18e4d6ded65ed65/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Tue, 18 May 2021 06:00:00 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ebb7a1d846e212b7a111eb8af8e18e4d6ded65ed65</guid>
        </item>
        <item>
            <title>GStreamer WebKit debugging by instrumenting source code (3/3)</title>
            <link>https://eocanha.org/blog/2021/05/11/gstreamer-webkit-debugging-by-instrumenting-source-code-3-3/</link>
            <description><![CDATA[

<p>This is the last post on the instrumenting source code series. I hope you to find the tricks below as useful as the previous ones. </p>



<p>In this post I show some more useful debugging tricks. Don&#8217;t forget to have a look at the other posts of the series:</p>



<ul id="block-b42f86ed-cff9-42e2-b084-bd3cfb76f92c"><li><a href="https://eocanha.org/blog/2021/04/13/gstreamer-webkit-debugging-tricks-using-gdb-1-2/">GStreamer WebKit debugging tricks using GDB (1/2)</a></li><li><a href="https://eocanha.org/blog/2021/04/20/gstreamer-webkit-debugging-tricks-using-gdb-2-2/">GStreamer WebKit debugging tricks using GDB (2/2)</a></li><li><a href="https://eocanha.org/blog/2021/04/27/gstreamer-webkit-debugging-by-instrumenting-source-code-1-3/">GStreamer WebKit debugging by instrumenting source code (1/3)</a></li><li><a href="https://eocanha.org/blog/2021/05/04/gstreamer-webkit-debugging-by-instrumenting-source-code-2-3/">GStreamer WebKit debugging by instrumenting source code (2/3)</a></li></ul>



<h2>Finding memory leaks in a RefCounted subclass</h2>



<p>The source code shown below must be placed in the .h where the class to be debugged is defined. It&#8217;s written in a way that doesn&#8217;t need to rebuild <code>RefCounted.h</code>, so it saves a lot of build time. It logs all refs, unrefs and adoptPtrs, so that any anomaly in the refcounting can be traced and investigated later. To use it, just make your class inherit from <code>LoggedRefCounted</code> instead of <code>RefCounted</code>.</p>



<p>Example output:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">void WTF::adopted(WTF::LoggedRefCounted&lt;T>*) [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount 1
void WTF::adopted(WTF::LoggedRefCounted&lt;T>*) [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount 1
^^^ Two adopts, this is not good.
void WTF::LoggedRefCounted&lt;T>::ref() [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount 1 --> ...
void WTF::LoggedRefCounted&lt;T>::ref() [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount ... --> 2
void WTF::LoggedRefCounted&lt;T>::deref() [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount 2 --> ...
void WTF::LoggedRefCounted&lt;T>::deref() [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount ... --> 1
void WTF::adopted(WTF::LoggedRefCounted&lt;T>*) [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount 1
void WTF::LoggedRefCounted&lt;T>::deref() [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount 1 --> ...
void WTF::LoggedRefCounted&lt;T>::deref() [with T = WebCore::MediaSourceClientGStreamerMSE]: this=0x673c07a4, refCount 1 --> ...
^^^ Two recursive derefs, not good either.</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#include "Logging.h"

namespace WTF {

template&lt;typename T> class LoggedRefCounted : public WTF::RefCounted&lt;T> {
    WTF_MAKE_NONCOPYABLE(LoggedRefCounted); WTF_MAKE_FAST_ALLOCATED;
public:
    void ref() {
        printf("%s: this=%p, refCount %d --> ...\n", __PRETTY_FUNCTION__, this, WTF::RefCounted&lt;T>::refCount()); fflush(stdout);
        WTF::RefCounted&lt;T>::ref();
        printf("%s: this=%p, refCount ... --> %d\n", __PRETTY_FUNCTION__, this, WTF::RefCounted&lt;T>::refCount()); fflush(stdout);
    }

    void deref() {
        printf("%s: this=%p, refCount %d --> ...\n", __PRETTY_FUNCTION__, this, WTF::RefCounted&lt;T>::refCount()); fflush(stdout);
        WTF::RefCounted&lt;T>::deref();
        printf("%s: this=%p, refCount ... --> %d\n", __PRETTY_FUNCTION__, this, WTF::RefCounted&lt;T>::refCount()); fflush(stdout);
    }

protected:
    LoggedRefCounted() { }
    ~LoggedRefCounted() { }
};

template&lt;typename T> inline void adopted(WTF::LoggedRefCounted&lt;T>* object)
{
    printf("%s: this=%p, refCount %d\n", __PRETTY_FUNCTION__, object, (object)?object->refCount():0); fflush(stdout);
    adopted(static_cast&lt;RefCountedBase*>(object));
}

} // Namespace WTF</pre>



<h2>Pause WebProcess on launch</h2>



<p><a href="https://github.com/WebKit/WebKit/blob/main/Source/WebKit/WebProcess/gtk/WebProcessMainGtk.cpp#L55">WebProcessMainGtk</a> and <a href="https://github.com/WebKit/WebKit/blob/main/Source/WebKit/WebProcess/wpe/WebProcessMainWPE.cpp#L88">WebProcessMainWPE</a> will sleep for 30 seconds if a special environment variable is defined:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">export WEBKIT2_PAUSE_WEB_PROCESS_ON_LAUNCH=1</pre>



<p>It only works <code>#if ENABLE(DEVELOPER_MODE)</code>, so you might want to remove those ifdefs if you&#8217;re building in Release mode.</p>



<h2>Log tracers</h2>



<p>In big pipelines (e.g. playbin) it can be very hard to find what element is replying to a query or handling an event. Even using gdb can be extremely tedious due to the very high level of recursion. My coworker <a href="https://github.com/ntrrgc" data-type="URL" data-id="https://github.com/ntrrgc">Alicia</a> commented that using log tracers is more helpful in this case.</p>



<p><code>GST_TRACERS=log</code> enables additional GST_TRACE() calls all accross GStreamer. The following example logs entries and exits into the query function.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">GST_TRACERS=log GST_DEBUG='query:TRACE'</pre>



<p>The names of the logging categories are somewhat inconsistent:</p>



<ul><li>log (the log tracer itself)</li><li>GST_BUFFER</li><li>GST_BUFFER_LIST</li><li>GST_EVENT</li><li>GST_MESSAGE</li><li>GST_STATES</li><li>GST_PADS</li><li>GST_ELEMENT_PADS</li><li>GST_ELEMENT_FACTORY</li><li>query</li><li>bin</li></ul>



<p>The log tracer code is in <code>subprojects/gstreamer/plugins/tracers/gstlog.c</code>.</p>
<span class="net_nemein_favourites">0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1ebb26ec5c667c6b26e11eb9de5bdf5b7cf7c4a7c4a&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1ebb26ec5c667c6b26e11eb9de5bdf5b7cf7c4a7c4a/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1ebb26ec5c667c6b26e11eb9de5bdf5b7cf7c4a7c4a&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1ebb26ec5c667c6b26e11eb9de5bdf5b7cf7c4a7c4a/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Tue, 11 May 2021 06:00:00 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1ebb26ec5c667c6b26e11eb9de5bdf5b7cf7c4a7c4a</guid>
        </item>
        <item>
            <title>Shishen Sho compiled for N900</title>
            <link>http://blogs.igalia.com/eocanha/?p=173</link>
            <description><![CDATA[
<p>I&#8217;ve recalled about my old <a href="https://garage.maemo.org/projects/shishensho/">Shishen Sho</a> game, originally developed for N810 (Maemo4) and I was wondering if it would compile for N900 (Maemo5). Well, after some minor corrections to make it work in a more recent version of Vala, it compiled. You can downloaded it here:</p>
<p><a href="https://garage.maemo.org/frs/download.php/7573/shishensho_0.3.1-maemo5_armel.deb">https://garage.maemo.org/frs/download.php/7573/shishensho_0.3.1-maemo5_armel.deb</a></p>
<p>Disclaimer: It&#8217;s compiled &#8220;as is&#8221;, with no adaption for sliding menus, no new hardware keys and no new fancy features. It just works and will let you have a good time while waiting for the bus.</p>
<span class="net_nemein_favourites">9 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=27a3c8301e9211dfaca35fdb9506f7eaf7ea&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/27a3c8301e9211dfaca35fdb9506f7eaf7ea/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=27a3c8301e9211dfaca35fdb9506f7eaf7ea&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/27a3c8301e9211dfaca35fdb9506f7eaf7ea/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Sun, 21 Feb 2010 02:11:36 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-27a3c8301e9211dfaca35fdb9506f7eaf7ea</guid>
        </item>
        <item>
            <title>Connecting a laptop to the internet with Yoigo trough N900 using bluetooth</title>
            <link>http://blogs.igalia.com/eocanha/?p=157</link>
            <description><![CDATA[
<p>Some simple steps to do tethering over bluetooth to connect to Yoigo Spanish carrier:</p>
<ol>
<lI>Enable the Maemo Extras-devel catalog (URL: http://repository.maemo.org/extras-devel, Distribution: fremantle, Components: free non-free) and install &#8220;Bluetooth Dial-up Networking&#8221;.</li>
<li>In your computer, edit <code>/etc/bluetooth/rfcomm.conf</code> to look like this, but using your own bluetooth device address (use <code>hcitool scan</code> from your laptop to get it):
<pre>
rfcomm1 {
        # Automatically bind the device at startup
        bind yes;                                 

        # Bluetooth address of the device
        device 00:11:22:33:44:55         

        # RFCOMM channel for the connection
        channel 2;                         

        # Description of the connection
        comment "N900";
}
</pre>
<p>Channels 1 and 3 are also available and can be defined as <code>rfcomm0</code> and <code>rfcomm2</code>, but the scope of that is out of this post.</li>
<li>Now edit the file <code>/home/youruser/.wvdialrc</code> in your laptop (using your own username) to look like this:
<pre>
[Dialer YoigoBT]
init1 = AT+CGDCONT=1,"IP","internet"
Username = ''
Password = ''
Modem = /dev/rfcomm1
Phone = *99#
</pre>
</li>
</ol>
<p>To connect to the internet, simply open a terminal and type:</p>
<pre>
sudo wvdial YoigoBT
</pre>
<p>To disconnect, just press CTRL+c and it&#8217;s done.</p>
<p>Thanks to <a href="http://www.go2linux.org/how-to-connect-internet-3g-gprs-using-bluetooth-usb-nokia-E71-cellular">this post</a>, which was used as a reference on how to connect using Nokia devices.</p>
<span class="net_nemein_favourites">12 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=23076a68ee4811de9d2a8b8f885f27762776&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/23076a68ee4811de9d2a8b8f885f27762776/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>1 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=23076a68ee4811de9d2a8b8f885f27762776&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/23076a68ee4811de9d2a8b8f885f27762776/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Mon, 21 Dec 2009 14:52:17 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-23076a68ee4811de9d2a8b8f885f27762776</guid>
        </item>
        <item>
            <title>Simple HTTP server in Python</title>
            <link>http://blogs.igalia.com/eocanha/?p=109</link>
            <description><![CDATA[
<p>Reading blog comments about <a href="http://meiga.igalia.com">Meiga</a> out there, I&#8217;ve found <a href="http://www.makeuseof.com/tag/dead-simple-file-sharing-with-meiga-linux/">one particularly interesting</a>. Python has an embedded HTTP server that can serve the current directory from a given port. It can be instanced for port 8282 simply issuing this command:</p>
<pre>
  python -m SimpleHTTPServer 8282
</pre>
<p>The funny thing is that&#8230; it works on the N810 also!</p>
<p>More info about SimpleHTTPServer <a href="http://docs.python.org/library/simplehttpserver.html">here</a>.</p>
<span class="net_nemein_favourites">17 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=38b3ab32648811deb2f7b36f459a0a330a33&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/38b3ab32648811deb2f7b36f459a0a330a33/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>1 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=38b3ab32648811deb2f7b36f459a0a330a33&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/38b3ab32648811deb2f7b36f459a0a330a33/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Mon, 29 Jun 2009 07:59:08 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-38b3ab32648811deb2f7b36f459a0a330a33</guid>
        </item>
        <item>
            <title>A safe upgrade to Diablo</title>
            <link>http://blogs.igalia.com/eocanha/?p=78</link>
            <description><![CDATA[
<p>At the end, Maemo Diablo release for N810 is out. But if you have valuable information, programs or configuration on it maybe you&#8217;re worried about what you&#8217;ll loose in a reflashing. In fact, if you&#8217;ve done the upgrade yet you&#8217;ll notice that the main part of the apps from Extras repository are missing in Diablo for the moment. Fortunately, there&#8217;s a way to install the apps from the old Chinook repository.</p>
<p>Here are six simple steps to perform the upgrade process and restore all your current applications:</p>
<ol>
<li>Backup your /home/user to a safe place by hand. Standard backup tool won&#8217;t<br />
backup every file you&#8217;ve at home and maybe you could need them later&#8230;</li>
<li>Do a backup using the backup tool.</li>
<li>Reflash the device with the <a href="http://tablets-dev.nokia.com/nokia_N810.php?f=RX-44_DIABLO_4.2008.23-14_PR_COMBINED_MR0_ARM.bin">new image</a> using the <a href="http://tablets-dev.nokia.com/d3.php">flasher tool</a> according to the <a href="http://maemo.org/community/wiki/HOWTO_FlashLatestNokiaImageWithLinux/#a4f6eb951c9d89a4a9027f479f3935c8">reflashing instructions</a></li>
<li>Restore the backup. Some old apps will remain grayshaded because the backup<br />
tool can&#8217;t find them in the now current Diablo repository.</li>
<li>Open Application Manager. Menu, tools, application catalog. Maemo Extras,<br />
edit. Distribution: chinook, uncheck the &#8220;disabled&#8221; checkbox, Accept. Close.</li>
<li>Menu, tools, restore applications. Accept.</li>
</ol>
<p>That&#8217;s all. Enjoy your updated device!</p>
<span class="net_nemein_favourites">5 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=d9708c8e42a111ddad19edf05367a91fa91f&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/d9708c8e42a111ddad19edf05367a91fa91f/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=d9708c8e42a111ddad19edf05367a91fa91f&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/d9708c8e42a111ddad19edf05367a91fa91f/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Wed, 25 Jun 2008 09:53:22 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-d9708c8e42a111ddad19edf05367a91fa91f</guid>
        </item>
        <item>
            <title>Shishen Sho Mahjongg 0.3 released</title>
            <link>http://blogs.igalia.com/eocanha/?p=76</link>
            <description><![CDATA[
<p>Version 0.3 of Shishen Sho Mahjongg has just been released. The main improvements since 0.2 are: Gravity, hints, undo history, time counter and speed improvements.</p>
<p>You can download the game and know more about it visiting <a href="https://garage.maemo.org/projects/shishensho">the project page at Maemo Garage</a>.</p>
<p>Enjoy it!</p>
<p><a href="http://maemo.org/downloads/product/raw/OS2008/shishensho/?get_installfile"><img src="http://maemo.org/midcom-static/style_maemo2007/install_button_small.png" alt="Click here to install this application" title="Click here to install this application" align="right" style="margin: 10px; padding: 0px;"/></a></p>
<p><b>28/05/2008 UPDATE:</b> Now the application is also available in Maemo Extras repository and listed in <a href="http://maemo.org/downloads/product/OS2008/shishensho">Maemo Downloads</a> with its own green &#8220;click to install&#8221; icon <img src='http://blogs.igalia.com/eocanha/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<span class="net_nemein_favourites">4 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=bb42a67c2acb11dd9cd60fa77a45f1e9f1e9&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/bb42a67c2acb11dd9cd60fa77a45f1e9f1e9/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=bb42a67c2acb11dd9cd60fa77a45f1e9f1e9&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/bb42a67c2acb11dd9cd60fa77a45f1e9f1e9/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Mon, 26 May 2008 00:39:53 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-bb42a67c2acb11dd9cd60fa77a45f1e9f1e9</guid>
        </item>
        <item>
            <title>Shishen Sho Mahjongg 0.2 released</title>
            <link>http://blogs.igalia.com/eocanha/?p=75</link>
            <description><![CDATA[
<p><a href="http://blogs.igalia.com/eocanha/?p=73">Last month I published Shishen Sho Mahjongg for Gtk and Maemo</a>, a board game similar to Mahjongg where the goal is to remove all the tile pairs and two tiles can be removed if a line with a maximum of three segments can be drawn between them.</p>
<p>Today I&#8217;m announcing version 0.2. The main improvements since 0.1.1 are Hildon integration (fullscreen, embedded menu, notifications) through conditional compilation and drawing of matching path when two pieces are matched.</p>
<p>You can download the game and know more about the project following these links:</p>
<ul>
<li><a href="https://garage.maemo.org/projects/shishensho">Project page at Maemo Garage</a></li>
<li>Maemo version: <a href="https://garage.maemo.org/frs/download.php/4079/shishensho_0.2.0-1_armel.deb">shishensho_0.2.0-1_armel.deb</a></li>
<li>Desktop version (i386): <a href="https://garage.maemo.org/frs/download.php/4080/shishensho_0.2.0-1_i386.deb">shishensho_0.2.0-1_i386.deb</a></li>
<li>Source code: <a href="https://garage.maemo.org/frs/download.php/4082/shishensho-0.2.0.tar.gz">shishensho-0.2.0.tar.gz</a></li>
<li>SVN repository: <a href="https://garage.maemo.org/plugins/scmsvn/viewcvs.php/?root=shishensho">svn checkout https://garage.maemo.org/svn/shishensho</a></li>
<li>Vala website at Gnome Live!: <a href="http://live.gnome.org/Vala#head-a2a9eb379001c7c92a6fcf5b84b0f08f8b71f997">List of applications developed in Vala</a></li>
</ul>
<p>Feel free to send me your comments, suggestions or patches over the original Vala sources.</p>
<p>Thank you! <img src='http://blogs.igalia.com/eocanha/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><center><br />
<a href="http://people.igalia.com/eocanha/shishensho/shishensho-screenshot2.png"><img src="http://people.igalia.com/eocanha/shishensho/shishensho-screenshot2-mini.png" border="0"></a><br />
</center></p>
<span class="net_nemein_favourites">6 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=178c0bc225da11ddb3743fda5d54f0edf0ed&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/178c0bc225da11ddb3743fda5d54f0edf0ed/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=178c0bc225da11ddb3743fda5d54f0edf0ed&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/178c0bc225da11ddb3743fda5d54f0edf0ed/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Mon, 19 May 2008 19:06:19 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-178c0bc225da11ddb3743fda5d54f0edf0ed</guid>
        </item>
        <item>
            <title>Setting up Vala on Maemo and CPP integration</title>
            <link>http://blogs.igalia.com/eocanha/?p=74</link>
            <description><![CDATA[
<p>Until now, when I wanted to build some Vala source code for the Maemo platform I generated C code using the i386 Vala compiler and then builded the executable inside the scratchbox using gcc. That was fine until I wanted to use Hildon features (not available for i386). I definitely needed the Vala compiler running on the scratchbox.</p>
<p>This weekend I&#8217;ve put myself on the way and managed to compile Vala 0.3.2 on the scratchbox for the CHINOOK_ARMEL target. The process was much simpler than I expected and consisted of these few steps:</p>
<ol>
<li>Log into the scratchbox and choose CHINOOK_ARMEL</li>
<li>Download the compiler from http://live.gnome.org/Vala/Release (I tried version 0.3.2)</li>
<li>Untar it: <code>tar jxvf vala-0.3.2.tar.bz2</code></li>
<li>Enter the vala-0.3.2 directory and configure the package for ARMEL cross compiling: <code>./configure --host=armel</code></li>
<li>Compile and install: <code>make; make install</code></li>
</ol>
<p>Alternately, to build for target CHINOOK_X86, repeat the previous steps but logged into the CHINOOK_X86 target. In step 3, issue <code>./configure</code> without arguments instead.</p>
<p>That&#8217;s it. You have now the Vala compiler ready to be used. But if you want to develop a multiplatform project, you&#8217;ll need to avoid compilation of the Hildon related code when not building for Maemo target. The best way I found to do that was to use CPP as a preprocessor to allow me to use #ifdef&#8217;s in the code.</p>
<p>This is a simple way to use CPP to preprocess a single file:</p>
<p><code>cpp -P -Dsymbol1 -Dsymbol2 ... source.vala destination.vala</code></p>
<p>But I&#8217;ve managed to tweak my compilation script to preprocess all the files, write the result to a directory called CPP and finally compiling the result. Here&#8217;s the source:</p>
<pre>
# File compile.sh
export DEFINE=""
export APPNAME="myapp"
export PACKAGES="--thread --pkg gtk+-2.0 --pkg gdk-2.0 --pkg libglade-2.0 --pkg gmodule-2.0"

# Perform preprocessing and output to CPP directory
# Arguments to this script are "defined" and passed to CPP
for i in $@
do
 DEFINE="$DEFINE -D$i"
 case $i in
  MAEMO)
   PACKAGES="$PACKAGES --pkg hildon-1"
   ;;
 esac
done
if [ ! -d CPP ]; then mkdir CPP; fi
for f in *.vala; do cpp -P $DEFINE $f CPP/$f; done
valac $PACKAGES CPP/*.vala -o $APPNAME -X -g -X "-Wl,--export-dynamic -rdynamic"`
rm -rf CPP
</pre>
<p>The <code>compile.sh</code> script can be used by passing it the symbol set that should be defined. For instance, <code>./compile.sh MAEMO DEV</code> would define both <code>MAEMO</code> and <code>DEV</code> symbols. Note that with this approach you should check the source files in the CPP directory when errors happen, because the line numbers referenced by the Vala compiler will be related to them and not to the original files.</p>
<p>I think this approach will be useful for other programmers too, so <a href="http://live.gnome.org/Vala/FAQ">I&#8217;ve contributed it to the Vala FAQ (Does Vala have a preprocessor?)</a>.</p>
<span class="net_nemein_favourites">5 <a href="http://maemo.org/news/?net_nemein_favourites_execute=fav&net_nemein_favourites_execute_for=1157c1bc259711dd9cc9c530a950b741b741&net_nemein_favourites_url=https://maemo.org/news/favorites//json/fav/midgard_article/1157c1bc259711dd9cc9c530a950b741b741/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-favorite.png" style="border: none;" alt="Add to favourites" title="Add to favourites" /></a>0 <a href="http://maemo.org/news/?net_nemein_favourites_execute=bury&net_nemein_favourites_execute_for=1157c1bc259711dd9cc9c530a950b741b741&net_nemein_favourites_url=https://maemo.org/news/favorites//json/bury/midgard_article/1157c1bc259711dd9cc9c530a950b741b741/" class="net_nemein_favourites_create"><img src="http://static.maemo.org:81/net.nemein.favourites/not-buried.png" style="border: none;" alt="Bury" title="Bury" /></a></span>]]></description>
            <author>Enrique Ocaña González &lt;eocanha@igalia.com&gt;</author>
            <category>feed:218abbb3f30ed17e36476558d8bce9b5</category>
            <pubDate>Mon, 19 May 2008 09:21:03 +0000</pubDate>
            <guid>http://maemo.org/midcom-permalink-1157c1bc259711dd9cc9c530a950b741b741</guid>
        </item>
    </channel>
</rss>
