<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>jcalado.com</title><description>pushing code</description><link>https://jcalado.com</link><item><title>IASDCG</title><link>https://jcalado.com/posts/iasdcg</link><guid isPermaLink="true">https://jcalado.com/posts/iasdcg</guid><description>CasparCG client for Christian congregations</description><pubDate>Mon, 20 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;IASDCG&lt;/h1&gt;
&lt;p&gt;IASDCG was my first ever C# WPF app and it was used to control CasparCG servers, with features tailored for local Seventh-day Adventist Churches.&lt;/p&gt;
&lt;h2&gt;Preview&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./iasdcg.jpg&quot; alt=&quot;IASDCG Interface&quot; /&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>CGTimer</title><link>https://jcalado.com/posts/cgtimer</link><guid isPermaLink="true">https://jcalado.com/posts/cgtimer</guid><description>Get current timecode from a casparCG server.</description><pubDate>Sat, 02 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;CGTimer&lt;/h1&gt;
&lt;p&gt;CGTimer is an Electron app to display current video time from a CasparCG server instance.&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Displays active clip current time&lt;/li&gt;
&lt;li&gt;Displays remaining clip time&lt;/li&gt;
&lt;li&gt;Starts flashing red at less than 5 seconds to clip end&lt;/li&gt;
&lt;li&gt;Warns about video being looped, via a red &quot;L&quot; on the clip time panel&lt;/li&gt;
&lt;li&gt;When CasparCG is issued a STOP command to the ffmpeg producer, everything is reset&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Preview&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./standby.png&quot; alt=&quot;CGTimer Standby Screen&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;View the project on &lt;a href=&quot;https://github.com/jcalado/cgtimer&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>Hyperdeckctl</title><link>https://jcalado.com/posts/hyperdeckctl</link><guid isPermaLink="true">https://jcalado.com/posts/hyperdeckctl</guid><description>Control multiple hyperdeck recorders from a single UI.</description><pubDate>Sat, 02 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Hyperdeckctl&lt;/h1&gt;
&lt;p&gt;Hyperdeckctl allows you to trigger common functions of your Blackmagic Design Hyperdeck recorders from a single interface.&lt;/p&gt;
&lt;h2&gt;Preview&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot01.png&quot; alt=&quot;Hyperdeckctl Interface&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;View the project on &lt;a href=&quot;https://github.com/jcalado/hyperdeckctl&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>VDO.Ninja invite generator</title><link>https://jcalado.com/posts/vdon-invite</link><guid isPermaLink="true">https://jcalado.com/posts/vdon-invite</guid><description>Advanced custom invite generator</description><pubDate>Sat, 05 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;VDON-invite&lt;/h1&gt;
&lt;p&gt;Generates VDO.Ninja invites tailored to the user preferences by toggling switches on or off.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot.png&quot; alt=&quot;VDON-invite as of 2021-01-17&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Expanding panel UI&lt;/li&gt;
&lt;li&gt;Popover information&lt;/li&gt;
&lt;li&gt;Loads data from external JSON file, allowing for complete reorder of toggles&lt;/li&gt;
&lt;li&gt;Generates additional VDO.Ninja director page URL when appropriate&lt;/li&gt;
&lt;li&gt;Generates custom view links&lt;/li&gt;
&lt;li&gt;Click to copy URLs&lt;/li&gt;
&lt;li&gt;Optionally obfuscates links via invite.cam&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;View the project on &lt;a href=&quot;https://github.com/jcalado/vdon-invite&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>Semáforo de Vacinação COVID</title><link>https://jcalado.com/posts/semaforo-vacinacao</link><guid isPermaLink="true">https://jcalado.com/posts/semaforo-vacinacao</guid><description>How long do I have to wait in line for my covid jab?</description><pubDate>Sun, 11 Jul 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Semáforo de Vacinação COVID - Mobile App&lt;/h1&gt;
&lt;p&gt;This React Native app consumes the same data as &lt;a href=&quot;https://covid19.min-saude.pt/cvc&quot;&gt;covid19.min-saude.pt/cvc&lt;/a&gt; and presents it in a friendly manner.&lt;/p&gt;
&lt;p&gt;It is my first React Native app, so some things might not be 100% up to standard.&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Downloads real-time data from the API endpoint&lt;/li&gt;
&lt;li&gt;Searches by location or center name&lt;/li&gt;
&lt;li&gt;Shows a map with API-provided markers so you can have a sense of scale. There are a lot of centers!&lt;/li&gt;
&lt;li&gt;Displays how old the API-provided data is, so the user is not misled&lt;/li&gt;
&lt;li&gt;Provides undocumented stats such as &quot;Pessoas em recobro&quot;, &quot;Pessoas em espera&quot;&lt;/li&gt;
&lt;li&gt;Pull down to refresh data&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Screenshots&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot1.png&quot; alt=&quot;Main page&quot; /&gt;
&lt;img src=&quot;./screenshot2.png&quot; alt=&quot;Details page&quot; /&gt;
&lt;img src=&quot;./screenshot3.png&quot; alt=&quot;More details&quot; /&gt;
&lt;img src=&quot;./screenshot4.png&quot; alt=&quot;Map&quot; /&gt;
&lt;img src=&quot;./screenshot5.png&quot; alt=&quot;Searching centers&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;View the project on &lt;a href=&quot;https://github.com/jcalado/semaforodevacinacao&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>Environmental quality sensors - CML</title><link>https://jcalado.com/posts/sensores-qa-cml</link><guid isPermaLink="true">https://jcalado.com/posts/sensores-qa-cml</guid><description>Public CML sensor data datatable in react</description><pubDate>Sat, 17 Jul 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Environmental Quality Sensors - Câmara Municipal de Lisboa&lt;/h1&gt;
&lt;p&gt;A React application that displays environmental quality sensor data from Lisbon&apos;s public API in an interactive data table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href=&quot;https://jcalado.com/sensores-qa-cml&quot;&gt;jcalado.com/sensores-qa-cml&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Screenshot&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot.jpg&quot; alt=&quot;Application Screenshot&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Search by Sensor name&lt;/li&gt;
&lt;li&gt;Search by Category name&lt;/li&gt;
&lt;li&gt;Search by Station&lt;/li&gt;
&lt;li&gt;Some sensors have colored thresholds in place: low, medium, high, danger, extreme&lt;/li&gt;
&lt;li&gt;Every column is sortable&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Technical Notes&lt;/h2&gt;
&lt;p&gt;Requests are proxied through &lt;a href=&quot;http://allorigins.win/&quot;&gt;allorigins.win&lt;/a&gt;, since the &lt;a href=&quot;http://opendata-cml.qart.pt:8080/lastmeasurements&quot;&gt;original API URL&lt;/a&gt; has CORS issues.&lt;/p&gt;
&lt;h2&gt;Metadata Info&lt;/h2&gt;
&lt;p&gt;There&apos;s some information about the API published here: &lt;a href=&quot;http://dados.cm-lisboa.pt/dataset/e7f31452-7d21-4b26-9eb5-1db62737a12d/resource/d8837f32-1f7e-4a61-bb8a-a2333f822edb/download/metadadosdadosabertos.pdf&quot;&gt;Metadata&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>APOD</title><link>https://jcalado.com/posts/apod</link><guid isPermaLink="true">https://jcalado.com/posts/apod</guid><description>Flutter app for NASA&apos;s APOD</description><pubDate>Tue, 17 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import GooglePlayButton from &apos;~/components/GooglePlayButton.astro&apos;&lt;/p&gt;
&lt;h1&gt;APOD&lt;/h1&gt;
&lt;p&gt;APOD stands for &quot;Astronomy Picture Of the Day&quot;.&lt;/p&gt;
&lt;h1&gt;App download&lt;/h1&gt;
&lt;p&gt;&amp;lt;GooglePlayButton appId=&quot;com.jcalado.apod&quot; /&amp;gt;&lt;/p&gt;
&lt;h2&gt;Screenshot&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;image1.png&quot; alt=&quot;Detail page&quot; /&gt; &lt;img src=&quot;image2.png&quot; alt=&quot;Archive of previous APODs&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Today&apos;s &lt;a href=&quot;https://apod.nasa.gov/apod/&quot;&gt;APOD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Last 90 days worth of APODs&lt;/li&gt;
&lt;li&gt;Get a random APOD&lt;/li&gt;
&lt;li&gt;Share&lt;/li&gt;
&lt;li&gt;Support for videos and other web content&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><author>Joel Calado</author></item><item><title>HeidiSQL Password Decoder: A Secure Client-Side Recovery Tool</title><link>https://jcalado.com/posts/heidisql-password-decoder</link><guid isPermaLink="true">https://jcalado.com/posts/heidisql-password-decoder</guid><description>A browser-based tool that securely decodes passwords from HeidiSQL connection settings files without sending data to any server.</description><pubDate>Sun, 23 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;🔐 HeidiSQL Password Decoder&lt;/h1&gt;
&lt;p&gt;I&apos;m excited to share a new tool I&apos;ve built that solves a common problem for database administrators who use HeidiSQL. Have you ever found yourself in a situation where you need to recover a database password from your HeidiSQL connection settings? Maybe you&apos;re migrating to a new system or just need to share credentials with a colleague. That&apos;s exactly why I created the HeidiSQL Password Decoder.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot.png&quot; alt=&quot;HeidiSQL Password Decoder Screenshot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href=&quot;https://jcalado.com/heidisql_password_decoder/&quot;&gt;jcalado.com/heidisql_password_decoder&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;HeidiSQL is a fantastic database management tool, but it stores your passwords in an encoded format in its settings file. While this isn&apos;t true encryption (and isn&apos;t meant to be), it does prevent casual viewing of your passwords. When you need those passwords outside of HeidiSQL, you&apos;re typically out of luck.&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;This browser-based tool uses the same algorithm that HeidiSQL employs to encode/decode passwords but runs entirely in your browser. No data ever leaves your computer, making it a secure way to retrieve those passwords when you need them.&lt;/p&gt;
&lt;h2&gt;✨ Key Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;🔒 100% Client-side Processing&lt;/strong&gt;: All decoding happens in your browser - no data is ever sent to a server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🖥️ Clean Modern Interface&lt;/strong&gt;: Intuitive design with visual feedback&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📋 Easy Copy Functionality&lt;/strong&gt;: One-click copy for decoded passwords&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🔍 Smart Detection&lt;/strong&gt;: Automatically finds password entries in your settings file&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🌐 Works Offline&lt;/strong&gt;: No internet connection required after initial page load&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;📋 How to Use It&lt;/h2&gt;
&lt;p&gt;The tool is designed to be as simple as possible:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Export your HeidiSQL connection settings or copy from your sessions file&lt;/li&gt;
&lt;li&gt;Paste the contents into the text area&lt;/li&gt;
&lt;li&gt;Click &quot;Decode Passwords&quot;&lt;/li&gt;
&lt;li&gt;View all your server connections and their decoded passwords&lt;/li&gt;
&lt;li&gt;Copy any password with a single click&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;🔍 Behind the Scenes&lt;/h2&gt;
&lt;p&gt;HeidiSQL&apos;s password encoding is relatively straightforward. The encoded password format ends with a digit that indicates the shift value used in the encoding. Here&apos;s the JavaScript function that powers the decoding:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function heidiDecode(hex) {
    var str = &apos;&apos;;
    var shift = parseInt(hex.substr(-1));
    hex = hex.substr(0, hex.length - 1);
    for (var i = 0; i &amp;lt; hex.length; i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16) - shift);
    return str;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The algorithm works like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It takes the last character of the encoded string as a &quot;shift&quot; value&lt;/li&gt;
&lt;li&gt;It processes the rest of the string in pairs of characters, treating them as hexadecimal values&lt;/li&gt;
&lt;li&gt;It converts each hex pair to a character code, subtracts the shift value, and converts to the corresponding character&lt;/li&gt;
&lt;li&gt;The resulting string is the original password&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;🔒 Privacy Considerations&lt;/h2&gt;
&lt;p&gt;When dealing with passwords, security is paramount. This tool was built with privacy as the top priority:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No data is ever sent to any server&lt;/li&gt;
&lt;li&gt;All processing happens directly in your browser&lt;/li&gt;
&lt;li&gt;No cookies or local storage used&lt;/li&gt;
&lt;li&gt;No analytics or tracking&lt;/li&gt;
&lt;li&gt;No external requests after page load&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Why Build This?&lt;/h2&gt;
&lt;p&gt;As a developer who works with databases frequently, I&apos;ve encountered situations where I needed to recover a HeidiSQL password. Rather than writing a quick script each time, I decided to build a proper tool that others might find useful as well.&lt;/p&gt;
&lt;p&gt;The project also gave me a chance to practice creating a focused, security-conscious web application that respects user privacy while solving a specific problem.&lt;/p&gt;
&lt;h2&gt;What&apos;s Next?&lt;/h2&gt;
&lt;p&gt;While the tool is fully functional as is, I&apos;m considering adding support for additional database tools that use similar encoding methods. If you have suggestions or feature requests, feel free to reach out or contribute to the project.&lt;/p&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;View the project on &lt;a href=&quot;https://github.com/jcalado/heidisql_password_decoder&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>Repetidores - Portugal Amateur Radio Repeater Directory</title><link>https://jcalado.com/posts/repetidores</link><guid isPermaLink="true">https://jcalado.com/posts/repetidores</guid><description>Interactive web application for exploring amateur radio repeaters across Portugal</description><pubDate>Fri, 24 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Repetidores - Your Complete Amateur Radio Companion for Portugal&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Repetidores has moved! The application is now available at &lt;a href=&quot;https://radioamador.info&quot;&gt;radioamador.info&lt;/a&gt;. All features and functionality remain and there&apos;s so much more at the new domain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://repetidores.jcalado.com&quot;&gt;Repetidores&lt;/a&gt; is an all-in-one Progressive Web App for Portuguese amateur radio operators. Instead of juggling multiple websites and resources, Repetidores brings together everything you need in one place: repeater data, band plan information, and upcoming ham radio events.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Amateur radio operators in Portugal were dealing with fragmented information scattered across multiple sources. Finding repeater details meant one website, checking band plans required another, and discovering local events meant searching through various channels. Whether you&apos;re planning a trip, setting up your radio equipment, or looking for the next ham radio gathering, having to consult multiple resources is inefficient and frustrating.&lt;/p&gt;
&lt;h2&gt;The Solution: A One-Stop-Shop for Ham Radio in Portugal&lt;/h2&gt;
&lt;p&gt;Repetidores consolidates the essential resources Portuguese amateur radio operators need into a single, modern platform. With over 190 repeaters in the database, comprehensive band plan information, and an events calendar, you can access everything from one convenient location.&lt;/p&gt;
&lt;p&gt;The application combines powerful search and filtering with interactive visualization, giving operators both the detailed technical specifications they need and the geographic context to make informed decisions.&lt;/p&gt;
&lt;h2&gt;Three Essential Resources in One Place&lt;/h2&gt;
&lt;h3&gt;1. Comprehensive Repeater Database&lt;/h3&gt;
&lt;p&gt;Access detailed information on over 190 repeaters across Portugal, including mainland, Azores, and Madeira regions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search and filter repeaters&lt;/li&gt;
&lt;li&gt;Show them on a map&lt;/li&gt;
&lt;li&gt;Copy repeater data easily - single click&lt;/li&gt;
&lt;li&gt;Export to Chirp-compatible CSV.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Band Plan Information&lt;/h3&gt;
&lt;p&gt;No need to search elsewhere for frequency allocations and band plan details. Repetidores includes a dedicated bands section with comprehensive frequency information, making it easy to understand which frequencies you can use and for what purposes.&lt;/p&gt;
&lt;h3&gt;3. Amateur Radio Events Calendar&lt;/h3&gt;
&lt;p&gt;Stay connected with the Portuguese ham radio community through the built-in events section. Discover upcoming amateur radio activities, contests, field days, and gatherings all in one convenient location.&lt;/p&gt;
&lt;h2&gt;Important Notes&lt;/h2&gt;
&lt;p&gt;The platform emphasizes responsible amateur radio operation. Users must:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hold proper licensing before transmitting&lt;/li&gt;
&lt;li&gt;Identify themselves correctly on air&lt;/li&gt;
&lt;li&gt;Comply with repeater owner guidelines&lt;/li&gt;
&lt;li&gt;Follow frequency band plans and regulations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Open Source&lt;/h2&gt;
&lt;p&gt;Repetidores is open source software released under the GPL-3.0 license. You can view the source code, report issues, or contribute on &lt;a href=&quot;https://github.com/jcalado/repetidores&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Try It Out&lt;/h2&gt;
&lt;p&gt;Visit &lt;a href=&quot;https://repetidores.jcalado.com&quot;&gt;repetidores.jcalado.com&lt;/a&gt; to access your all-in-one amateur radio companion for Portugal. Install it as a PWA on your device for instant access to repeaters, band plans, and events wherever you are.&lt;/p&gt;
&lt;p&gt;Whether you&apos;re a seasoned operator planning your next portable operation, a new ham learning the ropes, or an active community member looking for the next gathering, Repetidores brings together all the essential information you need in one convenient, mobile-friendly platform. Stop juggling multiple websites and bookmarks—everything you need is right here.&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>RT4D Codeplug Editor - A Modern, Open-Source Tool for Your Radtel RT-4D Radio</title><link>https://jcalado.com/posts/rt4d-codeplug-editor</link><guid isPermaLink="true">https://jcalado.com/posts/rt4d-codeplug-editor</guid><description>Modern, open-source alternative to the official CPS for programming Radtel RT-4D dual-mode radios</description><pubDate>Tue, 28 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;RT4D Codeplug Editor: A Modern, Open-Source Tool for Your RT-4D/Retevis RT84 Radio&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jcalado/rt4d-cps&quot;&gt;Source code at https://github.com/jcalado/rt4d-cps&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What is RT4D Codeplug Editor?&lt;/h2&gt;
&lt;p&gt;If you own a Radtel RT-4D (analog/DMR) radio, you know that programming it with the official Chinese Programming Software (CPS) can be... challenging. That&apos;s where RT4D Codeplug Editor comes in - a modern, open-source alternative built from the ground up to make radio programming straightforward and reliable.&lt;/p&gt;
&lt;h2&gt;Why Use RT4D Editor?&lt;/h2&gt;
&lt;h3&gt;🎯 Built for Accuracy&lt;/h3&gt;
&lt;p&gt;Unlike guesswork-based editors, RT4D Editor was developed through careful reverse-engineering of the official CPS. Every setting, every byte offset, every dropdown value has been verified against the official software to ensure your radio configuration is exactly what you expect.&lt;/p&gt;
&lt;h3&gt;🖥️ Clean, Modern Interface&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Tabbed interface for organized access to Channels, Contacts, Zones, and Settings&lt;/li&gt;
&lt;li&gt;Real-time editing with immediate visual feedback&lt;/li&gt;
&lt;li&gt;Advanced settings dialog for power users who want full control&lt;/li&gt;
&lt;li&gt;Cross-platform support - works on Windows, Linux, and macOS&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;📡 Complete Feature Support&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Channel Management:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Supports all 1024 channels&lt;/li&gt;
&lt;li&gt;Both analog (FM/AM/SSB) and DMR digital modes&lt;/li&gt;
&lt;li&gt;Full CTCSS/DCS sub-tone support (all 210+ codes)&lt;/li&gt;
&lt;li&gt;Scrambler, encryption, and privacy features&lt;/li&gt;
&lt;li&gt;Talkaround, scan, and alarm settings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Contact &amp;amp; Zone Organization:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manage up to 1000 DMR contacts&lt;/li&gt;
&lt;li&gt;Group lists for organized contact groups&lt;/li&gt;
&lt;li&gt;Zone-based channel organization&lt;/li&gt;
&lt;li&gt;All Call, Group Call, and Private Call support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Radio Settings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Identity:&lt;/strong&gt; Radio name, DMR ID, startup messages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audio:&lt;/strong&gt; Separate controls for analog and DMR audio
&lt;ul&gt;
&lt;li&gt;TX Mic Gain (0-31) and RX Speaker Volume (0-63)&lt;/li&gt;
&lt;li&gt;DMR Call audio with independent gain controls (0-24)&lt;/li&gt;
&lt;li&gt;Beep settings for various events&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Display:&lt;/strong&gt; LCD contrast, brightness, display modes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Power management&lt;/strong&gt; and dual-watch settings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4 programmable clock/timers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frequency lock ranges&lt;/strong&gt; for band limiting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scan settings&lt;/strong&gt; (direction, dwell time, modes)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Function key programming&lt;/strong&gt; (40 different actions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DMR enhancements:&lt;/strong&gt; hang times, remote control, call display&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advanced:&lt;/strong&gt; NOAA weather channels, spectrum scan, detection range&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;How It Works&lt;/h2&gt;
&lt;p&gt;The editor reads and writes &lt;code&gt;.4rdmf&lt;/code&gt; files - the binary codeplug format used by the RT-4D radio. The file structure includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CFG Section&lt;/strong&gt; (4096 bytes): Radio settings, identity, audio, display&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Channels&lt;/strong&gt; (1024 × 48 bytes): All channel data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contacts&lt;/strong&gt; (1000 × 32 bytes): DMR contact directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Group Lists&lt;/strong&gt; (250 × 288 bytes): Contact groupings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zones&lt;/strong&gt; (250 × 512 bytes): Channel organization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encryption Keys&lt;/strong&gt; (256 × 40 bytes): Privacy keys&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every field has been mapped to its exact byte offset through careful analysis of the official CPS software, ensuring 100% compatibility with your radio.&lt;/p&gt;
&lt;h2&gt;Technical Details&lt;/h2&gt;
&lt;p&gt;For the technically curious:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Built With:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 3.x&lt;/li&gt;
&lt;li&gt;PySide6 (Qt6) for the GUI&lt;/li&gt;
&lt;li&gt;Binary parsing with struct module&lt;/li&gt;
&lt;li&gt;GBK text encoding for Chinese character support&lt;/li&gt;
&lt;li&gt;BCD encoding for DMR IDs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Key Architecture:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;models.py&lt;/code&gt; - Data structures for all codeplug entities&lt;/li&gt;
&lt;li&gt;&lt;code&gt;parser.py&lt;/code&gt; - Binary file reading and conversion to Python objects&lt;/li&gt;
&lt;li&gt;&lt;code&gt;serializer.py&lt;/code&gt; - Python objects back to binary format&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dropdowns.py&lt;/code&gt; - All valid values for radio settings&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gui/&lt;/code&gt; - Qt-based user interface&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;File Format Documentation:&lt;/strong&gt;
Complete documentation of the &lt;code&gt;.4rdmf&lt;/code&gt; binary format is included in &lt;code&gt;CODEPLUG_FORMAT.md&lt;/code&gt;, making it easy for other developers to build compatible tools.&lt;/p&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Read from Radio:&lt;/strong&gt; Use the official CPS to read your current config and save as &lt;code&gt;.4rdmf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open in RT4D Editor:&lt;/strong&gt; Load the file and make your changes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save:&lt;/strong&gt; Export back to &lt;code&gt;.4rdmf&lt;/code&gt; format&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write to Radio:&lt;/strong&gt; Use the official CPS to write the modified file back&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Settings Organization&lt;/h2&gt;
&lt;p&gt;The Advanced Settings dialog logically groups related settings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;📻 Analog Audio Settings&lt;/strong&gt; - Squelch, mic gain, speaker volume, beeps for FM/AM/SSB operation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🔊 DMR Audio Settings&lt;/strong&gt; - Separate controls optimized for digital voice with call-specific audio levels&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🖥️ Display Settings&lt;/strong&gt; - Screen brightness, contrast, display modes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📡 DMR Operation Settings&lt;/strong&gt; - Remote control, hang times, call display&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;⚙️ Advanced Features&lt;/strong&gt; - NOAA, spectrum scan, detection settings&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Open Source &amp;amp; Community Driven&lt;/h2&gt;
&lt;p&gt;RT4D Codeplug Editor is open-source software, developed through reverse-engineering the official CPS to provide accurate, reliable radio programming. The project welcomes contributions, bug reports, and feature requests.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Benefits of Open Source:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transparent code&lt;/strong&gt; - see exactly what&apos;s happening with your radio data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community improvements&lt;/strong&gt; - bugs get fixed quickly&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-platform&lt;/strong&gt; - not locked to Windows&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Future-proof&lt;/strong&gt; - won&apos;t become abandonware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What&apos;s Next?&lt;/h2&gt;
&lt;p&gt;Future enhancements on the roadmap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DTMF programming system UI (data structure complete)&lt;/li&gt;
&lt;li&gt;Import/export from CSV for bulk editing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Whether you&apos;re a ham radio operator, professional radio user, or just someone who wants reliable control over your RT-4D radio programming, RT4D Codeplug Editor offers a modern, accurate, and user-friendly alternative to the official CPS.&lt;/p&gt;
&lt;p&gt;Github repo at https://github.com/jcalado/rt4d-cps&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;RT4D Codeplug Editor is not affiliated with or endorsed by the radio manufacturer. It&apos;s an independent, community-driven project created through reverse-engineering for compatibility and educational purposes.&lt;/em&gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>RadShot: A Lightweight Screenshot Tool for Radtel RT-4D</title><link>https://jcalado.com/posts/radshot</link><guid isPermaLink="true">https://jcalado.com/posts/radshot</guid><description>Capture and save screenshots from your Radtel RT-4D radio display with this tiny Windows utility.</description><pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;RadShot: A Lightweight Screenshot Tool for Radtel RT-4D&lt;/h1&gt;
&lt;p&gt;If you own a Radtel RT-4D, you&apos;ve probably wanted to capture what&apos;s on that little 128x64 display at some point — maybe to document a configuration, share a
channel setup, or just show off your radio&apos;s screen online.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RadShot&lt;/strong&gt; is a small Windows utility that does exactly that. Connect your RT-4D via USB, click capture, and save the screenshot as a PNG.&lt;/p&gt;
&lt;h2&gt;What It Does&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Captures the RT-4D display&lt;/strong&gt; over serial connection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Live preview&lt;/strong&gt; of the captured screen&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gallery view&lt;/strong&gt; to browse multiple captures&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rename and organize&lt;/strong&gt; your screenshots&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Export to PNG&lt;/strong&gt; with one click&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Why I Built It&lt;/h2&gt;
&lt;p&gt;I wanted a simple, fast tool to grab screenshots from my RT-4D without the overhead of larger applications. The result is a single executable under 300KB
that just works.&lt;/p&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;p&gt;The interface is straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Select your COM port from the dropdown&lt;/li&gt;
&lt;li&gt;Click &quot;Capture&quot; to grab the current display&lt;/li&gt;
&lt;li&gt;Preview appears instantly&lt;/li&gt;
&lt;li&gt;Save to your preferred folder&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can capture multiple screenshots in a session and browse them in the gallery view before deciding which ones to keep.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot.jpg&quot; alt=&quot;RadShot Screenshot&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Download&lt;/h2&gt;
&lt;p&gt;RadShot is free and open source. Grab it from GitHub:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/jcalado/radshot&quot;&gt;github.com/jcalado/radshot&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Prebuilt Windows binaries are available in the Releases section.&lt;/p&gt;
&lt;h2&gt;Technical Notes&lt;/h2&gt;
&lt;p&gt;For the curious: RadShot is written in C++ using Dear ImGui for the interface. The entire application compiles to a single portable executable with no
external dependencies. It communicates with the RT-4D using the same serial protocol the radio uses for programming.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you&apos;re an RT-4D owner, give it a try and let me know what you think. Issues and contributions are welcome on GitHub.&lt;/p&gt;
&lt;hr /&gt;
</content:encoded><author>Joel Calado</author></item><item><title>Remmina RDP Protocol Missing After Installing freerdp on Arch Linux</title><link>https://jcalado.com/posts/remmina-rdp-arch</link><guid isPermaLink="true">https://jcalado.com/posts/remmina-rdp-arch</guid><description>After installing freerdp for RDP support in Remmina on Arch Linux, the RDP protocol won&apos;t appear until you reboot</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Installed Remmina on Arch Linux but RDP isn&apos;t in the protocol list? Install &lt;code&gt;freerdp&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo pacman -S freerdp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Then reboot.&lt;/strong&gt; Restarting Remmina alone won&apos;t do it — the RDP plugin only appears after a full system reboot.&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>VoxLink: A Push-to-Talk Client for SvxLink Reflectors</title><link>https://jcalado.com/posts/voxlink</link><guid isPermaLink="true">https://jcalado.com/posts/voxlink</guid><description>Connect to SvxLink reflectors from your Android phone with VoxLink — a free, open-source push-to-talk client with Opus audio, multiple PTT modes, and background operation.</description><pubDate>Sat, 11 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;VoxLink: A Push-to-Talk Client for SvxLink Reflectors&lt;/h1&gt;
&lt;p&gt;If you use SvxLink reflectors to connect repeaters and stations, you&apos;ve probably wished you could jump on from your phone — without lugging a radio or sitting at a desktop client. &lt;strong&gt;VoxLink&lt;/strong&gt; is an Android app that does exactly that.&lt;/p&gt;
&lt;p&gt;Connect to any SvxLink reflector, pick a talkgroup, and hit PTT. That&apos;s it. No accounts, no subscriptions, no setup wizards.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./app-screenshot.png&quot; alt=&quot;VoxLink PTT screen&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Why I Built It&lt;/h2&gt;
&lt;p&gt;SvxLink is a fantastic system for linking amateur radio repeaters over IP, but the options for mobile clients have always been limited. I wanted something that felt native on Android, worked reliably in the background, and didn&apos;t compromise on audio quality. So I built one.&lt;/p&gt;
&lt;h2&gt;What It Does&lt;/h2&gt;
&lt;p&gt;VoxLink speaks the SvxLink Reflector Protocol V2 natively — TCP for control and signaling, UDP for audio. It handles authentication, heartbeats, talkgroup selection, and node tracking, all while streaming Opus-encoded audio at 16 kHz.&lt;/p&gt;
&lt;h3&gt;Three PTT Modes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hold&lt;/strong&gt; — press and hold to transmit, classic radio style&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Latch&lt;/strong&gt; — tap to toggle TX on and off&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VOX&lt;/strong&gt; — voice-activated transmission with adjustable threshold and delay&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Multiple Server Profiles&lt;/h3&gt;
&lt;p&gt;Save and switch between different reflector servers. Each profile stores its own callsign, auth key, talkgroup, and connection details. You can also import and export server configurations as JSON to share setups with other operators.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./servers-screen.png&quot; alt=&quot;Server list&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Live Node List&lt;/h3&gt;
&lt;p&gt;See who&apos;s connected to the reflector in real time. The nodes screen shows all stations on your current talkgroup with their callsigns.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./nodes-screen.png&quot; alt=&quot;Connected nodes&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Audio That Stays On&lt;/h3&gt;
&lt;p&gt;VoxLink runs as a foreground service with wake lock and WiFi lock, so it stays connected even with the screen off. Audio routing supports speaker, earpiece, and Bluetooth. There&apos;s also a time-out timer (configurable from 30 seconds to 10 minutes) with a vibration warning before it cuts your transmission.&lt;/p&gt;
&lt;h3&gt;Recording&lt;/h3&gt;
&lt;p&gt;Optionally record TX and RX audio as WAV files, organized by talkgroup and timestamp. Play them back or share them directly from the app.&lt;/p&gt;
&lt;h2&gt;Under the Hood&lt;/h2&gt;
&lt;p&gt;VoxLink is built with Flutter and uses native platform channels for low-latency audio I/O on Android. The Opus codec runs via FFI bindings to the native C library, and a custom FIR polyphase resampler handles the 48 kHz to 16 kHz conversion using SvxLink-compatible filter coefficients. An adaptive jitter buffer with packet loss concealment keeps audio smooth even on spotty connections.&lt;/p&gt;
&lt;p&gt;State management uses Riverpod, and the UI follows Material 3 with dynamic color support.&lt;/p&gt;
&lt;h2&gt;Get It&lt;/h2&gt;
&lt;p&gt;VoxLink is free — no ads, no in-app purchases, no subscriptions.&lt;/p&gt;
&lt;p&gt;Available on the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.jcalado.voxlink&quot;&gt;Google Play Store&lt;/a&gt;. More details at &lt;a href=&quot;https://voxlink.jcalado.com/&quot;&gt;voxlink.jcalado.com&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you&apos;re a ham using SvxLink reflectors, give VoxLink a try. Feedback and bug reports are welcome.&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>Ulanzi Stream Controller D200 as a Bitfocus Companion surface</title><link>https://jcalado.com/posts/ulanzi-d200-companion</link><guid isPermaLink="true">https://jcalado.com/posts/ulanzi-d200-companion</guid><description>A Bitfocus Companion surface plugin for the Ulanzi D200, with notes on reverse-engineering the wire protocol and making it work on Linux.</description><pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Bitfocus Companion&apos;s new surface plugin system (shipped in 4.3.0) makes it
possible to add support for new control surfaces without touching Companion
itself. I used that to plug in the &lt;strong&gt;&lt;a href=&quot;https://www.ulanzi.com/products/stream-controller-d200&quot;&gt;Ulanzi Stream Controller
D200&lt;/a&gt;&lt;/strong&gt;, a 13-button,
5×3 grid Stream-Deck-alike that&apos;s cheaper than the Elgato but wasn&apos;t
supported out of the box.&lt;/p&gt;
&lt;p&gt;Project: &lt;a href=&quot;https://github.com/jcalado/companion-surface-d200&quot;&gt;github.com/jcalado/companion-surface-d200&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What it does&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;13 Companion-controlled buttons, each with a 196×196 icon&lt;/li&gt;
&lt;li&gt;Brightness, button events, press/release&lt;/li&gt;
&lt;li&gt;Small-window status display (clock / system stats), selectable per surface&lt;/li&gt;
&lt;li&gt;Drop-in installable as a developer module in Companion 4.3.0+&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The reverse-engineering rabbit hole&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/redphx/strmdck&quot;&gt;redphx/strmdck&lt;/a&gt; had the wire protocol in
Python: 1024-byte HID packets framed as
&lt;code&gt;0x7c 0x7c [cmd:u16] [length:u32] [data...]&lt;/code&gt;, with full button uploads
pushed as ZIP archives containing a JSON manifest plus per-button PNGs. That
gave me a head start, but a few things were out of date or wrong:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;strmdck targets VID/PID &lt;code&gt;2207:0019&lt;/code&gt;. On my Linux box, the D200 enumerated as
&lt;code&gt;18d1:d002&lt;/code&gt;, Google&apos;s ADB-style VID/PID. Standard USB control transfers to
it failed with &lt;code&gt;EPROTO&lt;/code&gt;, &lt;code&gt;adb devices&lt;/code&gt; hit the same wall.&lt;/li&gt;
&lt;li&gt;My first port used &lt;code&gt;node-hid&lt;/code&gt;, which couldn&apos;t see the device at all.
Switching to &lt;code&gt;node-usb&lt;/code&gt; and bulk transfers got further but still failed with
&lt;code&gt;LIBUSB_TRANSFER_ERROR&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A USBPcap capture of Ulanzi Studio on Windows cleared everything up: the D200
actually exposes &lt;strong&gt;two USB devices&lt;/strong&gt; simultaneously through an internal hub.
The &lt;code&gt;18d1:d002&lt;/code&gt; one is an abandoned/bootloader interface, dead on arrival
from the host&apos;s point of view. The real device is &lt;code&gt;2207:0019&lt;/code&gt;, a proper HID
composite with two interrupt endpoints at &lt;code&gt;wMaxPacketSize = 1024&lt;/code&gt; plus a
keyboard interface for the standalone hotkey buttons.&lt;/p&gt;
&lt;p&gt;Windows enumerates both cleanly. Linux, connected directly, gives up after
three tries:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;usb 3-1: can&apos;t read configurations, error -22
usb 3-1: can&apos;t read configurations, error -22
usb usb3-port1: attempt power cycle
usb 3-1: New USB device found, idVendor=18d1, idProduct=d002
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Only the useless one survives. The fix turned out to be stupidly simple:
&lt;strong&gt;a USB 2.0 hub between the D200 and the host&lt;/strong&gt;. With the extra hub layer,
both child devices enumerate, &lt;code&gt;usbhid&lt;/code&gt; binds to the HID interface, and
&lt;code&gt;node-hid&lt;/code&gt; just works.&lt;/p&gt;
&lt;p&gt;That one detail burned a couple hours.&lt;/p&gt;
&lt;h2&gt;The ZIP manifest was wrong in strmdck too&lt;/h2&gt;
&lt;p&gt;The captured ZIPs from Ulanzi Studio use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;manifest.json
Images/&amp;lt;uuid&amp;gt;.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(flat, no &lt;code&gt;page/&lt;/code&gt; prefix) and require a per-button &lt;code&gt;Font&lt;/code&gt; object inside
each &lt;code&gt;ViewParam[0]&lt;/code&gt;. Getting icons to render required matching that structure
exactly, including declaring the small-window slot &lt;code&gt;3_2&lt;/code&gt; (which spans two
cells) with &lt;code&gt;SmallViewMode: 1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Plus a lovely firmware bug: the byte at file offsets &lt;code&gt;1016 + 1024·N&lt;/code&gt; in the
ZIP payload must not be &lt;code&gt;0x00&lt;/code&gt; or &lt;code&gt;0x7c&lt;/code&gt;, or the upload is silently
corrupted. strmdck&apos;s workaround (retry compression with a random-length
dummy file appended) ports over directly.&lt;/p&gt;
&lt;h2&gt;Writeup&lt;/h2&gt;
&lt;p&gt;The full wire protocol and ZIP format are documented in
&lt;a href=&quot;https://github.com/jcalado/companion-surface-d200/blob/main/PROTOCOL.md&quot;&gt;PROTOCOL.md&lt;/a&gt;;
Linux-specific setup (hub requirement, udev rule, the diagnosis of the
enumeration failure) is in
&lt;a href=&quot;https://github.com/jcalado/companion-surface-d200/blob/main/SETUP.md&quot;&gt;SETUP.md&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Support&lt;/h2&gt;
&lt;p&gt;If this is useful to you: &lt;a href=&quot;https://ko-fi.com/jcalado&quot;&gt;ko-fi.com/jcalado&lt;/a&gt;.&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>CGTimer 3.0</title><link>https://jcalado.com/posts/cgtimer-3-0</link><guid isPermaLink="true">https://jcalado.com/posts/cgtimer-3-0</guid><description>A major rewrite of CGTimer with a flexible layout system, OSC control, HyperDeck recorder integration, and a new preferences window.</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;CGTimer 3.0 is out. It&apos;s a major release that rebuilds the app around a flexible layout system and adds first-class support for the production tools I keep reaching for: OSC control surfaces and Blackmagic HyperDeck recorders.&lt;/p&gt;
&lt;p&gt;Download: &lt;a href=&quot;https://github.com/jcalado/cgtimer/releases/tag/v3.0.0&quot;&gt;github.com/jcalado/cgtimer/releases/tag/v3.0.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./dashboard.png&quot; alt=&quot;CGTimer 3.0 dashboard&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;A layout system that gets out of the way&lt;/h2&gt;
&lt;p&gt;The biggest change is that the dashboard is no longer a fixed arrangement. You can split panels horizontally or vertically, drag widgets between slots, and pull new widgets in from a palette. Resize anything by dragging the dividers, and reconfigure widgets (label, colors, options) inline. Press &lt;strong&gt;F&lt;/strong&gt; at any time to go fullscreen.&lt;/p&gt;
&lt;p&gt;If you used the old version, the default layout still stacks a remaining timer over an elapsed timer, so first-run still feels familiar.&lt;/p&gt;
&lt;h2&gt;New widgets&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time-of-day countdown&lt;/strong&gt;, replacing the older production clock. Pick a wall-clock time and the widget counts down to it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timezone clocks&lt;/strong&gt; for any city or zone, with themed previews so you can see what they&apos;ll look like before adding them to a layout.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HyperDeck status&lt;/strong&gt;, showing live timecode and recording state from a connected Blackmagic HyperDeck.&lt;/li&gt;
&lt;li&gt;A unified renderer for the remaining, elapsed, and loop timers so they all share the same typography.&lt;/li&gt;
&lt;li&gt;The loop icon now spins while a loop is active, so it&apos;s easy to tell at a glance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All clocks are now driven from a single wall-clock-aligned tick, so widgets on the same screen no longer drift apart by a fraction of a second.&lt;/p&gt;
&lt;h2&gt;OSC and HyperDeck&lt;/h2&gt;
&lt;p&gt;CGTimer now ships an OSC server, so an external console can drive timer commands (start, stop, reset, and so on) and switch between layouts remotely. That last part is the one I wanted most: building a production layout once and switching to it from a button on a Companion or QLab surface.&lt;/p&gt;
&lt;p&gt;HyperDeck support is end-to-end: configure recorders from the new Recorders tab in preferences, monitor their status, and drop a HyperDeck widget into your layout to see the deck&apos;s timecode next to your timers.&lt;/p&gt;
&lt;h2&gt;Preferences, rewritten&lt;/h2&gt;
&lt;p&gt;The Forge-generated preferences window is gone. In its place is a custom Fluent UI window with five tabs: Application, Colors, Timezones, Recorders, and Server. Open it with &lt;strong&gt;Cmd/Ctrl + ,&lt;/strong&gt;. Toggles in the Production tab are now inline, the Colors tab has been reformatted, and the Timezones tab has a themed time preview so you can pick zones without guessing.&lt;/p&gt;
&lt;h2&gt;Multi-display&lt;/h2&gt;
&lt;p&gt;Display matching is now hardened against monitor IDs changing across reboots, so windows return to the right screen instead of jumping around. Fullscreen and window positioning behave correctly when you plug or unplug displays mid-session.&lt;/p&gt;
&lt;h2&gt;Builds&lt;/h2&gt;
&lt;p&gt;3.0 ships builds for everything I can produce on CI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;macOS arm64 (&lt;code&gt;.dmg&lt;/code&gt;, &lt;code&gt;.zip&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Windows (&lt;code&gt;Setup.exe&lt;/code&gt; installer and a new portable &lt;code&gt;.exe&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Linux (&lt;code&gt;.AppImage&lt;/code&gt;, &lt;code&gt;.deb&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Auto-update metadata is published alongside the artifacts on all three platforms.&lt;/p&gt;
&lt;h2&gt;Under the hood&lt;/h2&gt;
&lt;p&gt;If you fork the project, the toolchain is now Vite plus electron-builder, replacing the previous Webpack and Electron Forge setup. Builds are noticeably faster and the config surface is much smaller. Electron, React, and Fluent UI are all on their latest majors (41, 19, and v9 respectively).&lt;/p&gt;
&lt;p&gt;Issues, ideas, and PRs welcome at &lt;a href=&quot;https://github.com/jcalado/cgtimer&quot;&gt;github.com/jcalado/cgtimer&lt;/a&gt;.&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>VoxLink 1.2: Audio file playback, deep links, smarter audio routing</title><link>https://jcalado.com/posts/voxlink-1-2</link><guid isPermaLink="true">https://jcalado.com/posts/voxlink-1-2</guid><description>VoxLink 1.2 adds audio file playback over the air, voxlink:// deep links and QR codes, a live audio-output picker, faster talkgroup-preset workflows, and a stack of fixes.</description><pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;VoxLink 1.2: Audio file playback, deep links, smarter audio routing&lt;/h1&gt;
&lt;p&gt;VoxLink 1.2 is out. The headline feature is &lt;strong&gt;audio file playback&lt;/strong&gt; — you can now transmit a pre-recorded clip over the air directly from the PTT screen — and it brings a stack of smaller workflow improvements on top.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./playlist_progress.png&quot; alt=&quot;[phone] File-playback progress card&quot; title=&quot;The file-playback progress card on the PTT screen while a clip streams over the air.&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Audio file playback&lt;/h2&gt;
&lt;p&gt;A new file-playback button sits next to PTT. Tap it, pick an audio file, and VoxLink streams it over the air while a progress card tracks playback. Local monitoring plays the same audio out the speaker while you transmit, so you actually hear what&apos;s going out.&lt;/p&gt;
&lt;p&gt;A few sensible guard rails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disabled while VOX mode is active — file playback and voice-activated TX don&apos;t mix.&lt;/li&gt;
&lt;li&gt;Disabled while another station is talking — no stomping on a live conversation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&apos;s the feature I&apos;ve wanted for ages for tests, recorded ID announcements, and net openings.&lt;/p&gt;
&lt;h2&gt;Faster talkgroup workflows&lt;/h2&gt;
&lt;p&gt;Managing presets used to mean diving into the server edit form. Several changes make presets feel first-class:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Talkgroups entry in the active server&apos;s menu&lt;/strong&gt; — jump straight to preset management without re-opening the edit form.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional onboarding&lt;/strong&gt; right after you add a new server, so you can set presets up while it&apos;s fresh.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;‹ / › chevron buttons on the PTT screen&lt;/strong&gt; to step through presets without leaving the talk view (appears when the server has two or more).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor another TG…&lt;/strong&gt; in the picker — drop into any arbitrary talkgroup for monitoring without first turning it into a preset.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Per-preset &quot;Monitor by default&quot; flag&lt;/strong&gt; in the talkgroup presets screen — pin specific talkgroups to always be monitored when you connect.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;./talkgroup_presets.png&quot; alt=&quot;[phone] Talkgroup presets with Monitor-by-default&quot; title=&quot;The talkgroup presets screen, with the new Monitor-by-default toggle.&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;voxlink:// deep links and QR codes&lt;/h2&gt;
&lt;p&gt;You can now share server configurations as a single URL or QR code. The format:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;voxlink://host:port/?name=&amp;amp;user=&amp;amp;pass=&amp;amp;tg=
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open one (or scan a QR code that encodes one) and VoxLink launches with the new-server form prefilled — no manual copying of host, user, or talkgroup numbers. Useful for net coordinators, club groups, or just sharing your own setup across devices.&lt;/p&gt;
&lt;h2&gt;Live audio routing&lt;/h2&gt;
&lt;p&gt;Two changes that fix a long-standing pain point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The audio output picker in Settings is now live&lt;/strong&gt; — it lists the actual devices currently available (built-in speaker, wired headset, paired Bluetooth device, etc.) instead of a fixed enum that didn&apos;t always match reality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-rerouting&lt;/strong&gt; — when &lt;em&gt;Audio output&lt;/em&gt; is set to &lt;em&gt;Auto&lt;/em&gt;, plugging in or removing a headset or Bluetooth device switches the route on the fly. If your selected device disappears mid-session, a toast tells you what happened.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Settings rows for audio output and audio input also stack the device or source name below the label, so a long Bluetooth name no longer wraps awkwardly.&lt;/p&gt;
&lt;h2&gt;Smaller changes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The PTT screen header now shows the &lt;strong&gt;server name&lt;/strong&gt; (with host as fallback) instead of the raw hostname — friendlier when you&apos;re managing multiple reflectors.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Fixes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Snackbars on the &lt;strong&gt;Servers&lt;/strong&gt; and &lt;strong&gt;Recordings&lt;/strong&gt; screens now auto-dismiss when an Android accessibility service is active. Previously they could sit on screen indefinitely, and recordings deleted via the snackbar were never actually cleaned from disk.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;&quot;Connection timed out&quot;&lt;/strong&gt; warning no longer lingers on the PTT screen after a successful auto-reconnect.&lt;/li&gt;
&lt;li&gt;The reflector connection no longer &lt;strong&gt;reconnects in a loop&lt;/strong&gt; after a protocol-level error like &lt;em&gt;Access denied&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Get it&lt;/h2&gt;
&lt;p&gt;VoxLink 1.2 is rolling out on the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.jcalado.voxlink&quot;&gt;Google Play Store&lt;/a&gt;. More details at &lt;a href=&quot;https://voxlink.jcalado.com/&quot;&gt;voxlink.jcalado.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you hit a bug or have an idea, drop into the &lt;a href=&quot;https://t.me/+7eNqxZZsIrcwYzc0&quot;&gt;VoxLink Telegram community&lt;/a&gt;. 73.&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item><item><title>VoxLink 1.3: APRS, accessibility, and a settings overhaul</title><link>https://jcalado.com/posts/voxlink-1-3</link><guid isPermaLink="true">https://jcalado.com/posts/voxlink-1-3</guid><description>VoxLink 1.3 brings full APRS-IS support (map, stations, messaging, beaconing), a stack of accessibility features, a reorganized settings area, Bluetooth audio routing fixes, on-screen monitor activity alerts, and a long run of audio reliability work for Android 16.</description><pubDate>Tue, 12 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import KofiBanner from &apos;~/components/KofiBanner.astro&apos;&lt;/p&gt;
&lt;h1&gt;VoxLink 1.3: APRS, accessibility, and a settings overhaul&lt;/h1&gt;
&lt;p&gt;VoxLink 1.3 is out. The headline is &lt;strong&gt;APRS&lt;/strong&gt; — VoxLink now speaks APRS-IS, with a live map, station list, messaging, and configurable beaconing — but a lot has happened around it: a full set of accessibility features, a reorganized settings area, Bluetooth audio routing fixes, and on-screen alerts for monitored talkgroup activity.&lt;/p&gt;
&lt;h2&gt;APRS&lt;/h2&gt;
&lt;p&gt;VoxLink is now an APRS client. Connect to APRS-IS with your callsign and passcode and you get:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;live map&lt;/strong&gt; (OpenStreetMap) with stations as markers, callsigns labeled under each symbol, and common APRS symbols mapped to Material icons.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;stations list&lt;/strong&gt; with a search box, sort by distance / last-heard / callsign, last-heard age pills, an inline movement chip for moving stations, category filter chips with a stale-fade, pull-to-refresh, dense rows, and persisted sort. Tapping a station opens a detail sheet with path, status, course/speed/altitude, and other metadata.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Messaging&lt;/strong&gt; — send and receive APRS messages directly from the app.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beaconing&lt;/strong&gt; with two positioning modes: automatic from GPS (with tunable accuracy) or a manual map picker for fixed locations. Each mode has its own settings, and a smart-beacon fallback derives speed from distance/time when the GPS speed channel is unreliable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Background operation&lt;/strong&gt; — the APRS-IS connection (and position stream) is kept alive through the foreground service, so beacons keep going out and incoming traffic keeps flowing when the app isn&apos;t in front.&lt;/li&gt;
&lt;li&gt;Parsing for &lt;strong&gt;compressed positions, Mic-E, course/speed/altitude, objects, and items&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;VoxLink now identifies itself with the &lt;strong&gt;officially-assigned &lt;code&gt;APVOXL&lt;/code&gt; tocall&lt;/strong&gt; on the APRS-IS network.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The whole feature lives behind a master toggle in Settings, so if you don&apos;t want it, it&apos;s not in your way. UI is localized in English and Portuguese.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;VoxLink 1.3 ships a dedicated accessibility section with options that make the app usable in tougher conditions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Outdoors mode&lt;/strong&gt; — a larger PTT button with a glanceable outer ring you can hit without looking.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Huge talker display&lt;/strong&gt; — 56px callsign, 22px subtitle, for reading at a glance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Green screen flash&lt;/strong&gt; on RX talker start, so you know someone&apos;s transmitting without looking at the indicator.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduce motion&lt;/strong&gt; — disables the pulsing connection indicator and other ambient animation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Haptic strength&lt;/strong&gt; — Off / Subtle / Strong, scaling all vibration durations across the app.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TX start/stop vibration&lt;/strong&gt; cues — a short pulse on TX start, a double-tap on stop.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High-contrast&lt;/strong&gt; state colors on the PTT button and talker display.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Monitor activity alerts&lt;/h2&gt;
&lt;p&gt;Monitored talkgroups now surface activity directly in the app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;monitor activity banner&lt;/strong&gt; appears at the top of the PTT screen when a monitored TG goes active. Tap it to switch to that talkgroup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OS notifications&lt;/strong&gt; for talker activity on monitored TGs and for connection drops, with toggles to enable or disable each in the new Notifications section.&lt;/li&gt;
&lt;li&gt;A 5-second idle-coalesce window keeps the banner stable through bursts of short transmissions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Settings, reorganized&lt;/h2&gt;
&lt;p&gt;The Settings screen had grown into a long scroll. It&apos;s now split into focused sub-screens, all reachable from a clean grouped-card index:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transmission (PTT / VOX / TOT)&lt;/li&gt;
&lt;li&gt;Audio&lt;/li&gt;
&lt;li&gt;External PTT&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;li&gt;PTT screen controls&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;li&gt;Connection&lt;/li&gt;
&lt;li&gt;APRS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each row uses a right-chevron for navigation. Less hunting, more findability.&lt;/p&gt;
&lt;p&gt;Other small additions: a &lt;strong&gt;Keep screen on&lt;/strong&gt; toggle (wired to wakelock), an &lt;strong&gt;APRS server picker&lt;/strong&gt;, and a server &lt;strong&gt;export/import&lt;/strong&gt; flow that uses your share sheet (with a visible warning about the secrets it contains).&lt;/p&gt;
&lt;h2&gt;Audio&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bluetooth audio routing fix&lt;/strong&gt; — the comm-device session lifecycle is now handled properly, which resolves a long-standing class of routing issues with BT headsets. A live audio output picker enumerates devices in real time, auto-reroutes on connect/disconnect when set to &lt;em&gt;Auto&lt;/em&gt;, and surfaces a fallback toast when a chosen device disappears.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User-selectable BT audio mode&lt;/strong&gt; — pick whether the Bluetooth path uses the voice-call (SCO) profile or the media profile, depending on what your headset does well.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;48 kHz Opus&lt;/strong&gt; — the encoder and decoder now run at 48 kHz, improving audio quality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RX hardening for background and locked-screen wake-ups&lt;/strong&gt;, including keeping the RX path warm across QSOs and surviving fast keyup → keydown patterns without missing the start of the next over.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Android 16 WiFi PSM mitigation&lt;/strong&gt; — the app holds a multicast lock and runs a 1 Hz UDP heartbeat so the radio doesn&apos;t park itself in power-save mode while backgrounded.&lt;/li&gt;
&lt;li&gt;AudioTrack lifecycle work: recreated after long idle to avoid the stuck-slow-mixer bug, jitter-buffer tail drained on &lt;code&gt;talkerStop&lt;/code&gt; to stop clipped overs, zombie playback timers prevented from double-draining, decoder + jitter buffer reset on foreground resume, audio channel taken off the main thread, FAST-mixer hint dropped.&lt;/li&gt;
&lt;li&gt;Several stability fixes around mic leaks in VOX, decoder teardown, and AudioTrack underruns.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Playback improvements&lt;/h2&gt;
&lt;p&gt;The audio file playback feature from 1.2 grew up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Playlist-based playback&lt;/strong&gt; with a strip UI for the active entry.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pause / resume&lt;/strong&gt; that preserves the absolute file offset.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manual-PTT interrupt&lt;/strong&gt; — keying up cleanly stops the file.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Nodes &amp;amp; talkgroups&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Nodes&lt;/strong&gt; screen now splits the list by activity on the selected talkgroup, so you can tell who&apos;s actually using the channel right now.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scan&lt;/strong&gt; across talkgroups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Per-preset default&lt;/strong&gt; monitored TGs and arbitrary-TG monitoring.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chevron buttons&lt;/strong&gt; to step through presets on the PTT screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other fixes &amp;amp; polish&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Recordings: swipe-to-delete with a working Undo.&lt;/li&gt;
&lt;li&gt;Servers: first server is auto-activated on add and on load, so the PTT picker always has presets to show.&lt;/li&gt;
&lt;li&gt;Polished active-server hero card and servers dashboard.&lt;/li&gt;
&lt;li&gt;Manage talkgroups directly from the active server menu, and onboard them when adding a new server.&lt;/li&gt;
&lt;li&gt;RX is now torn down cleanly on talkgroup switch, and monitor/scan toggles are persisted across restarts.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;voxlink://&lt;/code&gt; deep links continue to work for provisioning servers via URL or QR.&lt;/li&gt;
&lt;li&gt;A grab bag of smaller stability and translation fixes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1.3.1&lt;/h2&gt;
&lt;p&gt;A short follow-up patch shipped on top of 1.3.0 with a few requested PTT-screen options and one more reliability fix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Optional TX / TOT timer row&lt;/strong&gt; on the PTT screen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional Quit item&lt;/strong&gt; in the PTT-screen connection menu, for when you want to fully stop the app instead of backgrounding it.&lt;/li&gt;
&lt;li&gt;Foreground service notification now &lt;strong&gt;reflects RX state&lt;/strong&gt; (and the &lt;code&gt;mediaPlayback&lt;/code&gt; FGS type was dropped now that audio routing is handled directly).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Get it&lt;/h2&gt;
&lt;p&gt;VoxLink 1.3 is rolling out on the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.jcalado.voxlink&quot;&gt;Google Play Store&lt;/a&gt;. More details at &lt;a href=&quot;https://voxlink.jcalado.com/&quot;&gt;voxlink.jcalado.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you hit a bug or have an idea, drop into the &lt;a href=&quot;https://t.me/+7eNqxZZsIrcwYzc0&quot;&gt;VoxLink Telegram community&lt;/a&gt;. 73.&lt;/p&gt;
&lt;p&gt;&amp;lt;KofiBanner showIcon message=&quot;VoxLink is free software. If it earned a spot on your radio bag, you can buy me a coffee.&quot; /&amp;gt;&lt;/p&gt;
</content:encoded><author>Joel Calado</author></item></channel></rss>