<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>diegoebe</title><link href="https://diegoe.be/" rel="alternate"></link><link href="https://diegoe.be/feed/index.xml" rel="self"></link><id>https://diegoe.be/</id><updated>2025-07-01T10:00:00-05:00</updated><entry><title>The New Troll Diet</title><link href="https://diegoe.be/2025/07/01/the-new-troll-diet/" rel="alternate"></link><published>2025-07-01T10:00:00-05:00</published><updated>2025-07-01T10:00:00-05:00</updated><author><name>diegoe</name></author><id>tag:diegoe.be,2025-07-01:/2025/07/01/the-new-troll-diet/</id><summary type="html">&lt;p&gt;I have been thinking a lot about online harassment in software communities lately.&lt;/p&gt;
&lt;p&gt;Harassment is nothing new in our spaces, and I even have a bunch of fun stories from trolls, past and new. However, all these stories have one thing in common: they are irrelevant to modern harassment and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have been thinking a lot about online harassment in software communities lately.&lt;/p&gt;
&lt;p&gt;Harassment is nothing new in our spaces, and I even have a bunch of fun stories from trolls, past and new. However, all these stories have one thing in common: they are irrelevant to modern harassment and trolling. So I would like to humbly propose a new framing of this whole issue.&lt;/p&gt;
&lt;h2&gt;Harassment In The Troll Feeding Days&lt;/h2&gt;
&lt;p&gt;Perhaps the most jarring change in online culture has been in how harassment happens on the internet. Spending our formative years in forums, IRC, and mailing lists, we got used to the occasional troll that after a few annoying interactions would get blocked by an admin.&lt;/p&gt;
&lt;p&gt;Back then, a troll was limited to &lt;em&gt;baiting&lt;/em&gt; for replies, and that power was easy to take away. Remember, removing a troll was as simple as blocking an email address or banning an IP on IRC.&lt;/p&gt;
&lt;p&gt;In short: &lt;em&gt;Don't feed the troll&lt;/em&gt; and it will either get bored and go away, or be blocked by an admin. Right?&lt;/p&gt;
&lt;h2&gt;Online Harassment Is a Different Game Now&lt;/h2&gt;
&lt;p&gt;The days of starving trolls are over. Trolls now have metaphorical DoorDash, UberEats, and are even decent cooks themselves.&lt;/p&gt;
&lt;p&gt;It is now impossible to defend an online community by simply "blocking the bad apples". A determined troll now has access to its own audience, peers to amplify their message, and even attack tools that used to be exclusive to nation states.&lt;/p&gt;
&lt;p&gt;A DDoS attack can be implemented with a few dozen dollars and cost thousands to defend. Social media accounts can be bought by the hundreds. Doxxing is easy for motivated individuals. Harassment campaigns can be orchestrated in real-time to flood comment sections, media outlets, employer inboxes, and even deplatform creators.&lt;/p&gt;
&lt;p&gt;Deterrence used to work because the trolls would lose access to attention and relevance if banned. This is no longer the case. In fact, trolls now have &lt;em&gt;a lot&lt;/em&gt; to gain by building an audience around being ostracized by their targets, portraying themselves as brave truth tellers that are censored by evil-doers.&lt;/p&gt;
&lt;p&gt;A strange game indeed, and not playing it doesn't work anymore.&lt;/p&gt;
&lt;h2&gt;Rules Are No Longer Enough&lt;/h2&gt;
&lt;p&gt;All of the above means that online communities can no longer point to the &lt;em&gt;"No Trolls Allowed"&lt;/em&gt; sign and consider the job done, this "rules-based" framework is no longer viable deterrence. A different approach is needed, one that is not naive to the ruses and concern trolling of contemporary harassment.&lt;/p&gt;
&lt;p&gt;A relevant example comes to mind. The popular &lt;a href="https://x.com/IamRageSparkle/status/1280891537451343873"&gt;"Nazi Bar" story as told by Michael Tager&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"(...) Tager recounted visiting a "shitty crustpunk bar" where he saw a patron abruptly expelled: the bartender explained that the man was wearing "iron crosses and stuff", and that he feared such patrons would become regulars and start bringing friends if not promptly kicked out, which would lead him to realize "oh shit, this is a Nazi bar now" only after the unwanted patrons became too "entrenched" to kick out without trouble."&lt;/p&gt;
&lt;p&gt;(...) "(Internet slang) A space in which bigots or extremists have come to dominate due to a lack of moderation or by moderators wishing to remain neutral or avoid conflict."
&lt;a href="https://en.wiktionary.org/wiki/Nazi_bar"&gt;From Wiktionary&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The story is not about the necessity of having a better rulebook. No, the point is that, in some circumstances, moderation can not afford to be naive and has to see through the ruse of bad actors appealing to tolerance or optics. Some times you have to loudly tell someone to &lt;em&gt;fuck off&lt;/em&gt;, and kick them out.&lt;/p&gt;
&lt;p&gt;This might seem counter intuitive if you grew up in the "don't feed the troll" era. But trolls no longer need the attention of their victims to thrive. In fact, some times silence and retreat from conflict are even bigger rewards.&lt;/p&gt;
&lt;h2&gt;The Trap Card of Behavioral Outbursts&lt;/h2&gt;
&lt;p&gt;Because the &lt;em&gt;rules-based&lt;/em&gt; framework considers &lt;em&gt;any&lt;/em&gt; engagement a failure, it leads groups to avoid conflict at all cost, not realizing that they are already in conflict with their harassers. Taken to an extreme, any push-back against harassment is seen &lt;em&gt;as bad&lt;/em&gt; as the harassment itself. This flawed reasoning might even lead to throwing others under the bus, or walking back statements of support, all done in the name of keeping the harassers &lt;em&gt;seemingly&lt;/em&gt; silent.&lt;/p&gt;
&lt;p&gt;Unfortunately, conceding to trolls after receiving push-back is one of Behavioral Psychology "trap cards". The concept is formally known as "Behavioral Outburst" and describes how a subject will intensify an unwanted behavior after receiving push-back. The classic example is a kid having a tantrum:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A kid is at the store with their parent. The kid starts crying, asking for a new toy. The parent says no and warns the kid that they will go back home if they keep crying.&lt;/p&gt;
&lt;p&gt;The kid keeps crying and the parent decides to fulfill the warning to go back home.&lt;/p&gt;
&lt;p&gt;As a response to this consequence, the kid then has &lt;em&gt;an outburst&lt;/em&gt; of the unwanted behavior: louder crying, screaming, throwing themselves to the floor.&lt;/p&gt;
&lt;p&gt;The parent gets overwhelmed and ends up buying a new toy for the kid.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The above example is commonly used to demonstrate two concepts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When an unwanted behavior is met with resistance, it frequently leads to an &lt;em&gt;outburst&lt;/em&gt; of that behavior to "defeat" such resistance&lt;/li&gt;
&lt;li&gt;If the &lt;em&gt;outburst&lt;/em&gt; succeeds, then the &lt;em&gt;outburst&lt;/em&gt; becomes the new baseline for responding to any resistance&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We should understand that applying consequences to a harasser (bans, warnings, condemnation) is likely to cause an outburst of the unwanted behavior. This is unavoidable. However, &lt;em&gt;it is a fatal mistake to cede to a behavioral outburst&lt;/em&gt;. If consequences are taken back, then the &lt;em&gt;outburst&lt;/em&gt; becomes the new default level of harassment.&lt;/p&gt;
&lt;p&gt;Even worse, an illusion of control is introduced: we harass, they fight back; we intensify the harassment a little bit, they concede.&lt;/p&gt;
&lt;h2&gt;Why Speaking Up Is Important&lt;/h2&gt;
&lt;p&gt;Communities are not corporations and morale is not set by a rule-book or by mandate of leadership. Communities, specially the ones &lt;a href="https://tesk.page/2025/06/18/its-true-we-dont-care-about-accessibility-on-linux/#my-work-is-free-but-the-worth-is-not"&gt;giving away tens of thousands of dollars in value to each other&lt;/a&gt;, are held together by mutual trust.&lt;/p&gt;
&lt;p&gt;One element of this mutual trust, maybe the most important one, is knowing that your colleagues have your back and will defend you from anyone unfairly coming after you. &lt;a href="https://www.youtube.com/watch?v=npRemap8AmA"&gt;Just like a soccer team will swarm a rival to defend a teammate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Knowing that your team will loudly tell those coming after you to &lt;em&gt;fuck off&lt;/em&gt; is not only good for morale, but also a necessary outlet and catharsis for a community. Silence only leads to festering of the most rancid vibes, it erodes trust and creates feelings of isolation in the targeted individuals.&lt;/p&gt;
&lt;p&gt;If solidarity and empathy are not demonstrated, is that any different from there being none?&lt;/p&gt;
&lt;h2&gt;A New Framework: Never Cede To The Troll&lt;/h2&gt;
&lt;p&gt;We need a new framework for how to defend against "trolls". The feeding metaphor ran its course many years ago. It is done and will not be coming back.&lt;/p&gt;
&lt;p&gt;New online risks demand that we adapt and become proactive in protecting our spaces. We have to loudly and proudly set the terms of what is permissible. Those holding social or institutional power in communities should be willing to drop a few loud &lt;em&gt;fuck offs&lt;/em&gt; to anyone trying to work their way in by weaponizing optics, concern trolling, or the well known &lt;a href="https://www.pictoline.com/timeline/2017/08/14/15hrs04min45sec"&gt;"tolerance paradox"&lt;/a&gt;. Conceding through silence, or self-censorship, only emboldens those who benefit from attacking a community.&lt;/p&gt;
&lt;p&gt;It is time that we adopt a bolder framework where defending our spaces and standing our ground to protect each other is the bare minimum expected.&lt;/p&gt;</content><category term="planetgnome"></category><category term="2025"></category><category term="gnome"></category><category term="vibes"></category></entry><entry><title>packpath: A command line utility to upload Signal stickers from a simple config file</title><link href="https://diegoe.be/2021/03/15/packpath-upload-signal-stickers-from-config-file/" rel="alternate"></link><published>2021-03-15T12:10:00-05:00</published><updated>2021-03-15T12:10:00-05:00</updated><author><name>diegoe</name></author><id>tag:diegoe.be,2021-03-15:/2021/03/15/packpath-upload-signal-stickers-from-config-file/</id><summary type="html">&lt;p&gt;I have been using Signal a lot and, besides the privacy features, I have
come to really enjoy custom sticker packs. Naturally, this led me to
upload and maintain &lt;em&gt;a lot&lt;/em&gt; of them. To keep things under control I
wrote &lt;code&gt;packpath&lt;/code&gt;, a small command line utility to easily upload and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I have been using Signal a lot and, besides the privacy features, I have
come to really enjoy custom sticker packs. Naturally, this led me to
upload and maintain &lt;em&gt;a lot&lt;/em&gt; of them. To keep things under control I
wrote &lt;code&gt;packpath&lt;/code&gt;, a small command line utility to easily upload and
update Signal sticker packs from a simple config file.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A collage of different stickers I have added to my Signal app using packpath" src="https://diegoe.be/uploads/2021/03/packpath-1600px.jpg" title="A collage of different stickers I have added to my Signal app using packpath"&gt;&lt;/p&gt;
&lt;p&gt;Although the Signal stickers API is only &lt;em&gt;kinda&lt;/em&gt; public, some developers
have written libraries to interact with it. Concretely,
&lt;a href="https://signalstickers.com"&gt;signalstickers.com&lt;/a&gt; maintainer Romain
Ricard, has written
&lt;a href="https://github.com/signalstickers/signalstickers-client"&gt;signalstickers-client&lt;/a&gt;,
a Python library to interact with the sticker API.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;code&gt;signalstickers-client&lt;/code&gt; doing all of the heavy lifting, I was
able to write &lt;code&gt;packpath&lt;/code&gt;, a simple command line utility to create and
publish sticker packs based on a simple YAML configuration file. It's
&lt;a href="https://pypi.org/project/packpath/"&gt;already available as packpath in
PyPI&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip3&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;packpath
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To use &lt;code&gt;packpath&lt;/code&gt;, you need to create a directory with your sticker
images and a &lt;code&gt;config.yaml&lt;/code&gt; file. The YAML format is available in
&lt;code&gt;packpath --help&lt;/code&gt;, but it's actually very simple:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Ketnipz&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Harry Hambley&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;cover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ketnipz_001.webp&lt;/span&gt;

&lt;span class="nt"&gt;stickers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ketnipz_001.webp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;💓️&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ketnipz_002.webp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;💃️&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ketnipz_003.webp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;💕️&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ketnipz_004.webp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;😐️&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ketnipz_005.webp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;🙃️&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You'll need your Signal "user and password", which are available on
the desktop app through the web developer tools
(&lt;code&gt;window.reduxStore.getState().items.uuid_id&lt;/code&gt; and
&lt;code&gt;window.reduxStore.getState().items.password&lt;/code&gt;). &lt;a href="https://github.com/signalstickers/signalstickers-client#uploading-a-pack"&gt;See details on
signalstickers-client
README&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can then call &lt;code&gt;packpath&lt;/code&gt; on the directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;packpath&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;UUID&lt;span class="w"&gt; &lt;/span&gt;--password&lt;span class="w"&gt; &lt;/span&gt;PASS&lt;span class="w"&gt; &lt;/span&gt;path/to/sticker/pack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You will get a progress report, and the "secret" URL to share your
sticker pack:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;packpath&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;UUID&lt;span class="w"&gt; &lt;/span&gt;--password&lt;span class="w"&gt; &lt;/span&gt;PASS&lt;span class="w"&gt; &lt;/span&gt;path/to/sticker/pack
&lt;span class="o"&gt;[&lt;/span&gt;packpath&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Configuring&lt;span class="w"&gt; &lt;/span&gt;sticker&lt;span class="w"&gt; &lt;/span&gt;pack&lt;span class="w"&gt; &lt;/span&gt;Ketnipz&lt;span class="w"&gt; &lt;/span&gt;by&lt;span class="w"&gt; &lt;/span&gt;Harry&lt;span class="w"&gt; &lt;/span&gt;Hambley
&lt;span class="o"&gt;[&lt;/span&gt;packpath&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Adding:&lt;span class="w"&gt; &lt;/span&gt;💓️&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ketnipz_001.webp
&lt;span class="o"&gt;[&lt;/span&gt;packpath&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Adding:&lt;span class="w"&gt; &lt;/span&gt;💃️&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ketnipz_002.webp
&lt;span class="o"&gt;[&lt;/span&gt;packpath&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Adding:&lt;span class="w"&gt; &lt;/span&gt;💕️&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ketnipz_003.webp
&lt;span class="o"&gt;[&lt;/span&gt;packpath&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Adding:&lt;span class="w"&gt; &lt;/span&gt;😐️&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ketnipz_004.webp
&lt;span class="o"&gt;[&lt;/span&gt;packpath&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Adding:&lt;span class="w"&gt; &lt;/span&gt;🙃️&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ketnipz_005.webp
Pack&lt;span class="w"&gt; &lt;/span&gt;uploaded!

Pack&lt;span class="w"&gt; &lt;/span&gt;uploaded.&lt;span class="w"&gt; &lt;/span&gt;You&lt;span class="w"&gt; &lt;/span&gt;can&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;it&lt;span class="w"&gt; &lt;/span&gt;by&lt;span class="w"&gt; &lt;/span&gt;visiting:
https://signal.art/addstickers/#pack_id&lt;span class="o"&gt;=&lt;/span&gt;NNNNN&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;pack_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MMMMM

You&lt;span class="w"&gt; &lt;/span&gt;can&lt;span class="w"&gt; &lt;/span&gt;also&lt;span class="w"&gt; &lt;/span&gt;preview&lt;span class="w"&gt; &lt;/span&gt;your&lt;span class="w"&gt; &lt;/span&gt;pack&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;signalstickers.com:
https://signalstickers.com/pack/NNNNN?key&lt;span class="o"&gt;=&lt;/span&gt;MMMMM

Note&lt;span class="w"&gt; &lt;/span&gt;that&lt;span class="w"&gt; &lt;/span&gt;visiting&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;above&lt;span class="w"&gt; &lt;/span&gt;URL&lt;span class="w"&gt; &lt;/span&gt;will&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;technically&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;make&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;pack&lt;span class="w"&gt; &lt;/span&gt;ID&lt;span class="w"&gt; &lt;/span&gt;and&lt;span class="w"&gt; &lt;/span&gt;key&lt;span class="w"&gt; &lt;/span&gt;visible&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;signalstickers.com&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;logs.
This&lt;span class="w"&gt; &lt;/span&gt;will&lt;span class="w"&gt; &lt;/span&gt;NOT&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;your&lt;span class="w"&gt; &lt;/span&gt;pack&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;signalstickers.com,&lt;span class="w"&gt; &lt;/span&gt;see&lt;span class="w"&gt; &lt;/span&gt;https://signalstickers.com/contribute&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;that.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code is licensed as AGPL-3.0-only, and you can check it out in &lt;a href="https://github.com/diegoe/packpath"&gt;the
packpath repo in GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many thanks to Romain for writing
&lt;a href="https://github.com/signalstickers/signalstickers-client"&gt;&lt;code&gt;signalstickers-client&lt;/code&gt;&lt;/a&gt;,
which actually made this tool possible.&lt;/p&gt;</content><category term="planetgnome"></category><category term="2021"></category><category term="python"></category><category term="signal"></category><category term="english"></category><category term="free software"></category></entry><entry><title>A minimal jhbuild GNOME session in Debian</title><link href="https://diegoe.be/2020/08/01/a-minimal-jhbuild-gnome-session-in-debian/" rel="alternate"></link><published>2020-08-01T17:33:00-05:00</published><updated>2020-08-01T17:33:00-05:00</updated><author><name>diegoe</name></author><id>tag:diegoe.be,2020-08-01:/2020/08/01/a-minimal-jhbuild-gnome-session-in-debian/</id><summary type="html">&lt;p&gt;I recently setup a GNOME development environment (after about seven
years!). That meant starting from scratch since my old notes and scripts
were completely useless.&lt;/p&gt;
&lt;p&gt;My goal for this setup was once again to have the bare minimum jhbuild
modules on top of a solid base system provided by my …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently setup a GNOME development environment (after about seven
years!). That meant starting from scratch since my old notes and scripts
were completely useless.&lt;/p&gt;
&lt;p&gt;My goal for this setup was once again to have the bare minimum jhbuild
modules on top of a solid base system provided by my distro. The Linux
desktop stack has changed a bit, specially around activation, dbus, and
systemd, so I was a bit lost on how to do things properly.&lt;/p&gt;
&lt;p&gt;Luckily around the time I was trying to figure this out, I ran into
&lt;a href="https://blogs.gnome.org/fmuellner/2020/03/02/shell-hacking-on-silverblue/"&gt;Florian Müllner's excellent post on how to work on shell hacking on a
Silverblue
system&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After removing the container-related bits, I was able to get a reliable
jhbuild session integrated into my system.&lt;/p&gt;
&lt;p&gt;Here is how to run a development GNOME session, fully integrated into
your system.&lt;/p&gt;
&lt;h2&gt;Register a new session&lt;/h2&gt;
&lt;p&gt;First, you need to tell GDM about your new session. I was able to do
that by creating &lt;code&gt;/usr/share/wayland-sessions/jhbuild.desktop&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[Desktop Entry]&lt;/span&gt;
&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jhbuild GNOME&lt;/span&gt;
&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;This session logs you into a development GNOME&lt;/span&gt;
&lt;span class="na"&gt;Exec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/gnome-session-jhbuild&lt;/span&gt;
&lt;span class="na"&gt;TryExec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/gnome-session-jhbuild&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Application&lt;/span&gt;
&lt;span class="na"&gt;DesktopNames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;GNOME&lt;/span&gt;
&lt;span class="na"&gt;X-GDM-SessionRegisters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Other distros might have slightly different paths. Check the installed
files of your GDM package.&lt;/p&gt;
&lt;h2&gt;Create a wrapper gnome-session-jhbuild&lt;/h2&gt;
&lt;p&gt;The above &lt;code&gt;jhbuild.desktop&lt;/code&gt; won't do anything unless you create an
executable that starts the session. Most of the script is actually
moving some systemd/dbus plumbing around so the right jhbuild services
get started.&lt;/p&gt;
&lt;p&gt;Put this in &lt;code&gt;/usr/local/bin/gnome-session-jhbuild&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# All credit to fmuellner!&lt;/span&gt;
&lt;span class="c1"&gt;# https://gitlab.gnome.org/fmuellner/silverblue-stuff/-/blob/master/sb-session-setup.sh&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-x

jhbuild&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;/home/diegoe/.local/bin/jhbuild&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;jhbuild&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;env&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;JHBUILD_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s:\r::&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;USER_UNIT_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$XDG_RUNTIME_DIR&lt;/span&gt;/systemd/user.control

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER_UNIT_DIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# Pick up systemd units defined in jhbuild&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;ln&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$JHBUILD_PREFIX&lt;/span&gt;/lib/systemd/user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER_UNIT_DIR&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;daemon-reload
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nv"&gt;DBUS_SERVICE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$XDG_RUNTIME_DIR&lt;/span&gt;/dbus-1
rm&lt;span class="w"&gt; &lt;/span&gt;-rf&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DBUS_SERVICE_DIR&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DBUS_SERVICE_DIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;ln&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$JHBUILD_PREFIX&lt;/span&gt;/share/dbus-1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DBUS_SERVICE_DIR&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c1"&gt;# $PATH and a few other things are likely overriden by your distro on your&lt;/span&gt;
&lt;span class="c1"&gt;# ~/.profile file (see /etc/skel/.profile) -- this might cause .desktop files&lt;/span&gt;
&lt;span class="c1"&gt;# to be seen as &amp;quot;broken&amp;quot; (because TryExec/Exec can&amp;#39;t confirm there&amp;#39;s a valid&lt;/span&gt;
&lt;span class="c1"&gt;# binary to use)&lt;/span&gt;
jhbuild&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;gnome-session

rm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DBUS_SERVICE_DIR&lt;/span&gt;
rm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER_UNIT_DIR&lt;/span&gt;
systemctl&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don't forget to mark the &lt;code&gt;gnome-session-jhbuild&lt;/code&gt; script as executable!&lt;/p&gt;
&lt;h2&gt;A minimal jhbuild module list&lt;/h2&gt;
&lt;p&gt;I can currently get a stable session running with the following modules
built:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;jhbuild&lt;span class="w"&gt; &lt;/span&gt;buildone&lt;span class="w"&gt; &lt;/span&gt;adwaita-icon-theme&lt;span class="w"&gt; &lt;/span&gt;glib&lt;span class="w"&gt; &lt;/span&gt;dconf&lt;span class="w"&gt; &lt;/span&gt;glib-networking&lt;span class="w"&gt; &lt;/span&gt;gvfs&lt;span class="w"&gt; &lt;/span&gt;gtk+&lt;span class="w"&gt; &lt;/span&gt;gtksourceview&lt;span class="w"&gt; &lt;/span&gt;glade&lt;span class="w"&gt; &lt;/span&gt;gnome-session&lt;span class="w"&gt; &lt;/span&gt;gnome-desktop&lt;span class="w"&gt; &lt;/span&gt;gnome-session&lt;span class="w"&gt; &lt;/span&gt;gnome-settings-daemon&lt;span class="w"&gt; &lt;/span&gt;gnome-control-center&lt;span class="w"&gt; &lt;/span&gt;gjs&lt;span class="w"&gt; &lt;/span&gt;mutter&lt;span class="w"&gt; &lt;/span&gt;gnome-shell
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You might need to &lt;code&gt;buildone&lt;/code&gt; a few others to satisfy dependencies, but
most of the time it's better to try and fill the missing pieces with
the distro &lt;code&gt;-dev&lt;/code&gt; packages.&lt;/p&gt;
&lt;p&gt;If for some reason your new session doesn't start and you get stuck
unable to log into any session, this is likely because of stuck services
or processes. A reboot will clean things up, but make sure you change
back to your system's default session, or you'll keep trying to log
into the broken one!&lt;/p&gt;
&lt;h2&gt;A word on $PATH and installed apps&lt;/h2&gt;
&lt;p&gt;I ran into a hair pulling issue where I couldn't get any of my jhbuild
installed apps to appear in the overview unless I had the equivalent app
installed on the base system. &lt;code&gt;$PATH&lt;/code&gt; was being lost as soon as a
&lt;code&gt;gnome-session&lt;/code&gt; binary started.&lt;/p&gt;
&lt;p&gt;Well, turns out the answer is rather obvious. &lt;code&gt;gnome-session&lt;/code&gt; starts a
&lt;em&gt;login shell&lt;/em&gt; which means that your system takes charge and sets a few
things for you, this means that the &lt;code&gt;$PATH&lt;/code&gt; visible in calls to
&lt;code&gt;jhbuild run&lt;/code&gt; or &lt;code&gt;jhbuild shell&lt;/code&gt; is dropped, among other things.&lt;/p&gt;
&lt;p&gt;The solution in my system was to add the following to my &lt;code&gt;~/.profile&lt;/code&gt;
file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# add jhbuild PATH&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$UNDER_JHBUILD&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$JHBUILD_PREFIX&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;$UNDER_JHBUILD&lt;/code&gt; var is set whenever you are running inside
&lt;code&gt;jhbuild&lt;/code&gt; so you can use it to do other fun things in your shell, like
adding an emoji to your prompt:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of a terminal running a jhbuild session" src="https://diegoe.be/uploads/2020/08/terminal-prompt-jhbuild-big.png" title="Screenshot of a terminal running a jhbuild session"&gt;&lt;/p&gt;
&lt;p&gt;To get something like the above prompt you can add this to your
&lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$UNDER_JHBUILD&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;🍄 &lt;/span&gt;&lt;span class="nv"&gt;$PS1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="planetgnome"></category><category term="2020"></category><category term="gnome"></category><category term="jhbuild"></category><category term="linux"></category><category term="english"></category><category term="free software"></category></entry><entry><title>Some (late) video and audio advice for GUADEC online</title><link href="https://diegoe.be/2020/07/21/some-video-and-audio-advice-for-guadec-online/" rel="alternate"></link><published>2020-07-21T23:31:00-05:00</published><updated>2020-07-21T23:31:00-05:00</updated><author><name>diegoe</name></author><id>tag:diegoe.be,2020-07-21:/2020/07/21/some-video-and-audio-advice-for-guadec-online/</id><summary type="html">&lt;p&gt;&lt;a href="https://2020.guadec.org"&gt;GUADEC 2020&lt;/a&gt; has moved online because of the
pandemic, and that means that many of us will be streaming our voice and
faces.&lt;/p&gt;
&lt;p&gt;Seeing as I have a fancy B.A. on Communication Studies &amp;amp; Film, I thought
I might share some guerilla film making tips for our new online reality …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://2020.guadec.org"&gt;GUADEC 2020&lt;/a&gt; has moved online because of the
pandemic, and that means that many of us will be streaming our voice and
faces.&lt;/p&gt;
&lt;p&gt;Seeing as I have a fancy B.A. on Communication Studies &amp;amp; Film, I thought
I might share some guerilla film making tips for our new online reality.&lt;/p&gt;
&lt;p&gt;Here are some tips on how to sound and look good online.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Bright pink sunset from the window seat of a plane in Lima" src="https://diegoe.be/uploads/2020/07/20181128-DSCF6485-4.jpg" title="Bright pink sunset from the window seat of a plane in Lima"&gt;&lt;/p&gt;
&lt;h2&gt;The executive summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;From most important to least: Clear voice, good framing, good big
    soft lights&lt;/li&gt;
&lt;li&gt;Sit facing a big window, or on a light colored room with good
    lighting that hits your face as much as possible&lt;/li&gt;
&lt;li&gt;Frame yourself in the center, and try to raise your camera to your
    eye level with books or boxes&lt;/li&gt;
&lt;li&gt;Use your earbuds' microphone, but keep the cable away from your
    body by resting it on the desk, or using some masking tape to secure
    it to your clothes to avoid rubbing noises&lt;/li&gt;
&lt;li&gt;Tune your microphone volume to the &lt;em&gt;lowest possible sensitivity&lt;/em&gt;
    that gives your clear voice, low "noise" (hums and static). Record
    yourself, test playback at 20-25% of your maximum playback volume on
    earbuds.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The best lighting&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The ideal situation is to sit facing a big window.&lt;/strong&gt; With light coming
into the room, on a cloudy day. You can put the window slightly in front
and to your left/right if you can't sit directly in front.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you have no usable window, you can use lamps.&lt;/strong&gt; If you have tall
lamps that you can point to a white wall, or white ceiling, that's
perfect. That will give you a big soft source of light.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You have lamps but no white wall or white ceiling.&lt;/strong&gt; Try to "make" a
wall with white reflective cardboard, a lot of white printer paper,
polystyrene (like a pro), or aluminum wrapping if you are desperate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You only have your ceiling lights.&lt;/strong&gt; Sit below &lt;em&gt;and behind&lt;/em&gt; your
ceiling light. You should be able to lightly tilt your head up and see
your bulb or fluorescent. White rooms with many ceiling lights help
bounce light to your face.&lt;/p&gt;
&lt;p&gt;Remember you can borrow bulbs from other rooms or lamps if you find
yourself with a light that is in the perfect spot, but too weak, or too
blue ("cool light") or too orange ("warm").&lt;/p&gt;
&lt;h2&gt;The best framing&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Put yourself in the center of the frame.&lt;/strong&gt; Sit front and center of
your camera, and try not to slouch to the sides, or worse, point the
camera to your ceiling or desk.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Line your camera lens with your eyes.&lt;/strong&gt; You can use books or boxes to
raise your camera. You probably know this pitfall as "nostrils cam"
and "receding hair line cam".&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cleanup your background, and some padding around it.&lt;/strong&gt; Make sure that
whatever ends up in frame is flattering, or at least not distracting,
plus some "padding" around, in case you accidentally rotate your
camera.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don't put bright lights on your background.&lt;/strong&gt; Bright light sources
like a TV, monitor, or window will confuse your camera and might make
you look washed out.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Put some distance between you and the background.&lt;/strong&gt; Otherwise it will
look like you are in a cell, a dungeon, or an unmarked CIA location.&lt;/p&gt;
&lt;h2&gt;The best audio&lt;/h2&gt;
&lt;p&gt;Microphones are "simple" but full of small technical details that are
out of scope for this guide. The good news is that you likely already
have a good enough mic that can be made to sound &lt;em&gt;slightly better&lt;/em&gt; or in
some cases much better.&lt;/p&gt;
&lt;p&gt;For a more in depth look into how to properly record your voice,
covering mics and voice use itself, see &lt;a href="https://www.youtube.com/playlist?list=PLGUJF8aG_m7soM0uaA_ucKHlgh890Uyou"&gt;this "How to be an online
voice actor" playlist by
SBN3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I only have my laptop mic, or my phone's cheap earbuds+mic.&lt;/strong&gt; This is
&lt;em&gt;fine.&lt;/em&gt; You can still get good audio from this. See below.&lt;/p&gt;
&lt;h3&gt;How to set up your cheap laptop/earbuds (or any) mic&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Set yourself up following the previous lighting and framing advice.
    Get comfortable&lt;/li&gt;
&lt;li&gt;Pick the mic that makes you the most comfortable&lt;/li&gt;
&lt;li&gt;Open your (system) sound settings, and a sound recording app&lt;/li&gt;
&lt;li&gt;Set your system sound settings microphone volume to 50%. Record
    yourself as if you were talking across the table, plus some seconds
    of silence&lt;/li&gt;
&lt;li&gt;Play back your recording at around 20-25% playback volume. Can you
    hear yourself clearly without having to raise the playback volume
    much more?&lt;/li&gt;
&lt;li&gt;If you can't hear yourself, raise your sound settings microphone
    volume some more. Rinse and repeat until you hear yourself properly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;You want the lowest possible microphone volume (sensitivity) where you
have clear voice, without background "hums", "static" or
"refrigerator noise", and without having to raise playback volume
above 40% or so on speakers, or 30% on headphones.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now repeat the test with your next best option. Keep going until you are
satisfied. Remember that price or looks can be deceiving. Your earbuds
might as well be your best microphone.&lt;/p&gt;
&lt;h3&gt;Earbuds troubleshooting&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;My wired earbuds sound better, but they make "bottle noises" when
rubbing with my clothes.&lt;/strong&gt; Keep the cable as far from your clothes as
possible. Any part of the cable can transmit these "bottle noises".
Let the excess cable rest on your desk, not your clothes or laptop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I still can't avoid the noises.&lt;/strong&gt; Get a clothespin, or some good
quality masking or gaffers tape, and secure the mic to your desk, or
your shirt. You can do fine with two or three "fix points" on your
clothes. Don't overdo it or you'll end up increasing rubs.&lt;/p&gt;
&lt;p&gt;Also avoid "loose" clothes, or noisy accessories like necklaces or
long complex earrings. And needless to say, &lt;em&gt;don't play with the cable
during the meeting or call&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;(Also don't chew your mic or cable while talking. Yes, people do this)&lt;/p&gt;
&lt;h3&gt;I have a fancy mic&lt;/h3&gt;
&lt;p&gt;If you have a USB mic, like a "podcaster" mic, make sure you compare
them against your earbuds or laptop mic. Specially your earbuds. While
there are many good external mics, usually earbuds trump them because
they are almost automatically set up at the perfect position and
distance to make a good recording of your voice.&lt;/p&gt;
&lt;p&gt;That's not to dismiss your fancy mic, but make sure you test it after
doing some tuning as suggested above.&lt;/p&gt;
&lt;h3&gt;A note on polar patterns&lt;/h3&gt;
&lt;p&gt;The ideal position of your fancy mic will depend on its particular polar
pattern (the shape of the "net" it throws to catch your voice). Most
"desk" mics sold for calls or podcasting are &lt;em&gt;usually&lt;/em&gt; designed to
work the best on close range.&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://www.shure.eu/musicians/discover/educational/polar-patterns"&gt;a good visual explanation and examples of polar patterns for
Shure&lt;/a&gt;
microphones, but these are standard across brands.&lt;/p&gt;
&lt;p&gt;Assuming you have a desk/podcast marketed external mic, that actually
sounds better than your other options, here's some advice to make the
most out of it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Put your fancy mic "one fist away" from your mouth.&lt;/strong&gt; Most of these
mics are designed for voice, so you want them as close a possible, with
the lowest possible sensitivity in your sound settings.&lt;/p&gt;
&lt;p&gt;Use books or boxes if you need to raise the mic to be at a comfortable
level that also gives you good audio. Your mic should ideally be "one
fist away" from your mouth, and slightly off center (slight diagonal
from your mouth) to avoid most breathing and wording "pops".&lt;/p&gt;
&lt;p&gt;Remember this &lt;em&gt;slightly&lt;/em&gt; depends on the polar pattern of your mic. For
example, Blue Yeti mics "look" like you should "point them" to your
mouth, like a karaoke mic, but actually they have to be "standing"
(fully vertical) in front of your mouth (like an "old timey radio"
mic).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disable automatic gain in your fancy mic.&lt;/strong&gt; Automatic volume/gain is a
blunt tool and you don't need it if you properly adjust your base
volume as explained above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make sure your mic has fresh batteries, if it uses batteries.&lt;/strong&gt; Some
mics run on batteries and you'll have weird bugs or noises if you have
low enough batteries.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Check that your microphone does not "ground" with other devices.&lt;/strong&gt;
Depending on your setup, some times electricity can "loop" through
your microphone causing the classic "ground" noise (that permanent
electrical buzz). Try unplugging other devices, using a different USB
port, or even unplugging your AC adapter. Also check that your
sensitivity is not excessive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If your mic has a "hardware" boost, it's worth trying it out.&lt;/strong&gt; If
you have raised the sound settings levels and you are getting noise or
poor voice quality, turn on the mic "boost", lower the sound settings
mic volume and try again. Some mics have very good "boosters" that
produce much better recordings. But this is very hit and miss. Try it
without, and then with. Compare the best two settings.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;There's an almost infinite list of tech nitpicks and pet peeves for the
above, but this should put you in the right direction at least.&lt;/p&gt;
&lt;p&gt;Let me know if I omitted a good hack, or a better explanation for any of
the above. I'll be in &lt;a href="https://chat.gnome.org/channel/GUADEC"&gt;#guadec on
chat.gnome.org&lt;/a&gt; if you need help
or have comments.&lt;/p&gt;
&lt;p&gt;See you at GUADEC (online)!&lt;/p&gt;</content><category term="planetgnome"></category><category term="2020"></category><category term="gnome"></category><category term="media"></category><category term="english"></category><category term="free software"></category></entry><entry><title>Fix HDMI audio lag on Retina MacBookPro 2013 (macbook11,1) in Linux</title><link href="https://diegoe.be/2020/06/14/fix-hdmi-audio-lag-on-retina-macbookpro-2013-macbook111-in-linux/" rel="alternate"></link><published>2020-06-14T18:37:00-05:00</published><updated>2020-06-14T18:37:00-05:00</updated><author><name>diegoe</name></author><id>tag:diegoe.be,2020-06-14:/2020/06/14/fix-hdmi-audio-lag-on-retina-macbookpro-2013-macbook111-in-linux/</id><summary type="html">&lt;p&gt;&lt;em&gt;The problem&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The HDMI out works just fine out of the box, except that you'll notice
that unless you boot with the HDMI cable connected, you'll experience
some weird audio lag through HDMI. Even worse, after a few seconds, HDMI
audio will simply stop working.&lt;/p&gt;
&lt;p&gt;Audio drift, lag, and eventually …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;The problem&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The HDMI out works just fine out of the box, except that you'll notice
that unless you boot with the HDMI cable connected, you'll experience
some weird audio lag through HDMI. Even worse, after a few seconds, HDMI
audio will simply stop working.&lt;/p&gt;
&lt;p&gt;Audio drift, lag, and eventually no audio. To rub some salt into the
wound, this does not happen under macOS. Classic.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The solution&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, the good news is that you can get this fixed. Turns out this is
because of &lt;a href="https://bugzilla.kernel.org/show_bug.cgi?id=60769"&gt;Linux kernel bug #60769&lt;/a&gt;. I can't
comment on the details of how and why the &lt;code&gt;IOMMU&lt;/code&gt; feature breaks this
particular combination of videocard/HDMI/audio, but I can tell you how
to work-around this.&lt;/p&gt;
&lt;p&gt;To fix, or at least work-around this, you have to edit your
&lt;code&gt;/etc/default/grub&lt;/code&gt; and add &lt;code&gt;intel_iommu=on,igfx_off&lt;/code&gt; to your kernel
boot options:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;(...) intel_iommu=on,igfx_off&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="planetgnome"></category><category term="2020"></category><category term="debian"></category><category term="linux"></category><category term="english"></category><category term="free software"></category></entry></feed>