<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
>
	<channel>
		<title>Chaotic Experiments</title>
		<description>The semi-interesting bits brought to you from entropy.</description>
		<sy:updatePeriod>daily</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		<link>https://chaoticlab.io/</link>
		<atom:link href="https://chaoticlab.io/feed.xml" rel="self" type="application/rss+xml" />
		<lastBuildDate>Fri, 29 Mar 2024 00:00:00 +0200</lastBuildDate>
		<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 29.3 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 29.3 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I have also uploaded installers for 29.2 because I have completely missed that release.&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orge676912&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org092cc3e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org03a5b25&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgc583c97&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org0d6fdd4&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org1d51fac&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Fri, 29 Mar 2024 00:00:00 +0200</pubDate>
				<link>https://chaoticlab.io/posts/emacs-29-3-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-29-3-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 29.1 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 29.1 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org3692d80&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org2e1b95e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orge7fe294&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org78a17df&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org399e595&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5bdcf57&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 01 Aug 2023 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-29-1-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-29-1-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 28.2 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 28.2 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgc125c31&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org9d624a2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org2463e33&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org85871f2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org7550c9c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org0b6f0c3&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Mon, 26 Sep 2022 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-28-2-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-28-2-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 28.1 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 28.1 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
This time there is no 32-bit version of it as no 32-bit executables were provided by the maintainers.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgc440404&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgaca397d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org5950f70&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org0ebba41&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd13ff2b&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org1592bb0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Wed, 04 May 2022 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-28-1-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-28-1-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 27.2 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 27.2 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from a previous release because the installer&apos;s code was not modified since then, so the screenshots will look the same (except the version number, obviously).&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org4ed9868&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga9d1d00&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd9bf715&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga6003d2&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org6fa4054&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org344f491&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 13 Apr 2021 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-27-2-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-27-2-msi/</guid>
			</item>
		
			<item>
				<title>Installing Entware on an Android-powered device: Entware Installer Module for Magisk</title>
				
				
					<description>&lt;p&gt;
You may have an old unused Android-powered phone lying around, or you may have a set-top box which remains unused most of the time, so you want to make it to work also as a home WEB-server. Maybe you are geeky enough for an idea of carrying a Linux-powered server in your pocket. Or you would like to improve the functionality of your Android phone to include a package manager which simplifies installation of &lt;a href=&quot;http://bin.entware.net/armv7sf-k2.6/Packages.html&quot;&gt;a large number of server-side software and development tools&lt;/a&gt;. These are only the reasons for installing &lt;a href=&quot;https://entware.net/&quot;&gt;Entware&lt;/a&gt; on an Android-powered device I can imagine. Everyone can have his or her reasons for doing so.
&lt;/p&gt;

&lt;p&gt;
However, installing Entware on Android might be not straightforward. Initially, I planned to write a guide on how-to get Entware running on a device rooted using Magisk.
&lt;/p&gt;

&lt;p&gt;
To my shame, the guide turned out to be complicated and error-prone. To save you from the hassle, I decided to reuse my findings and code and developed a module for Magisk which you can &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk&quot;&gt;find on Github&lt;/a&gt;. Installing Entware using this module is as straightforward as possible, but for now, it supports only devices on which the root file system is a RAM-drive (&lt;code&gt;rootfs&lt;/code&gt;). Unfortunately, this rules out most of the recent devices released with Android 9 and newer (so-called &quot;system-as-root&quot; devices). On these devices, the root file system is a real partition, so you need to manually modify  it before using the module because Magisk does not currently provide a facility to make reversible modifications to directories outside of &quot;/system.&quot;
&lt;/p&gt;

&lt;p&gt;
I do not want to repeat myself in this post because I wrote hopefully &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk/blob/master/README.md&quot;&gt;complete documentation for the module&lt;/a&gt;. If you happen to have a newer device where the root file system is not a RAM-drive,
I &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk/blob/master/README.md#compatibility&quot;&gt;mentioned&lt;/a&gt; there the modifications which you might want to make before the installation.
&lt;/p&gt;

&lt;p&gt;
Hopefully, I will get this module into the official Magisk modules repository at some point. Now you can install it manually, as &lt;a href=&quot;https://github.com/arbv/entware-installer-for-magisk/blob/master/README.md#installation&quot;&gt;described in the documentation&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Happy Entware installation!
&lt;/p&gt;
</description>
				
				<pubDate>Fri, 02 Oct 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/entware-installer-for-magisk/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/entware-installer-for-magisk/</guid>
			</item>
		
			<item>
				<title>Update to My &apos;daemonize&apos; Library</title>
				
				
					<description>&lt;p&gt;
I have updated &lt;a href=&quot;/c/c++/unix/2018/10/01/daemonize.html&quot;&gt;my tiny C library for writing Unix daemons&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
In fact, the library&apos;s code itself remained intact.  When the original version was released, I made a somewhat sinful thing: although the library&apos;s code was written with portability in mind, the only example which came with it was Linux specific because of usage of &lt;a href=&quot;https://www.man7.org/linux/man-pages/man2/signalfd.2.html&quot;&gt;&lt;code&gt;signalfd(2)&lt;/code&gt;&lt;/a&gt; to redirect signal handling to the main event processing loop. This issue has been addressed recently: now, additionally to the original Linux specific example there is one which should be portable to the other Unix-like systems. It utilises the somewhat lesser-known &lt;a href=&quot;https://cr.yp.to/docs/selfpipe.html&quot;&gt;self-pipe trick&lt;/a&gt; to redirect signal processing to the loop &lt;sup&gt;&lt;a id=&quot;fnr.example&quot; class=&quot;footref&quot; href=&quot;#fn.example&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;

&lt;p&gt;
I advise you to use the new example as a template for your daemons, even though there is slightly more code involved in doing the same thing. Even though we seem to live in the world of Linux monoculture, losing portability to other Unixes would be a sad thing.
&lt;/p&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.example&quot; class=&quot;footnum&quot; href=&quot;#fnr.example&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot; role=&quot;doc-footnote&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
&lt;a href=&quot;https://man7.org/tlpi/code/online/dist/altio/self_pipe.c.html&quot;&gt;Here&lt;/a&gt; you can find another good example of the trick.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 08 Sep 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/daemonize-posix-update/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/daemonize-posix-update/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 27.1 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 27.1 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
As usual, it is a belated update.
&lt;/p&gt;

&lt;p&gt;
Although this release of Emacs contains a Windows installer, I decided to release my installer as well, because MSI installers might be more convenient in some cases.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I decided to reuse screenshots from the previous release because the installer&apos;s code was not modified since then.&lt;/i&gt;
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org38a89a0&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgdcfa594&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org26fa044&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orge3ea924&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org02f8d30&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org60c9c9d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 25 Aug 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-27-1-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-27-1-msi/</guid>
			</item>
		
			<item>
				<title>Finding the Square Root of a Number Without Using the Standard Library (Newton&apos;s Method)</title>
				
				
					<description>&lt;p&gt;
In this short post, I want to show a way to find the square root of a positive number without relying on the standard library using &lt;a href=&quot;https://en.wikipedia.org/wiki/Newton%27s_method&quot;&gt;Newton&apos;s method&lt;/a&gt;. This is the method which seems to be used in many implementations of the C standard library. The example code is in the C programming language. Before going to the implementation, I provide the mathematical formulae used.
&lt;/p&gt;

&lt;p&gt;
I want to demonstrate how one could solve it with a relatively small amount of code without sacrificing precision much or at all compared to the &lt;code&gt;sqrt()&lt;/code&gt; function from the C standard library.
&lt;/p&gt;
&lt;div id=&quot;outline-container-org0f1ff28&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org0f1ff28&quot;&gt;A Bit of Math&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org0f1ff28&quot;&gt;
&lt;p&gt;
Before going to the code, we need to describe the method which we are going to use. No advanced understanding of math is required.
&lt;/p&gt;

&lt;p&gt;
Finding the square root of a number
&lt;/p&gt;

&lt;p&gt;
\[N = \sqrt{X}\]
&lt;/p&gt;

&lt;p&gt;
using Newton&apos;s method requires multiple steps.
&lt;/p&gt;

&lt;p&gt;
To find the value of the desired accuracy
&lt;/p&gt;

&lt;p&gt;
\[N = A_n\]
&lt;/p&gt;

&lt;p&gt;
we will use the following formula:
&lt;/p&gt;

&lt;p&gt;
\[A_{n} = \frac{A_{n-1} + \frac{X}{A_{n-1}}}{2}\]
&lt;/p&gt;

&lt;p&gt;
where accuracy depends on the value of \(n\). The higher the value of \(n\) the more accurate value of square root we could obtain. We can say that \(n\) is the number of approximations (how many times we want to apply this formula).
&lt;/p&gt;

&lt;p&gt;
When choosing \(n\) one needs to keep in mind that, in general, Newton&apos;s method has quadratic convergence which intuitively means that the number of correct digits roughly doubles in every step. On a computer, the number of approximations is dictated by the hardware.
&lt;/p&gt;

&lt;p&gt;
From the formula above it is obvious that we need to know a way to find a value of \(A_1\) to start.
&lt;/p&gt;

&lt;p&gt;
A good starting value (or, should I say, a good first approximation) would be &lt;i&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Integer_square_root&quot;&gt;integer square root&lt;/a&gt;&lt;/i&gt; of \(X\):
&lt;/p&gt;

&lt;p&gt;
\[I=\lfloor \sqrt{X} \rfloor\]
&lt;/p&gt;

&lt;p&gt;
so
&lt;/p&gt;

&lt;p&gt;
\[A_{1} = I.\]
&lt;/p&gt;

&lt;p&gt;
We will refer to this formulae during the programming process. Now let&apos;s go to the implementation.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgfd256b1&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgfd256b1&quot;&gt;Implementation&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgfd256b1&quot;&gt;
&lt;p&gt;
From the description above it becomes obvious that the first step which we need to do is to calculate the &lt;i&gt;integer square root&lt;/i&gt; \(I\). We can calculate this value iteratively increasing some number \(k\) starting from \(1\) until \(k^2 \gt X\). Reaching this condition means that we have found the &lt;i&gt;integer square root&lt;/i&gt; \(I\) of the number \(X\):
&lt;/p&gt;

&lt;p&gt;
\[I = k - 1.\]
&lt;/p&gt;

&lt;p&gt;
We can achieve this using the following C code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;isqrt&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;k&lt;/span&gt; = 1, &lt;span class=&quot;org-variable-name&quot;&gt;result&lt;/span&gt; = 1;
    &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (result &amp;lt;= X)
    {
        k++;
        result = k*k;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; k--;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
There are more &lt;a href=&quot;http://www.nuprl.org/MathLibrary/integer_sqrt/&quot;&gt;efficient methods available&lt;/a&gt;, but this one is easier to understand.
&lt;/p&gt;

&lt;p&gt;
Then we need to find \(A_n\)&lt;sup&gt;&lt;a id=&quot;fnr.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I have to admit that this sentence was added after some &lt;a href=&quot;https://www.reddit.com/r/programming/comments/gmsnog/finding_the_square_root_of_a_number_without_using/&quot;&gt;discussion&lt;/a&gt; at Reddit and it is quite bold. I tried to find some facts which will prove that I am wrong, but so far I have found none. But I am not a floating-point expert, though, so if you have information on this or, even better, the proof - please feel free to contact me. I am interested in improving this code and always ready to admit my mistakes. iteratively. Here the question arises: how should we peek \(n\)? We can paraphrase this question: how many times should we approximate the value?
&lt;/p&gt;

&lt;p&gt;
In C we can use the following trick: considering that the floating-point numbers have finite precision, we may iterate until the value \(A_n\) and \(A_{n-1}\) will not become equal when compared using &lt;code&gt;==&lt;/code&gt; operator in C. That means that we have reached the maximum possible precision on the current hardware (at least for this implementation). That is to say that I expect the method to converge as soon as
&lt;/p&gt;

&lt;p&gt;
\[\left[A_{n-1} - A_n \right] \lt \epsilon\]
&lt;/p&gt;

&lt;p&gt;
where \(\epsilon\) is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Machine_epsilon&quot;&gt;machine epsilon&lt;/a&gt; for double-precision floating-point values (defined as &lt;code&gt;DBL_EPSILON&lt;/code&gt; constant in C).&lt;sup&gt;&lt;a id=&quot;fnr.1.1&quot; class=&quot;footref&quot; href=&quot;#fn.1&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;

&lt;p&gt;
Please keep in mind that this approach may not work in some other programming environments. If it is the case, limit \(n\) with some sane number. Also keep in mind, that we are targeting platforms with &lt;a href=&quot;https://en.wikipedia.org/wiki/IEEE_754&quot;&gt;IEEE 754-compliant&lt;/a&gt; floating-point units.
&lt;/p&gt;

&lt;p&gt;
So, finally, here is the code which implements calculation of the square root using Newton&apos;s method (with some checks omitted for clarity):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;nsqrt&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;I&lt;/span&gt;;
    &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;A_prev&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;A&lt;/span&gt;;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 0.0 || X == 1.0 &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; X;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    I = isqrt((&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)X); &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;see above&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)(I*I)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;exact root&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)I;
    }
    A = A_prev = I;
    &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt; {
        A_prev = A;
        A = (A + X/A)/2.0;
    } &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (A_prev != A);

    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; A;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The reader might be interested in how well the code above performs compared against the &lt;code&gt;sqrt()&lt;/code&gt; function from the C standard library. According to my tests, precision wise, it produces very similar or even the same results, at least on Windows (x86_64) and Linux (x86_64, ARM). I believe that it would be &lt;a href=&quot;https://github.com/brho/plan9/blob/master/sys/src/libc/port/sqrt.c&quot;&gt;the case&lt;/a&gt; for &lt;a href=&quot;https://9p.io/plan9/&quot;&gt;Plan 9&lt;/a&gt; as well. There is one notable exception though: when calculating \(\sqrt{2}\) the results produced by the function above and the built-in one might differ. It seems that the functions in standard C library implementations may return the precomputed value of \(\sqrt{2}\) (the &lt;code&gt;M_SQRT2&lt;/code&gt; constant), which might have been computed using different, possibly more precise, method.
&lt;/p&gt;

&lt;p&gt;
Let&apos;s add the corresponding check to the code (as well as some other checks). Here is the revised version of the function:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;nsqrt&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;inf&lt;/span&gt; = 1.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;positive infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;ninf&lt;/span&gt; = -inf; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;negative infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;nan&lt;/span&gt; = 0.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;not a number&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;I&lt;/span&gt;;
    &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;A_prev&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;A&lt;/span&gt;;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 0.0 || X == 1.0 || X == inf)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; X;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 2.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; M_SQRT2;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == ninf || X &amp;lt; -0.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;NaN cannot be compared using == operator&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (memcmp((&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;X, (&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;nan, &lt;span class=&quot;org-keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)) == 0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;I =  floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    I = isqrt((&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)X);
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)(I*I)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;exact root&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)I;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Newton&apos;s method: A{n} = (A{n-1} + X/A{n-1})/2&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    A = A_prev = I; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;A{1} = I, or A{1} = floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt; {
        A_prev = A;
        A = (A + X/A)/2.0;
    } &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (A_prev != A);
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; A;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
As far as I can tell, this version should be standard-compliant (at least on my hardware), but I do not want to make such a bold statement, especially considering that developing the standard compliant version of &lt;code&gt;sqrt()&lt;/code&gt; was not the main point of this post.
&lt;/p&gt;

&lt;p&gt;
Moreover, I do not want to claim that this function works in the same way as &lt;code&gt;sqrt()&lt;/code&gt; from the standard C library. For some input values that can be not true. At very least you can expect that the results would be very similar. Please keep it in mind when comparing the implementations.
&lt;/p&gt;

&lt;p&gt;
The main point of this post is to show that one can solve the problem without sacrificing precision with a small amount of code, a bit of math and some knowledge of how the hardware works.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org2493c05&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org2493c05&quot;&gt;The Full Example&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org2493c05&quot;&gt;
&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;to make assert() work in release builds&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#undef&lt;/span&gt; NDEBUG

&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;assert.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;org-preprocessor&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;org-comment-delimiter&quot;&gt;/*&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
Given a number N, the task is to find the square root of N without using sqrt() function.
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;org-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;isqrt&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;k&lt;/span&gt; = 1, &lt;span class=&quot;org-variable-name&quot;&gt;result&lt;/span&gt; = 1;
    &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (result &amp;lt;= X)
    {
        k++;
        result = k*k;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; k--;
}

&lt;span class=&quot;org-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;nsqrt&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;X&lt;/span&gt;)
{
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;inf&lt;/span&gt; = 1.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;positive infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;ninf&lt;/span&gt; = -inf; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;negative infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;nan&lt;/span&gt; = 0.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;not a number&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;I&lt;/span&gt;;
    &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;A_prev&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;A&lt;/span&gt;;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 0.0 || X == 1.0 || X == inf)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; X;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == 2.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; M_SQRT2;
    }
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == ninf || X &amp;lt; -0.0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;NaN cannot be compared using == operator&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (memcmp((&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;X, (&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *)&amp;amp;nan, &lt;span class=&quot;org-keyword&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)) == 0)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; nan;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;I =  floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    I = isqrt((&lt;span class=&quot;org-type&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;long&lt;/span&gt;)X);
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; (X == (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)(I*I)) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;exact root&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    {
        &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt;)I;
    }
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Newton&apos;s method: A{n} = (A{n-1} + X/A{n-1})/2&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    A = A_prev = I; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;A{1} = I, or A{1} = floor(sqrt(X))&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt; {
        A_prev = A;
        A = (A + X/A)/2.0;
    } &lt;span class=&quot;org-keyword&quot;&gt;while&lt;/span&gt; (A_prev != A);
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; A;
}

&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;main&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;argc&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;char&lt;/span&gt; **&lt;span class=&quot;org-variable-name&quot;&gt;argv&lt;/span&gt;)
{
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;inf&lt;/span&gt; = 1.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;positive infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;ninf&lt;/span&gt; = -inf; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;negative infinity&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;nan&lt;/span&gt; = 0.0l/0.0l; &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;not a number&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;i&lt;/span&gt;;
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;some edge cases&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
    assert(isnan(sqrt(nan)));
    assert(isnan(nsqrt(nan)));
    assert(isnan(sqrt(-1.0)));
    assert(isnan(nsqrt(-1.0)));
    assert(sqrt(inf) == nsqrt(inf));
    assert(isnan(sqrt(ninf)));
    assert(isnan(nsqrt(ninf)));
    assert(sqrt(0.0) == nsqrt(0.0));
    assert(sqrt(-0.0) == nsqrt(-0.0));
    assert(sqrt(1.0) == nsqrt(1.0));
    assert(sqrt(2.0) == nsqrt(2.0));

    &lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; (i = 0; i &amp;lt; 100; i++)
    {
        &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;r&lt;/span&gt; = sqrt(i), &lt;span class=&quot;org-variable-name&quot;&gt;nr&lt;/span&gt; = nsqrt(i);
        printf(&lt;span class=&quot;org-string&quot;&gt;&quot;%lu - sqrt(): %.50f, nsqrt(): %.50f. same: %s\n&quot;&lt;/span&gt;,
                i, r, nr, (r == nr ? &lt;span class=&quot;org-string&quot;&gt;&quot;true&quot;&lt;/span&gt; : &lt;span class=&quot;org-string&quot;&gt;&quot;false&quot;&lt;/span&gt;));
    }
    &lt;span class=&quot;org-keyword&quot;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;h2 class=&quot;footnotes&quot;&gt;Footnotes: &lt;/h2&gt;
&lt;div id=&quot;text-footnotes&quot;&gt;

&lt;div class=&quot;footdef&quot;&gt;&lt;sup&gt;&lt;a id=&quot;fn.1&quot; class=&quot;footnum&quot; href=&quot;#fnr.1&quot; role=&quot;doc-backlink&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;div class=&quot;footpara&quot; role=&quot;doc-footnote&quot;&gt;&lt;p class=&quot;footpara&quot;&gt;
I have to admit that this sentence was added after some &lt;a href=&quot;https://www.reddit.com/r/programming/comments/gmsnog/finding_the_square_root_of_a_number_without_using/&quot;&gt;discussion&lt;/a&gt; at Reddit and it is quite bold. I tried to find some facts which will prove that I am wrong, but so far I have found none. But I am not a floating-point expert, though, so if you have information on this or, even better, the proof - please feel free to contact me. I am interested in improving this code and always ready to admit my mistakes.
&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 19 May 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/sqrt-newton/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/sqrt-newton/</guid>
			</item>
		
			<item>
				<title>Facilities for Context Switching and Coroutines on AVR microcontrollers (and AVR-based Arduino boards)</title>
				
				
					<description>&lt;p&gt;
In this short post, I want to present a &lt;a href=&quot;https://github.com/arbv/avr-context&quot;&gt;small project&lt;/a&gt; on which I have been working for the last couple of weeks. It is a small library to control an AVR micro-controller execution context. Additionally, it can be used on AVR-based Arduino boards.
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;I have to note that this is my first serious attempt in micro-controllers programming. Nevertheless, I tried to do my best, but bugs are always possible, so bug reports are welcome. Caveat lector.&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
Initially, the project started as a side effect of my attempt to understand how task switching is performed in operating systems. I believe that it is better to use microcontrollers to understand the concepts like this one because the generic computers are meant to run full-featured, multi-user operating systems with virtual memory support. These things, while important on their own, considerably complicate the low-level programming to the point where it is hard to see the forest behind the trees.
&lt;/p&gt;

&lt;p&gt;
The functionality, developed in the process, turned out to be generic enough, so I decided to continue to work on the project, and implemented substitutes for functions &lt;code&gt;getcontext()&lt;/code&gt;, &lt;code&gt;setcontext()&lt;/code&gt;, &lt;code&gt;makecontext()&lt;/code&gt;, &lt;code&gt;swapcontext()&lt;/code&gt;. These functions are commonly available on UNIX-like operating systems because they used to be a part of the POSIX standard (You can read about them &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/getcontext.html&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html&quot;&gt;here&lt;/a&gt;). They can be used to implement many interesting abstractions, but in most cases, this functionality is used to implement coroutines. I decided to go ahead and implemented the &lt;a href=&quot;http://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf&quot;&gt;asymmetric stackful coroutines&lt;/a&gt; (as in the &lt;a href=&quot;https://www.lua.org/&quot;&gt;Lua programming language&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
I tried to make the library&apos;s interface as easy to use as possible. There are 8 functions (4 to work with execution context, 4 for to work with coroutines), 4 macros and 2 data types. The interface can be summarised as follows (to give you the high level view):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-C&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Context Switching: avrcontext.h&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t_&lt;/span&gt; {
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
} &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt;;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; (*&lt;span class=&quot;org-type&quot;&gt;avr_context_func_t&lt;/span&gt;)(&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *);

&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_SAVE_CONTEXT&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;presave_code&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;load_address_to_Z_code&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_RESTORE_CONTEXT&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;load_address_to_Z_code&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_SAVE_CONTEXT_GLOBAL_POINTER&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;presave_code&lt;/span&gt;, &lt;span class=&quot;org-variable-name&quot;&gt;global_context_pointer&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;org-preprocessor&quot;&gt;#define&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;AVR_RESTORE_CONTEXT_GLOBAL_POINTER&lt;/span&gt;(&lt;span class=&quot;org-variable-name&quot;&gt;global_context_pointer&lt;/span&gt;) &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_getcontext&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_setcontext&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;);

&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_swapcontext&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;oucp&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_makecontext&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;cp&lt;/span&gt;,
                     &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;stackp&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;stack_size&lt;/span&gt;,
                     &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_context_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;successor_cp&lt;/span&gt;,
                     &lt;span class=&quot;org-type&quot;&gt;avr_context_func_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;funcp&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;funcargp&lt;/span&gt;);

&lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Asymmetric Stackful Coroutines: avrcoro.h&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_coro_t_&lt;/span&gt; {
    &lt;span class=&quot;org-comment-delimiter&quot;&gt;/* &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt; */&lt;/span&gt;
} &lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt;;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_coro_state_t_&lt;/span&gt; {
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_SUSPENDED&lt;/span&gt; = 0,
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_RUNNING&lt;/span&gt;,
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_DEAD&lt;/span&gt;,
    &lt;span class=&quot;org-variable-name&quot;&gt;AVR_CORO_ILLEGAL&lt;/span&gt;,
} &lt;span class=&quot;org-type&quot;&gt;avr_coro_state_t&lt;/span&gt;;

&lt;span class=&quot;org-keyword&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *(*&lt;span class=&quot;org-type&quot;&gt;avr_coro_func_t&lt;/span&gt;)(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *);

&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_init&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;coro&lt;/span&gt;,
                  &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;stackp&lt;/span&gt;, &lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;stack_size&lt;/span&gt;,
                  &lt;span class=&quot;org-type&quot;&gt;avr_coro_func_t&lt;/span&gt; &lt;span class=&quot;org-variable-name&quot;&gt;func&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_resume&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;coro&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; **&lt;span class=&quot;org-variable-name&quot;&gt;data&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_yield&lt;/span&gt;(&lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;self&lt;/span&gt;, &lt;span class=&quot;org-type&quot;&gt;void&lt;/span&gt; **&lt;span class=&quot;org-variable-name&quot;&gt;data&lt;/span&gt;);
&lt;span class=&quot;org-type&quot;&gt;avr_coro_state_t&lt;/span&gt; &lt;span class=&quot;org-function-name&quot;&gt;avr_coro_state&lt;/span&gt;(&lt;span class=&quot;org-keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;org-type&quot;&gt;avr_coro_t&lt;/span&gt; *&lt;span class=&quot;org-variable-name&quot;&gt;coro&lt;/span&gt;);

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
I do not want to repeat myself here, so if you are interested, you can find the full project documentation on &lt;a href=&quot;https://github.com/arbv/avr-context&quot;&gt;the project&apos;s&lt;/a&gt; page on GitHub. There are &lt;a href=&quot;https://github.com/arbv/avr-context/tree/master/examples&quot;&gt;examples&lt;/a&gt; included. I tried to arrange them in such a way that one can use them as a tutorial. They are, I hope, properly documented as well.
&lt;/p&gt;

&lt;p&gt;
The list of available examples:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;b&gt;Context Switching:&lt;/b&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/01.GOTO_via_Context_Switching/01.GOTO_via_Context_Switching.ino&quot;&gt;GOTO via Context Switching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/02.Non-Linear_Program_Execution/02.Non-Linear_Program_Execution.ino&quot;&gt;Non-Linear Program Execution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/03.Symmetric_Stackful_Coroutines/03.Symmetric_Stackful_Coroutines.ino&quot;&gt;Symmetric Stackful Coroutines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Context_Switching/04.Preemptive_Task_Switching/04.Preemptive_Task_Switching.ino&quot;&gt;Preemptive Task Switching&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Coroutines:&lt;/b&gt;
&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/01.Basic_Generator/01.Basic_Generator.ino&quot;&gt;Basic Generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/02.Symmetric_Coroutines_via_Asymmetric_Ones/02.Symmetric_Coroutines_via_Asymmetric_Ones.ino&quot;&gt;Symmetric Coroutines via Asymmetric Ones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/03.Producer-Consumer/03.Producer-Consumer.ino&quot;&gt;Producer-Consumer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/arbv/avr-context/blob/master/examples/Coroutines/04.Producer-Filter-Consumer/04.Producer-Filter-Consumer.ino&quot;&gt;Producer-Filter-Consumer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The library can be installed via &quot;Library Manager&quot; in Arduino IDE (search for &lt;b&gt;AVR-context&lt;/b&gt;).
&lt;/p&gt;


&lt;div id=&quot;org44111c5&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/avr-context/libmgr.png&quot; alt=&quot;libmgr.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
The project turned out to be very interesting on itself and involved some research. The references to the specifications, papers and other resources can be found in the project&apos;s documentation. I may do a couple of publications which demonstrate how this library was developed. Although the result is hardware specific, the approach itself can be adapted to almost any hardware platform.
&lt;/p&gt;
</description>
				
				<pubDate>Fri, 15 May 2020 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/avr-context/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/avr-context/</guid>
			</item>
		
			<item>
				<title>High-Quality Video Playback on Linux</title>
				
				
					<description>&lt;p&gt;
Some programs are so damn good that you start to see them without any relation to the platform on which they run. In this case, you start looking for their substitutes if you are unable to use them on some platforms, often without success. In my opinion, one of the better combinations for video playback is &lt;a href=&quot;https://mpc-hc.org/&quot;&gt;Media Player Classic Home Cinema&lt;/a&gt; in combination with &lt;a href=&quot;http://madvr.com/&quot;&gt;MadVR&lt;/a&gt; video renderer. It is rather hard to beat this combination, but there is a very good, open-source alternative available on Linux: &lt;a href=&quot;https://mpv.io/&quot;&gt;mpv&lt;/a&gt;+&lt;a href=&quot;https://www.smplayer.info/&quot;&gt;SMPlayer&lt;/a&gt;. In this post, I am going to describe how I essentially repeated my configuration for high-quality video playback on Linux.
&lt;/p&gt;

&lt;p&gt;
I believe that there is one thing worth noting: as both &lt;code&gt;SMPlayer&lt;/code&gt; and &lt;code&gt;mpv&lt;/code&gt; are available on Windows the information from this post might be useful if you plan to use these programs on Windows as well. I think that no additional adaptation required for this platform. The same goes for macOS.
&lt;/p&gt;

&lt;p&gt;
I would suggest you keep the &lt;a href=&quot;https://mpv.io/manual/stable/&quot;&gt;man page&lt;/a&gt; of &lt;code&gt;mpv&lt;/code&gt; opened so that you can quickly read about the configuration options referenced in this post.
&lt;/p&gt;
&lt;div id=&quot;outline-container-org97e1b73&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org97e1b73&quot;&gt;Important Options for High-Quality Video Playback&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org97e1b73&quot;&gt;
&lt;p&gt;
To improve video playback quality, we need the following:
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;b&gt;Good scaling algorithms&lt;/b&gt; - I believe that this part is obvious. I should note that scaling algorithms are computationally intensive in general and require a fairly high-performance video card. I suggest that you use the following algorithms: &lt;a href=&quot;https://en.wikipedia.org/wiki/Lanczos_resampling&quot;&gt;ewa_lanczos&lt;/a&gt; (aka jinc) with an &lt;a href=&quot;https://en.wikipedia.org/wiki/Ringing_artifacts&quot;&gt;anti-ringing filter&lt;/a&gt; for up-scaling and &lt;a href=&quot;https://en.wikipedia.org/wiki/Chrominance&quot;&gt;chroma&lt;/a&gt; scaling, mitchell for down-scaling. A better alternative to ewa_lanczos would be ewa_lanczossharp, but it is very computationally intensive.  If you have decided to use it, I believe that you might not need the anti-ringing filter in that case.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Smooth-motion (with V-Sync)&lt;/b&gt;. Here I should note that this is not converting video to the higher frame-rate as some might think. This technique allows frames from a video to better synchronise with frame-rate of your display. Without this, some judder might appear during motion. This technique is called &lt;a href=&quot;https://github.com/mpv-player/mpv/wiki/Interpolation&quot;&gt;Interpolation&lt;/a&gt; in &lt;code&gt;mpv&apos;s&lt;/code&gt; manual, and there is an in-depth explanation of it on the wiki of the project.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Debanding filter&lt;/b&gt; - prevents &lt;a href=&quot;https://en.wikipedia.org/wiki/Colour_banding&quot;&gt;colour banding&lt;/a&gt; from appearing on the scenes containing some gradients.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org8cd524b&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org8cd524b&quot;&gt;Configuring mpv&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org8cd524b&quot;&gt;
&lt;p&gt;
Let&apos;s create a configuration file for &lt;code&gt;mpv&lt;/code&gt; which uses the techniques mentioned above. The configuration file of &lt;code&gt;mpv&lt;/code&gt; is located here: &lt;code&gt;~/.config/mpv/mpv.conf&lt;/code&gt;, we are going to add the options described below into it.
&lt;/p&gt;

&lt;p&gt;
In some cases, I am going to mention settings both for &lt;b&gt;middle-end&lt;/b&gt; and &lt;b&gt;high-end&lt;/b&gt; systems. In my opinion, the visual difference between them is so subtle that I would suggest that you go with the configuration for middle-end systems first, especially if you use a laptop. If you use a relatively modern desktop or do not mind extra battery drain and fan noise then go experiment with the configuration for high-end systems.
&lt;/p&gt;

&lt;p&gt;
The first thing which we should set is a video renderer profile. There are many of them but &lt;code&gt;gpu&lt;/code&gt; and &lt;code&gt;gpu-hq&lt;/code&gt; are the ones in which we are interested the most. These, as you might have guessed, allow offloading most of the video post-processing and rendering to a GPU using OpenGL or Vulkan API. &lt;code&gt;gpu-hq&lt;/code&gt; is pre-configured to use higher quality, more computationally intensive filters.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;middle-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;profile=gpu
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;high-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;profile=gpu-hq
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
We may use Vulkan or OpenGL as a GPU API. Honestly, I have not noticed any difference in performance when playing a video using either, so I would suggest that you stick with OpenGL as the most compatible option. We are going to enable V-Sync as well.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;gpu-api=opengl
opengl-swapinterval=1
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
If you want to use Vulkan instead, here is how to do it:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;gpu-api=vulkan
vulkan-swap-mode=fifo
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The next logical step is to configure smooth-motion. Here is how:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;video-sync=display-resample
interpolation
tscale=oversample
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Now let&apos;s configure scaling.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;middle-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;scale=ewa_lanczos:scale-antiring=1
cscale=ewa_lanczos:scale-antiring=1
dscale=mitchell
correct-downscaling
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;b&gt;high-end systems:&lt;/b&gt;
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;scale=ewa_lanczossharp
cscale=ewa_lanczossharp
dscale=mitchell
correct-downscaling
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
It is a good idea to enable dithering when it is necessary. &lt;code&gt;mpv&lt;/code&gt; uses a fairly good dithering algorithm by default.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;dither-depth=auto
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
The last step is to offload video decoding to GPU when possible. It is especially useful for laptops. We are using &lt;code&gt;auto-copy&lt;/code&gt; instead of &lt;code&gt;auto&lt;/code&gt; to enforce copying back decoding results back to the system RAM. It might be necessary for some filters to work and helps to avoid some decoding issues at the expense of a relatively small performance loss.
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;hwdec=auto-copy
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-orgd944762&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;orgd944762&quot;&gt;Using SMPlayer with a Pre-configured mpv Instance&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-orgd944762&quot;&gt;
&lt;p&gt;
I prefer to use &lt;code&gt;mpv&lt;/code&gt; as a back-end of &lt;code&gt;SMPlayer&lt;/code&gt;. If you are going to use &lt;code&gt;mpv&lt;/code&gt; as a standalone video player then you can skip reading this section.
&lt;/p&gt;

&lt;p&gt;
Modern versions of &lt;code&gt;SMPlayer&lt;/code&gt; can use &lt;code&gt;mpv&lt;/code&gt; as its back-end without any additional configuration. However, &lt;code&gt;SMPlayer&lt;/code&gt; tries to have &lt;code&gt;mpv&lt;/code&gt; under its full control and starts it with &lt;code&gt;--no-config&lt;/code&gt; option. It forces &lt;code&gt;mpv&lt;/code&gt; to ignore its default configuration file. Fortunately, &lt;code&gt;SMPlayer&lt;/code&gt; can pass user-defined command-line options to &lt;code&gt;mpv&lt;/code&gt;, which allows us to bypass this limitation. To do it we have to use this extra option to force &lt;code&gt;mpv&lt;/code&gt; to load its configuration file:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;--include=~/.config/mpv/mpv.conf
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Here is the screenshot which shows us how to do it:
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org2f38d67&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/linux-hq-video-playback/extra-args.png&quot; alt=&quot;extra-args.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;
Please keep in mind that &lt;code&gt;SMPlayer&lt;/code&gt; expects that &lt;code&gt;mpv&lt;/code&gt; does not load its configuration file, so be conscious about what you have in the &lt;code&gt;mpv.conf&lt;/code&gt; file.
&lt;/p&gt;

&lt;p&gt;
Also, it might be a good idea to configure &lt;code&gt;SMPlayer&lt;/code&gt; to use &lt;code&gt;Default&lt;/code&gt; video output engine with disabled post-processing:
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orge45945e&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/linux-hq-video-playback/default-video-out.png&quot; alt=&quot;default-video-out.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org566ec93&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org566ec93&quot;&gt;Conclusions&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org566ec93&quot;&gt;
&lt;p&gt;
In this post, we have configured &lt;code&gt;mpv&lt;/code&gt; and &lt;code&gt;SMPlayer&lt;/code&gt; for high-quality video playback. I think that there are some things left which are worth noting.
&lt;/p&gt;

&lt;p&gt;
Firstly, the video output quality depends mostly on the quality of the video files. No amount of configuration will make a miracle here if all you have is a low-quality media material.
&lt;/p&gt;

&lt;p&gt;
Secondly, the quality of the display matters a lot. It does not necessarily mean that you should use these ridiculously expensive professional displays for high precision colour work. Adequately priced display with good IPS matrix will do. I doubt that you will see any difference on a low-end TFT monitor.
&lt;/p&gt;

&lt;p&gt;
I think that these things are rather obvious, but I wanted to have them mentioned anyway.
&lt;/p&gt;

&lt;p&gt;
Hopefully, this post will improve your &lt;del&gt;anime&lt;/del&gt; video playback experience and make your entertainment more joyful.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Mon, 07 Oct 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/linux-hq-video-playback/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/linux-hq-video-playback/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 26.3 for Windows with Per-User Installation Support</title>
				
				
					<description>&lt;p&gt;
I have been working on improving &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;Emacs installer for Windows&lt;/a&gt; to add support both per-user and per-machine installations. It was made to address the installation issues of users without administrative privileges. This post is a follow up to a post I have made &lt;a href=&quot;/posts/emacs-26-3-msi/&quot;&gt;recently&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
This effort resulted in adding support for building &lt;b&gt;per-user&lt;/b&gt; installers. These are available alongside the usual, &lt;b&gt;per-machine&lt;/b&gt; installers. It should be noted, though, that their name might be a little bit deceptive because they support installation in both per-machine &lt;b&gt;and&lt;/b&gt; per-user mode. As you might expect the latter does not require administrative privileges.
&lt;/p&gt;

&lt;p&gt;
Feature-wise both kinds of installers provide similar functionality with one notable exception: &lt;b&gt;the per-user installers unable to set and modify environmental variables conditionally depending on selected scope&lt;/b&gt; and, thus, unable to add installation directory of Emacs to the &lt;b&gt;Path&lt;/b&gt;. This is a limitation of tooling.
&lt;/p&gt;

&lt;p&gt;
Please keep in mind that mixing both per-user and per-machine installations of the same package on the same machine might result in strange behaviour. I would suggest sticking with classical, per-machine only installers if you have enough privileges on your machine.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
As usual, If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
The screenshots provided below show the installation of a per-user installer in advanced mode.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;orgf050894&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org46a7371&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgb51442d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgdc5c9bf&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org39fa6e6&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org9a2284d&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd46bc0c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-per-user-msi/07.png&quot; alt=&quot;07.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Tue, 01 Oct 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-26-3-per-user-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-26-3-per-user-msi/</guid>
			</item>
		
			<item>
				<title>Update: MSI Installer for GNU Emacs 26.3 for Windows</title>
				
				
					<description>&lt;p&gt;
Following the GNU Emacs 26.3 release, &lt;a href=&quot;/emacs/wix/update/2019/01/05/emacs_installer.html&quot;&gt;my MSI installer&lt;/a&gt; for GNU Emacs has been updated!
&lt;/p&gt;

&lt;p&gt;
This time it is rather a belated update.
&lt;/p&gt;

&lt;p&gt;
You can find all the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer&quot;&gt;sources&lt;/a&gt; on GitHub as well as the &lt;a href=&quot;https://github.com/arbv/emacs-msi-installer/releases&quot;&gt;pre-built installers&lt;/a&gt; for the latest release of GNU Emacs. The provided installers bundle official, unmodified GNU Emacs binaries for Windows.
&lt;/p&gt;

&lt;p&gt;
If you used an older version of the installer you should be able to perform an in-place upgrade.
&lt;/p&gt;

&lt;p&gt;
Enjoy!
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org177b0fb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/01.png&quot; alt=&quot;01.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;org8df1398&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/02.png&quot; alt=&quot;02.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgaee6541&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/03.png&quot; alt=&quot;03.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgd829cbb&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/04.png&quot; alt=&quot;04.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orga7aefbc&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/05.png&quot; alt=&quot;05.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;div id=&quot;orgbdb252f&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/emacs-26-3-msi/06.png&quot; alt=&quot;06.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Thu, 12 Sep 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/emacs-26-3-msi/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/emacs-26-3-msi/</guid>
			</item>
		
			<item>
				<title>Integrating Xfce with LightDM Display Manager</title>
				
				
					<description>&lt;p&gt;
One of the most basic security features of any laptop or workstation is the ability to lock the sscreen. It might be convenient in many other, non-security related, scenarios as well. In most cases, this feature works without user&apos;s intervention on most of the Linux distributions, yet it did not work for me in Xfce4 with LightDM on Arch Linux. As I understand, Xfce does not have its display manager, so it relies on third-party solutions, mostly Gnome Display Manager (GDM). As I prefer Xfce as my desktop environment, I did not want to install GDM as it needs many Gnome libraries to work. Because of this, I decided to use LighDM as my display manager, which is more desktop environment agnostic and lightweight. Unfortunately, Xfce lacks proper integration with it (at least in Arch Linux). In this post, I want to provide a solution to this problem. Moreover, I believe that information in this post might give some ideas to the users of the other desktop environments and window managers on how to integrate them with LightDM.
&lt;/p&gt;

&lt;p&gt;
To some extent, this post is a continuation of the other LightDM related post which I have posted &lt;a href=&quot;/posts/lightdm-extmonitor/&quot;&gt;earlier&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
If the first two buttons from the image below do not work on your system, you might want to continue reading this post.
&lt;/p&gt;

&lt;div class=&quot;org-center&quot;&gt;

&lt;div id=&quot;org83ca94c&quot; class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img src=&quot;/data/xfce-lightdm/session-buttons.png&quot; alt=&quot;session-buttons.png&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org3b26198&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org3b26198&quot;&gt;How Xfce Initiates Screen Locking and User Switching&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org3b26198&quot;&gt;
&lt;p&gt;
Xfce does not do screen locking or user switching itself, it delegates this functionality to the other programs.
&lt;/p&gt;

&lt;p&gt;
For screen locking Xfce executes &lt;code&gt;xflock4&lt;/code&gt; program which is a shell script. The script locks the session by calling the following programs if they are present on the system (in the following order):
&lt;/p&gt;

&lt;ol class=&quot;org-ol&quot;&gt;
&lt;li&gt;&lt;code&gt;xscreensaver-command&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gnome-screensaver-command&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xlock&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slock&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Similarly, Xfce delegates user switching to the gdmplexiserver which is (or was) a part of the Gnome Display Manager package. As you can see, Xfce is attuned to reuse some of the parts of the GNOME desktop environment.
&lt;/p&gt;

&lt;p&gt;
Considering that LightDM has its utility to control itself, the &lt;code&gt;dm-tool&lt;/code&gt;, we might try to &quot;deceive&quot; Xfce to invoke the &lt;code&gt;dm-tool&lt;/code&gt; instead. We could accomplish that by placing the scripts which call the &lt;code&gt;dm-tool&lt;/code&gt; with a required parameter (&lt;code&gt;lock&lt;/code&gt; or &lt;code&gt;switch-to-greeter&lt;/code&gt;) and are named as above mentioned programs into a directory from the &lt;code&gt;$PATH&lt;/code&gt; environmental variable (&lt;code&gt;/usr/local/bin&lt;/code&gt; seems like the right choice).
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;outline-container-org56787ac&quot; class=&quot;outline-2&quot;&gt;
&lt;h2 id=&quot;org56787ac&quot;&gt;The Scripts to Perform Screen Locking and User Switching&lt;/h2&gt;
&lt;div class=&quot;outline-text-2&quot; id=&quot;text-org56787ac&quot;&gt;
&lt;p&gt;
At this point, it is obvious that we need two &lt;b&gt;executable&lt;/b&gt; shell scripts, one for session locking and one for user switching, which we should place into &lt;code&gt;/usr/local/bin&lt;/code&gt; folder. For the first one, I propose to use the name &lt;code&gt;slock&lt;/code&gt; or &lt;code&gt;xlock&lt;/code&gt; &lt;i&gt;(I used to recommend &lt;code&gt;xscreensaver-command&lt;/code&gt;, but I had some problems in SMPlayer in this case)&lt;/i&gt;. Here is the code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;fake slock to make xflock to use lightdm locker
&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which dm-tool&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n $&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt; ] ; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    dm-tool lock
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
For the second case, user switching, we might use a very similar script, named as &lt;code&gt;gdmplexiserver&lt;/code&gt; (the only difference is a parameter to the &lt;code&gt;dm-tool&lt;/code&gt;):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;fake gdmplexiserver to make xflock to use lightdm locker
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;for user switching
&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which dm-tool&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n $&lt;span class=&quot;org-variable-name&quot;&gt;DMTOOL_AVAILABLE&lt;/span&gt; ] ; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    dm-tool switch-to-greeter
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
If you are a &lt;code&gt;systemd&lt;/code&gt; user, you might try to use a script which relies on &lt;code&gt;loginctl&lt;/code&gt; for both cases:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;LOGINCTL_AVAILABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which loginctl&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n $&lt;span class=&quot;org-variable-name&quot;&gt;LOGINCTL_AVAILABLE&lt;/span&gt; ] ; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    loginctl lock-session
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
After you have done all the steps mentioned above, screen locking and user switching in Xfce should work as expected.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;UPD:&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;20.07.19 - Note about problems with &lt;code&gt;xscreensaver-command&lt;/code&gt;.&lt;/i&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
				
				<pubDate>Fri, 19 Jul 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/xfce-lightdm/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/xfce-lightdm/</guid>
			</item>
		
			<item>
				<title>Using LightDM with an External Monitor on a Laptop or with the Multi-monitor Setups</title>
				
				
					<description>&lt;p&gt;
Like many other users, I find it convenient to connect an external monitor to my laptop sometimes. As I often do this, I expect this functionality to work flawlessly but, unfortunately, I experienced some problems when using LightDM on Arch Linux .  By default, LightDM tries to mirror data on multiple displays, and it does not work well when you have monitors with different resolutions. In this post, I want to share my solution to this problem. I expect that this solution might be useful not only for laptop users but for the workstation users with multi-monitor setups as well. Moreover, if LightDM&apos;s user interface sometimes stops responding to your actions, this post might be useful for you.
&lt;/p&gt;

&lt;p&gt;
In general, on a laptop with an external monitor, I expect the login screen to appear on it and have the laptop screen disabled in that case.  If there are multiple external monitors connected to the system, I want only one of them used for a login screen.
&lt;/p&gt;

&lt;p&gt;
Fortunately, these actions can be programmed using a UNIX shell script build around the functionality of the &lt;code&gt;xrandr&lt;/code&gt; utility.
&lt;/p&gt;

&lt;p&gt;
When used without any parameters it prints the list of monitor outputs alongside the information about the connected monitors:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;artem@artbox:~$ xrandr
Screen 0: minimum 8 x 8, current 1366 x 768, maximum 32767 x 32767
LVDS1 connected 1366x768+0+0 (normal left inverted right x axis y axis) 340mm x 190mm
   1366x768      60.03*+
   1280x720      59.74
   1024x768      60.00
   1024x576      60.00    59.90    59.82
   960x540       60.00    59.63    59.82
   800x600       60.32    56.25
   864x486       60.00    59.92    59.57
   640x480       59.94
   720x405       59.51    60.00    58.99
   680x384       60.00
   640x360       59.84    59.32    60.00
DP1 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
VGA1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
We could filter out the information about the available outputs using the UNIX tools:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;artem@artbox:~$ xrandr | grep connected | cut -d &apos; &apos; -f 1-2
LVDS1 connected
DP1 disconnected
HDMI1 disconnected
VGA1 disconnected
VIRTUAL1 disconnected
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Keeping in mind that an internal laptop screen is usually connected using the &lt;code&gt;LVDS&lt;/code&gt; interface, we could use the information obtained from the &lt;code&gt;xrandr&lt;/code&gt; tool to achieve what is required.
&lt;/p&gt;

&lt;p&gt;
Let&apos;s outline the logic of the script using pseudo-code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;var primary_out = nil
var to_disable = nil

foreach monitor_out in list_monitor_outputs() do
    if is_connected(monitor_out) then
        if is_connected_via_LVDS(monitor_out) then
            to_disable = monitor_out
        else if primary_out == nil then
            primary_out = monitor_out
        else
            disable_monitor_output(monitor_out)
        endif
    endif
endfor

if primary_out != nil and to_disable != nil then
    set_as_primary_monitor_output(primary_out)
    disable_monitor_output(to_disable)
else if primary_out != nil then
    set_as_primary_monitor_output(primary_out)
endif
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
After translating the pseudo-code above into a shell script, I got the following code:
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-shell&quot;&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;!/bin/&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;the script will not work if xrandr is not available
&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -z &lt;span class=&quot;org-string&quot;&gt;&quot;$(&lt;/span&gt;&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;which xrandr&lt;/span&gt;&lt;span class=&quot;org-string&quot;&gt;)&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;exit&lt;/span&gt; 1
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;org-variable-name&quot;&gt;DISABLE_SUBSTRING&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;LVDS&quot;&lt;/span&gt;

&lt;span class=&quot;org-variable-name&quot;&gt;TO_DISABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;PRIMARY_OUT&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;&quot;&lt;/span&gt;

&lt;span class=&quot;org-variable-name&quot;&gt;old_IFS&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;${IFS}&quot;&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;IFS&lt;/span&gt;=$&lt;span class=&quot;org-string&quot;&gt;&apos;\n&apos;&lt;/span&gt;
&lt;span class=&quot;org-keyword&quot;&gt;for&lt;/span&gt; out&lt;span class=&quot;org-keyword&quot;&gt; in&lt;/span&gt; &lt;span class=&quot;org-sh-quoted-exec&quot;&gt;`xrandr | grep connected | cut -d &apos; &apos; -f 1-2`&lt;/span&gt;; &lt;span class=&quot;org-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;org-variable-name&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;`echo $out | cut -d &apos; &apos; -f 1`&lt;/span&gt;
    &lt;span class=&quot;org-variable-name&quot;&gt;state&lt;/span&gt;=&lt;span class=&quot;org-sh-quoted-exec&quot;&gt;`echo $out | cut -d &apos; &apos; -f 2`&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ &lt;span class=&quot;org-string&quot;&gt;&quot;$state&quot;&lt;/span&gt; = &lt;span class=&quot;org-string&quot;&gt;&quot;connected&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;org-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt; in&lt;/span&gt;
            &lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;disable a monitor connected via LVDS
&lt;/span&gt;            ${&lt;span class=&quot;org-variable-name&quot;&gt;DISABLE_SUBSTRING&lt;/span&gt;}*)
                &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -z &lt;span class=&quot;org-string&quot;&gt;&quot;$TO_DISABLE&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
                    &lt;span class=&quot;org-variable-name&quot;&gt;TO_DISABLE&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt;
                &lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
                ;;
            *)
                &lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;set the &apos;first&apos; external monitor as the
&lt;/span&gt;                &lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;primary one, disable the other external monitors
&lt;/span&gt;                &lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -z &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
                    &lt;span class=&quot;org-variable-name&quot;&gt;PRIMARY_OUT&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt;
                &lt;span class=&quot;org-keyword&quot;&gt;else&lt;/span&gt;
                    xrandr --output &lt;span class=&quot;org-string&quot;&gt;&quot;$name&quot;&lt;/span&gt; --off
                &lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
                ;;
        &lt;span class=&quot;org-keyword&quot;&gt;esac&lt;/span&gt;
    &lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;org-keyword&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;org-variable-name&quot;&gt;IFS&lt;/span&gt;=&lt;span class=&quot;org-string&quot;&gt;&quot;${old_IFS}&quot;&lt;/span&gt;

&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;If there is an internal screen, as well as at least one external monitor, then
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;disable the internal monitor and use the external monitor as the primary one.
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;Otherwise, if there are any external monitors, use the &apos;first&apos; detected one
&lt;/span&gt;&lt;span class=&quot;org-comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;org-comment&quot;&gt;as the primary monitor.
&lt;/span&gt;&lt;span class=&quot;org-keyword&quot;&gt;if&lt;/span&gt; [ -n &lt;span class=&quot;org-string&quot;&gt;&quot;$TO_DISABLE&quot;&lt;/span&gt; ] &amp;amp;&amp;amp; [ -n &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    xrandr --output &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; --primary --auto --output &lt;span class=&quot;org-string&quot;&gt;&quot;$TO_DISABLE&quot;&lt;/span&gt; --off
&lt;span class=&quot;org-keyword&quot;&gt;elif&lt;/span&gt; [ -n &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; ]; &lt;span class=&quot;org-keyword&quot;&gt;then&lt;/span&gt;
    xrandr --output &lt;span class=&quot;org-string&quot;&gt;&quot;$PRIMARY_OUT&quot;&lt;/span&gt; --primary --auto
&lt;span class=&quot;org-keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;org-keyword&quot;&gt;exit&lt;/span&gt; 0
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
To use the script, one should save it into an &lt;b&gt;executable&lt;/b&gt; file and alter the LightDM&apos;s settings to use it to configure the displays.
&lt;/p&gt;

&lt;p&gt;
In order to accomplish this one should change the &lt;code&gt;display-setup-script&lt;/code&gt; in the &lt;code&gt;[Seat:*]&lt;/code&gt; section of the LightDM configuration file (&lt;code&gt;/etc/lightdm/lightdm.conf&lt;/code&gt;):
&lt;/p&gt;

&lt;div class=&quot;org-src-container&quot;&gt;
&lt;pre class=&quot;src src-nil&quot;&gt;[Seat:*]
...
display-setup-script=/path/to/the-script
...

&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
To apply the new settings, please restart the LightDM daemon. The next LightDM session should use the script to configure monitors.
&lt;/p&gt;
</description>
				
				<pubDate>Tue, 16 Jul 2019 00:00:00 +0300</pubDate>
				<link>https://chaoticlab.io/posts/lightdm-extmonitor/</link>
				<guid isPermaLink="true">https://chaoticlab.io/posts/lightdm-extmonitor/</guid>
			</item>
		
	</channel>
</rss>


