<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
    <title>Michael Calabrese</title>
    <link>https://mccalabrese.github.io/gnome-blog</link>
    <description>GSoC development blog</description>

    
    
    <item>
        <title>Pitivi Timeline Ruler | Widget Finalization</title>
        <link>https://mccalabrese.github.io/gnome-blog/posts/fourth-post/</link>
        <guid>https://mccalabrese.github.io/gnome-blog/posts/fourth-post/</guid>
        <pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
        <description><![CDATA[
            <h2 id="c-api-and-introspection">C API and Introspection</h2>
<p>I spent some time cleaning up the Rust C extension and the FFI layer to make it easier to consume from C and through GObject Introspection. One of the biggest changes was exposing the PitiviTimelineRuler instance type in the public headers instead of treating it as a generic GtkWidget. That gives GIR enough information to generate proper bindings automatically.</p>
<p>I also fixed an issue that only showed up in headless CI environments. The widget was previously relying on gtk::init() during type registration, which doesn't work well without a display server. Switching to set_initialized() solved the problem and made the test suite much more reliable.</p>
<h2 id="rendering-improvements">Rendering Improvements</h2>
<p>The rendering code also received a fairly large cleanup. Previously, the widget stored several pieces of drawing state separately, including adjustments, cached Pango layouts, and font descriptions. These have now been grouped into a single DrawingState struct protected by one RefCell.</p>
<p>Besides making the code easier to reason about, this reduces unnecessary borrow checks during rendering and avoids situations where only part of the drawing state could be updated while signals were being emitted.</p>
<p>I also introduced a labels_dirty flag so timeline labels are only recalculated when they're actually needed during the snapshot phase. That removes quite a bit of redundant layout work while scrolling and zooming.</p>
<h2 id="timeline-marker-api">Timeline Marker API</h2>
<p>The custom layout manager is nearly finished, and with it comes a much simpler way to place widgets on the timeline.</p>
<p>I am currently wrapping up an add_marker() API that will allow attaching any GTK widget to the ruler at a specific timestamp. The PitiviTimelineLayoutChild now exposes the widget's timestamp as a GObject property.</p>
<p>I'm looking forward to getting this merged, as it should make timeline overlays and markers much easier to implement.</p>
<h2 id="stability-fixes">Stability Fixes</h2>
<p>I also addressed a few smaller edge cases along the way. One of them involved enforcing a minimum value for min_tick_spacing_px, preventing potential divide-by-zero errors when calculating the tick spacing.</p>

        ]]></description>
    </item>
    
    
    
    <item>
        <title>GUADEC 2026</title>
        <link>https://mccalabrese.github.io/gnome-blog/posts/guadec/</link>
        <guid>https://mccalabrese.github.io/gnome-blog/posts/guadec/</guid>
        <pubDate>Thu, 23 Jul 2026 00:00:00 +0000</pubDate>
        <description><![CDATA[
            <p>When Felipe first emailed us about the GUADEC 2026 travel grant, we were thrilled to learn that we were going to have the opportunity to attend the conference in person.</p>
<p>This was my first GUADEC, and it was a pleasure to meet the GNOME community and put faces to names. The conference was held in A Coruña, Spain, which turned out to be an amazing city with great food, friendly people, and beautiful views along the coast.</p>
<div style="display:flex; gap:1rem; justify-content:center; flex-wrap:wrap;">
    <img src="sign.jpg" alt="GUADEC 2026" style="width:48%; max-width:500px;">
    <img src="soccer.jpg" alt="A Coruña" style="width:48%; max-width:500px;">
</div>
<h2 id="community">Community</h2>
<p>The first thing I would like to mention was how patient and open the community was to both my fiancée Laureen and me. We knew going into the conference that we were much more junior than many of the developers attending, but everyone was incredibly approachable.</p>
<p>I received a great deal of help debugging issues in my local development environment, as well as guidance on some of the more difficult parts of my GSoC project.</p>
<div style="display:flex; gap:1rem; justify-content:center; flex-wrap:wrap;">
    <img src="dinner.png" alt="GUADEC 2026 Dinner" style="width:48%; max-width:500px;">
    <img src="conference.jpg" alt="A Coruña" style="width:48%; max-width:500px;">
</div>
<h2 id="talks">Talks</h2>
<p>The talks were very informative and I took way too many notes to include them all here without turning this into a novel. That said, I wanted to write a short summary of a couple of talks that I found interesting:</p>
<h3 id="varlink-for-system-components">Varlink for System Components</h3>
<p>Sebastian Wick gave a talk about modernizing the system component stack. His proposed idea for allowing more memory safety and zero cost abstractions was to write components in Rust, however this introduces the issue of introspection. For asynchronous functionality, Tokio and Glib both have main loops, and moving data between the loops can introduce a lot of overhead. GObject bindings can also make Rust's memory safety essentially moot.</p>
<p>Sebastian spoke about potentially not using GObject in some cases, and instead exposing more functionality over IPC using Varlink. Varlink is language agnostic, and services could be consumed from many languages without requiring GObject bindings. This process also would be very simple, allowing signals to occur as JSON strings that are easily observable. This would require some new crates to replace Glib functionality, and some more complicated functionality like file thrashing and sftp could be particularly difficult.</p>
<p>It is early, the ecosystem is still being built, but Sebastian argued that usage patterns will evolve and getting involved now will help shape the future of GNOME and Rust.</p>
<h3 id="using-gtk-in-c-with-peel">Using GTK in C++ with Peel</h3>
<p>Sergey Bugaev hosted a workshop on using GTK from C++ with Peel. Peel is a library that allows you to use GTK in C++ to make GTK applications and widgets. Sergey made a simple widget that can draw using stylus input, and he walked us through the process of creating a simple application using Peel. The workshop was very informative.</p>
<p>I really regret not coding his example myself, I wish a recording of the lecture had been taken. That said, his repo can be found at <a rel="external" href="https://gitlab.gnome.org/bugaevc/peel">https://gitlab.gnome.org/bugaevc/peel</a> and his readme has instructions for usage and a basic code example.</p>
<h3 id="debugging-with-tracy">Debugging with Tracy</h3>
<p>Ivan Molodetskikh gave a talk that seemed really handy to me about using Tracy to profile performance for Mutter, GNOME shell, and applications. I had never heard of Tracy before this talk, however the capabilities seemed very handy. Tracy visualizes "zones" on a timeline, allowing you to see exactly where execution time is being spent across threads. The Tracy zones must nest correctly, where parent zones cannot end before their child zones. It can also show where threads are waiting. This allows for a very clear visualization of where time is being spent in the application, and can help identify bottlenecks or bugs.</p>
<p>The major downside to Tracy is that it requires a lot of setup, and the application must be compiled with the Tracy client library. Ivan gave a fairly in-depth breakdown of how to add Tracy profiling to an application, and I will go back to the recording of his talk to actually implement it in the future.</p>
<h2 id="technical-take-aways-for-my-project">Technical Take Aways for My Project</h2>
<ul>
<li>
<p>Sergey Bugaev helped me get the GIR generation for my C API working correctly. We also improved the FFI by exposing <code>PitiviTimelineRuler</code> directly in the public header rather than accepting a generic <code>GtkWidget*</code> and performing a runtime type check. This makes the API more type-safe and simplifies the Rust implementation. The GIR generation currently works after calling <code>gtk::init()</code> from <code>pitivi_timeline_ruler_get_type()</code>, but Sergey pointed out that this approach will likely fail in CI because the generated scanner shouldn't require GTK to be initialized this way. I'm still trying to build a solid mental model of how GIR generation and introspection work, so if anyone has experience with bindings, I'd love to hear your thoughts.</p>
</li>
<li>
<p>Federico also spent some time reviewing my project with me. He suggested refactoring <code>PitiviTimelineRuler</code> so all of the mutable drawing state lives inside a single RefCell rather than several individual ones, I think the result would look something like this:</p>
</li>
</ul>
<pre><code>#[derive(Default)]
struct DrawingState {
    cache: BTreeMap&lt;...&gt;,
    font: Option&lt;...&gt;,
    handler_id: Option&lt;...&gt;,
}

#[derive(Properties)]
#[properties(wrapper_type = super::MyWidget)]
pub struct MyWidget {

    #[property(get, set)]
    zoom_level: Cell&lt;u64&gt;,

    state: RefCell&lt;DrawingState&gt;,
}
</code></pre>
<h2 id="thanks-to-gnome-foundation">Thanks to GNOME Foundation</h2>
<p>I want to give a special thanks to the GNOME Foundation for granting us the travel grant to attend GUADEC 2026. It was a wonderful experience and I look forward to attending future conferences in person!</p>
<p>A full-resolution album of these photos is available under CC BY 4.0 for anyone in the GNOME community to reuse.
<a rel="external" href="https://www.flickr.com/photos/204880226@N08/albums/72177720334807665/">https://www.flickr.com/photos/204880226@N08/albums/72177720334807665/</a></p>
<img src="sponsored-by-foundation.png" alt="Sponsored by GNOME Foundation" style="width:30%; max-width:300px;">

        ]]></description>
    </item>
    
    
    
    <item>
        <title>Pitivi Timeline Ruler | Widget Maturing</title>
        <link>https://mccalabrese.github.io/gnome-blog/posts/third-post/</link>
        <guid>https://mccalabrese.github.io/gnome-blog/posts/third-post/</guid>
        <pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate>
        <description><![CDATA[
            <p>Hello GNOME, This is a progress report on the Pitivi Timeline Ruler Rust rewrite.</p>
<h3 id="progress">Progress</h3>
<p>We are rewriting the Pitivi Ruler in Rust using a modern <code>GtkSnapshot</code> rendering pipeline to improve performance and memory safety. At its current stage the ruler is being constructed as a standalone widget in a personal repository that can be found here:</p>
<p><a rel="external" href="https://gitlab.gnome.org/Mccalabrese/pitivi-timeline-ruler">Pitivi Timeline Ruler</a></p>
<pre><code>GTK_DEBUG=interactive cargo run --example sandbox
</code></pre>
<p><em>Any feedback on the code is greatly appreciated!</em></p>
<h3 id="updates">Updates</h3>
<p>The widget is drawing well and a lot of the initial bugs have been ironed out.</p>
<p>A major structural change that has been made after mentor feedback was to pull state orchestration out of the widget itself, and keep more of the logic on the app side. The goal is a "dumb widget, smart app" framework, where the ruler acts as a stateless viewport. The app (or sandbox example) provides the logic for how to handle gestures and what to do when the user interacts with the widget. One example of this is that <code>project_duration</code> was removed as a property entirely, and logic around bounds is now handled entirely on the app side. This allows the widget to be used in a variety of contexts, and allows the app to handle bounds in whatever way is appropriate for the context.</p>
<p>Beyond the pivot on structure, some key systems-level refinements were made:</p>
<ul>
<li>
<p>Property types we refactored heavily as this moved past the rough prototype stage. <code>zoom_level</code> received a rename to <code>ns_per_pixel</code> to better reflect what the property actually represents. Many properties dealing with pixels were changed to unsigned integers, which allowed me to delete out some negative checks.</p>
</li>
<li>
<p>The project does now include a rough doc string and comment draft for the widget, which will be fleshed out more as the widget matures and more of the public API is finalized.</p>
</li>
<li>
<p>Cache clearing was added to <code>set_ns_per_pixel</code> to prevent modulo math escapes during purging of cached layouts when users change the zoom level.</p>
</li>
</ul>
<h3 id="next-steps">Next Steps</h3>
<p>The major milestone ahead is the implementation of a custom <code>gtk::LayoutManager</code> to handle the layout of children widgets.</p>
<p>Once the <code>PitiviTimelineLayoutManager</code> is implemented, the playhead rendering will be moved out of the ruler's snapshot pipeline and into the layout manager as a distinct child widget. This will allow Pitivi to easily inject custom markers, loop-brackets, and multiple playheads without modifying the underlying ruler engine.</p>
<p>I am currently studying Marc-André Lureau's <code>rdw</code> (Remote Desktop Widget) repository as a guide on how to make this update.</p>

        ]]></description>
    </item>
    
    
    
    <item>
        <title>Pitivi Timeline Ruler | Standalone Beta Progress</title>
        <link>https://mccalabrese.github.io/gnome-blog/posts/second-post/</link>
        <guid>https://mccalabrese.github.io/gnome-blog/posts/second-post/</guid>
        <pubDate>Thu, 18 Jun 2026 00:00:00 +0000</pubDate>
        <description><![CDATA[
            <p>Hello GNOME, This is a progress report on the Pitivi Timeline Ruler Rust rewrite.</p>
<h3 id="progress">Progress</h3>
<p>We are rewriting the Pitivi Ruler in Rust and gtk4 snapshot logic to improve performance and memory safety. At its current stage the ruler is being constructed as a standalone widget in a personal repo that can be found here:</p>
<p><a rel="external" href="https://gitlab.gnome.org/Mccalabrese/pitivi-timeline-ruler">Pitivi Timeline Ruler</a></p>
<pre><code>GTK_DEBUG=interactive cargo run --example sandbox
</code></pre>
<p><em>Any feedback on the code is greatly appreciated!</em></p>
<h3 id="structure">Structure</h3>
<p>I am structuring this around rendering a single interval of ticks between two major ticks once, then stamping that across the duration of the project, as seen in <code>draw_single_interval()</code>.</p>
<p>With the ticks stamped across the timeline I am then rendering a cache of Pango labels for the timestamps that are stamped across the visible window. I made the decision to use a BTreeMap for the cache for ease of iterating chronologically through the stamps and for dropping out-of-bounds keys. The logic for this cache handling primarily lives in <code>update_label_cache()</code>.</p>
<p>After some feedback from members of the video editing community, I made the decision that minor ticks should always be clean multiples of frames in the time period. This logic is implemented in <code>calculate_minor_divisions()</code>.</p>
<h3 id="next-steps">Next Steps</h3>
<p>The primary goal I am focusing on next is implementing the gesture handling, including click and drag actions. Once gestures are implemented I am going to begin moving a lot of the math to traits so that I can write a mock_env and a live_env to start writing some unit testing.</p>

        ]]></description>
    </item>
    
    
    
    <item>
        <title>Synchronizing Timeline Ticks with GES Framerates in Rust</title>
        <link>https://mccalabrese.github.io/gnome-blog/posts/ges-sync/</link>
        <guid>https://mccalabrese.github.io/gnome-blog/posts/ges-sync/</guid>
        <pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate>
        <description><![CDATA[
            <p>While working on my GSoC project (rewriting the Pitivi timeline in Rust), I ran into an issue getting precise UI ticks that map to the
absolute nanosecond timestamps of the video frames. Initially I hardcoded NTSC fractional math (24000/1001) to calculate the boundaries of frames.</p>
<p>This led to issues with truncated timestamps, and had a glaring issue with other framerates (like 30fps). I needed a more robust solution that could handle any framerate and provide accurate tick positions.</p>
<p>I assumed that I could extract the framerate directly from <code>ges::Timeline</code>, however there is no direct getter in the Rust bindings. After some digging, I discovered that the framerate is actually stored in the <code>gst::Caps</code> of the timeline's video stream as a <code>gst::Fraction</code>.</p>
<h3 id="my-approach">My Approach</h3>
<p>The steps I used:</p>
<ul>
<li>Enumerate the timeline tracks (<code>timeline.tracks()</code>)</li>
<li>Filter for the video track (checking <code>ges::TrackType::VIDEO</code>)</li>
<li>Read the track's <code>restriction_caps</code></li>
<li>Extract the <code>gst::Fraction</code></li>
</ul>
<h3 id="my-helper">My helper</h3>
<p>I wrote a helper function to extract the framerate from the timeline:</p>
<pre><code data-lang="rust">
pub fn get_fps(&amp;self, timeline: &amp;ges::Timeline) -&gt; Option&lt;(i128, i128)&gt; {
    timeline
        .tracks()
        .into_iter()
        .find(|track| track.track_type().contains(ges::TrackType::VIDEO))
        .and_then(|track| {
            let caps = track.restriction_caps().or_else(|| track.caps())?;
            let structure = caps.structure(0)?;
            let fps = structure.get::&lt;gst::Fraction&gt;(&quot;framerate&quot;).ok()?;

            // Extract the safe numerator and denominator
            Some((fps.numer() as i128, fps.denom() as i128))
        })
}

// ... inside the timeline injection logic:
if let Some((fps_num, fps_denom)) = self.get_fps(timeline) {
    self.fps_num.set(fps_num.max(1) as i32);
    self.fps_denom.set(fps_denom.max(1) as i32);
} else {
    // Default to 23.976 if we can&#39;t find a valid framerate caps
    self.fps_num.set(24_000);
    self.fps_denom.set(1_001);
}

</code></pre>
<p>I make some assumptions here, such as only one video track existing, and that the framerate is always present in the caps. This solution made the tick spacing and labels line up with the timeline’s actual frame boundaries at any framerate.</p>

        ]]></description>
    </item>
    
    
    
    <item>
        <title>Hello Planet GNOME! | GSoC 2026 Introduction</title>
        <link>https://mccalabrese.github.io/gnome-blog/posts/first-post/</link>
        <guid>https://mccalabrese.github.io/gnome-blog/posts/first-post/</guid>
        <pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate>
        <description><![CDATA[
            <p>Hello everyone, I'm Michael, and I am excited to be contributing to the GNOME foundation as a part of Google Summer of Code 2026.</p>
<h3 id="a-bit-about-me">A bit about me</h3>
<p>I am a Computer Engineering student and long time Linux user. GNOME has been my desktop environment for years and I was very excited to be working with the GNOME foundation.</p>
<p>I have a fairly significant amount of custom tooling that was all in Python and Bash, and about 16 months ago I began rewriting it in Rust, primarily to learn, however the performance and reliability improvements were quite noticeable. This led me to rewrite all of my scripts and tools in Rust. That experience put me in a great position to tackle the Rust rewrite of the Pitivi timeline ruler.</p>
<h3 id="the-summer-project">The Summer Project</h3>
<p>The plan of attack with this project is first to create a standalone GTK4 Timeline Ruler widget in Rust, then modify Pitivi to use the new ruler via <code>PyGObject</code>.</p>
<p>I am currently building a basic test binary, which can be found at <a rel="external" href="https://gitlab.gnome.org/Mccalabrese/pitivi-timeline-ruler">Project</a>. This will be used to test the functionality of the widget and to ensure that it is working correctly before integrating it into Pitivi.</p>
<p>I am very excited to be working on this project and I look forward to sharing my progress with the community. I hope to learn a lot and contribute something meaningful to the GNOME ecosystem.</p>

        ]]></description>
    </item>
    
    
</channel>
</rss>
