<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en" xml:base="http://blog.bstpierre.org/wp-atom.php">
	<title type="text">The Daily Build</title>
	<subtitle type="text">Software Development, version 3.0</subtitle>

	<updated>2012-05-16T12:07:25Z</updated>

	<link rel="alternate" type="text/html" href="http://blog.bstpierre.org" />
	<id>http://blog.bstpierre.org/feed/atom</id>
	

	<generator uri="http://wordpress.org/" version="3.0.4">WordPress</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TheDailyBuild" /><feedburner:info uri="thedailybuild" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>TheDailyBuild</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[Moving Through i3 Workspaces]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/7DE0DJBPkdY/moving-through-i3-workspaces" />
		<id>http://blog.bstpierre.org/?p=426</id>
		<updated>2012-05-10T18:14:47Z</updated>
		<published>2012-05-16T12:07:25Z</published>
		<category scheme="http://blog.bstpierre.org" term="linux" /><category scheme="http://blog.bstpierre.org" term="i3" /><category scheme="http://blog.bstpierre.org" term="tip" />		<summary type="html"><![CDATA[The default i3 config file only has commands to move to a specific numbered workspace (e.g. mod-1, mod-2). For better or worse, I&#8217;m in the habit of &#8220;traveling&#8221; through the workspace list using Ctrl-Alt-Up and Ctrl-Alt-Down (or Left and Right, if you prefer a horizontal feel for your workspaces). This is trivial to do in [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/moving-through-i3-workspaces">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/moving-through-i3-workspaces";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "Moving+Through+i3+Workspaces";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;The default i3 config file only has commands to move to a specific numbered workspace (e.g. mod-1, mod-2). For better or worse, I&amp;#8217;m in the habit of &amp;#8220;traveling&amp;#8221; through the workspace list using Ctrl-Alt-Up and Ctrl-Alt-Down (or Left and Right, if you prefer a horizontal feel for your workspaces). This is trivial to do in your ~/.i3/config:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
# Use mod-Control-Up and Down to rotate through the workspace list.&lt;br /&gt;
bindsym $mod+Control+Up workspace prev&lt;br /&gt;
bindsym $mod+Control+Down workspace next&lt;/p&gt;
&lt;p&gt;# Use mod-Shift-Control-Up and Down to move the selected window to an&lt;br /&gt;
# adjacent workspace. (This does *not* change your view to that workspace,&lt;br /&gt;
# it just "zaps" the window there.)&lt;br /&gt;
bindsym $mod+Shift+Control+Up move workspace prev&lt;br /&gt;
bindsym $mod+Shift+Control+Down move workspace next&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=7DE0DJBPkdY:8RynJ-XEwco:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=7DE0DJBPkdY:8RynJ-XEwco:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=7DE0DJBPkdY:8RynJ-XEwco:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=7DE0DJBPkdY:8RynJ-XEwco:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=7DE0DJBPkdY:8RynJ-XEwco:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/7DE0DJBPkdY" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/moving-through-i3-workspaces#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/moving-through-i3-workspaces/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/moving-through-i3-workspaces</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[Getting dnsmasq, virtual machines (libvirt), and vpn to inter-operate]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/xg4n61MgPe0/getting-dnsmasq-virtual-machines-libvirt-and-vpn-to-inter-operate" />
		<id>http://blog.bstpierre.org/?p=431</id>
		<updated>2012-05-14T15:22:17Z</updated>
		<published>2012-05-15T11:43:50Z</published>
		<category scheme="http://blog.bstpierre.org" term="network" /><category scheme="http://blog.bstpierre.org" term="dns" /><category scheme="http://blog.bstpierre.org" term="linux" /><category scheme="http://blog.bstpierre.org" term="virtual-machine" />		<summary type="html"><![CDATA[Fixing Dnsmasq to Work With Libvirt There&#8217;s a bug written in the Ubuntu tracker (and in Fedora too, I think) about running dnsmasq and libvirt at the same time. Basically, libvirt runs an instance of dnsmasq, and if you install the system dnsmasq it tries to bind to all interfaces by default. The &#8220;easy&#8221; workaround [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/getting-dnsmasq-virtual-machines-libvirt-and-vpn-to-inter-operate">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/getting-dnsmasq-virtual-machines-libvirt-and-vpn-to-inter-operate";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "Getting+dnsmasq%2C+virtual+machines+%28libvirt%29%2C+and+vpn+to+inter-operate";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;h2&gt;Fixing Dnsmasq to Work With Libvirt&lt;/h2&gt;
&lt;p&gt;There&amp;#8217;s &lt;a href="https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/231060"&gt;a bug written in the Ubuntu tracker&lt;/a&gt; (and in Fedora too, I think) about running dnsmasq and libvirt at the same time. Basically, libvirt runs an instance of dnsmasq, and if you install the system dnsmasq it tries to bind to all interfaces by default. The &amp;#8220;easy&amp;#8221; workaround is to use the interface and bind-interfaces configuration options in dnsmasq.conf. On my machine, I&amp;#8217;ve got:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
interface=eth0&lt;br /&gt;
interface=br0&lt;br /&gt;
bind-interfaces&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This makes it so that the system dnsmasq only listens on eth0 and br0, and does not bind to the wildcard address. Now you can run two instances of dnsmasq: the system instance, and libvirt&amp;#8217;s instance.&lt;/p&gt;
&lt;h2&gt;Getting The System Dnsmasq to Answer for the VMs&lt;/h2&gt;
&lt;p&gt;I wish I knew the answer for this: I&amp;#8217;d like for my system dnsmasq to respond to queries for &amp;#8220;fedora16&amp;#8243; and &amp;#8220;winxp&amp;#8221; (hostnames of two VMs I use). I tried a couple of things that didn&amp;#8217;t work, and settled for a subpar solution.&lt;/p&gt;
&lt;p&gt;First, I thought I might be able to use a fake domain &amp;#8220;.vm&amp;#8221; and tell the system dnsmasq to forward queries for that domain to libvirt&amp;#8217;s dnsmasq. This may be a workable solution; it didn&amp;#8217;t work when I tried it, but I was fighting other issues with libvirt at the time and I haven&amp;#8217;t had a chance to go back and try it again. The problem I ran into is that libvirt&amp;#8217;s dnsmasq was receiving queries for &amp;#8220;fedora16.vm&amp;#8221; but it didn&amp;#8217;t have &amp;#8220;.vm&amp;#8221; configured as a local domain. You can&amp;#8217;t monkey directly with libvirt&amp;#8217;s dnsmasq config (at least not that I saw), or this would be an easy fix. I tried changing the names assigned in the libvirt XML file dealing with DHCP names and addresses, but didn&amp;#8217;t get anywhere. Again, more experimentation here might win the day. (Definitely let me know if you know how to solve this.)&lt;/p&gt;
&lt;p&gt;I also flailed around with some other config options trying to get those names forwarded to libvirt&amp;#8217;s dnamasq but couldn&amp;#8217;t come up with anything clean.&lt;/p&gt;
&lt;p&gt;What I finally settled on is adding the names of the VMs to my local host file:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
# Virtual Machines; this should match up with the DHCP assignments in&lt;br /&gt;
# /etc/libvirt/qemu/networks/default.xml&lt;br /&gt;
192.168.122.22 fedora16.home.bstpierre.org fedora16&lt;br /&gt;
192.168.122.23 winxp1.home.bstpierre.org winxp1&lt;br /&gt;
# etc...&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This file is referenced by dnsmasq.conf via &lt;code&gt;addn-hosts=/etc/dnsmasq.hosts&lt;/code&gt;. It&amp;#8217;s not perfect, since I have to remember to enter the addresses in two places (default.xml and dnsmasq.hosts) when I create a new VM, but I don&amp;#8217;t do that often so it won&amp;#8217;t be a huge burden.&lt;/p&gt;
&lt;h2&gt;Getting Names from the VPN&lt;/h2&gt;
&lt;p&gt;When I connect to $DAYJOB VPN, I need to be able resolve names for that domain from the corporate (internal) DNS servers. Dnsmasq has a config option that allows you to tie a certain domain to a certain set of DNS servers:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
server=/example.com/172.18.1.1&lt;br /&gt;
server=/example.com/172.18.12.1&lt;br /&gt;
address=/vpnserver.example.com/169.254.123.210&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The first two lines set the DNS servers when I&amp;#8217;m on the VPN. The last line makes it so that I have the public address for the VPN server when I&amp;#8217;m not yet connected &amp;#8212; since the domain matches, dnsmasq will try to forward the request to the internal DNS servers, which is guaranteed not to work. This is slightly clumsy since the address is hardcoded, but it doesn&amp;#8217;t change in practice and I can always query it directly from upstream DNS (e.g. &lt;code&gt;dig vpnserver.example.com @192.168.1.1&lt;/code&gt; to get it from my router).&lt;/p&gt;
&lt;p&gt;Finally, I don&amp;#8217;t want to be making requests to those 172.18 addresses when I&amp;#8217;m not on the VPN, so I set up this interface definition in /etc/network/interfaces:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
iface tun0 inet manual&lt;br /&gt;
pre-up ip route delete 172.18.0.0/16 || true&lt;br /&gt;
pre-up service openvpn start || true&lt;br /&gt;
post-down service openvpn stop&lt;br /&gt;
post-down ip route add blackhole 172.18.0.0/16 || true&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;After the VPN is taken down, this will add a blackhole route for 172.18.0.0/16, which is where those DNS servers live. Just before the VPN is started, it removes the blackhole route so that I can get to those servers once the VPN is ready.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=xg4n61MgPe0:5CrEcL1qHAw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=xg4n61MgPe0:5CrEcL1qHAw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=xg4n61MgPe0:5CrEcL1qHAw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=xg4n61MgPe0:5CrEcL1qHAw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=xg4n61MgPe0:5CrEcL1qHAw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/xg4n61MgPe0" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/getting-dnsmasq-virtual-machines-libvirt-and-vpn-to-inter-operate#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/getting-dnsmasq-virtual-machines-libvirt-and-vpn-to-inter-operate/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/getting-dnsmasq-virtual-machines-libvirt-and-vpn-to-inter-operate</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[Controlling Audio with i3]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/joNeQKUGsJo/controlling-audio-with-i3" />
		<id>http://blog.bstpierre.org/?p=420</id>
		<updated>2012-05-10T14:00:45Z</updated>
		<published>2012-05-12T12:52:46Z</published>
		<category scheme="http://blog.bstpierre.org" term="linux" /><category scheme="http://blog.bstpierre.org" term="i3" /><category scheme="http://blog.bstpierre.org" term="tip" />		<summary type="html"><![CDATA[As I mentioned in the last post, I&#8217;ve switched to the i3 window manager. After fixing the Caps Lock key, the next order of business is getting the audio keys on my multimedia keyboard to control audio output. (It&#8217;s nice to be able to quickly mute or pause when the phone rings, for example.) This [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/controlling-audio-with-i3">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/controlling-audio-with-i3";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "Controlling+Audio+with+i3";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;As I mentioned in the &lt;a href="http://blog.bstpierre.org/making-caps-lock-an-additional-control-in-xwindows"&gt;last post&lt;/a&gt;, I&amp;#8217;ve switched to the i3 window manager. After fixing the Caps Lock key, the next order of business is getting the audio keys on my multimedia keyboard to control audio output. (It&amp;#8217;s nice to be able to quickly mute or pause when the phone rings, for example.)&lt;/p&gt;
&lt;p&gt;This turns out to be pretty easy. I used xev to figure out the keysyms for the audio keys, and then added bindings to ~/.i3/config:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
bindsym XF86AudioRaiseVolume exec pactl set-sink-volume 0 +5%&lt;br /&gt;
bindsym XF86AudioLowerVolume exec pactl set-sink-volume 0 -- -5%&lt;br /&gt;
bindsym XF86AudioMute exec ~/bin/toggle-mute&lt;br /&gt;
bindsym XF86AudioPlay exec clementine --play-pause&lt;br /&gt;
bindsym XF86AudioStop exec clementine --stop&lt;br /&gt;
bindsym XF86AudioPrev exec clementine --previous&lt;br /&gt;
bindsym XF86AudioNext exec clementine --next&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;As you can see, I prefer clementine as an audio player. If you have something different that you like, look up the command line method for controlling the player.&lt;/p&gt;
&lt;p&gt;The pactl command controls pulse audio. The toggle script is something I threw together because pactl doesn&amp;#8217;t support toggling the mute, you have to tell it mute or unmute:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
#!/bin/bash&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;toggle=$((pactl list sinks | grep -q Mute:.no &amp;amp;&amp;amp; echo 1) || echo 0)&lt;br /&gt;
pactl set-sink-mute 0 $toggle&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I only have one sink, so if you have more than one, you&amp;#8217;ll need to adjust the script.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=joNeQKUGsJo:Avxe9WD9iY4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=joNeQKUGsJo:Avxe9WD9iY4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=joNeQKUGsJo:Avxe9WD9iY4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=joNeQKUGsJo:Avxe9WD9iY4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=joNeQKUGsJo:Avxe9WD9iY4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/joNeQKUGsJo" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/controlling-audio-with-i3#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/controlling-audio-with-i3/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/controlling-audio-with-i3</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[Making Caps Lock an Additional Control in XWindows]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/iexshiDZpyA/making-caps-lock-an-additional-control-in-xwindows" />
		<id>http://blog.bstpierre.org/?p=416</id>
		<updated>2012-05-10T13:52:31Z</updated>
		<published>2012-05-11T11:49:20Z</published>
		<category scheme="http://blog.bstpierre.org" term="linux" /><category scheme="http://blog.bstpierre.org" term="i3" /><category scheme="http://blog.bstpierre.org" term="tip" />		<summary type="html"><![CDATA[Background: I just built a new computer, and &#8220;upgraded&#8221; to Ubuntu 12.04. I&#8217;ve been a fan of Ubuntu for a long time (first Debian, then Ubuntu because of the faster / more predictable release cycle). But you can add me to the list of people unimpressed with the &#8220;Unity&#8221; desktop environment, and not terribly impressed [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/making-caps-lock-an-additional-control-in-xwindows">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/making-caps-lock-an-additional-control-in-xwindows";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "Making+Caps+Lock+an+Additional+Control+in+XWindows";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;Background: I just built a new computer, and &amp;#8220;upgraded&amp;#8221; to Ubuntu 12.04. I&amp;#8217;ve been a fan of Ubuntu for a long time (first Debian, then Ubuntu because of the faster / more predictable release cycle). But you can add me to the list of people unimpressed with the &amp;#8220;Unity&amp;#8221; desktop environment, and not terribly impressed by Gnome 3. Since I&amp;#8217;m in the middle of an upgrade and learning about new features anyway, I figured I&amp;#8217;d make the leap to a better window manager. I&amp;#8217;ve settled on &lt;a title="i3 Window Manager" href="http://www.i3wm.org/"&gt;i3&lt;/a&gt;, which gives me a lot of power over how things are arranged. Of course it also means that I&amp;#8217;ve got to configure a bunch of stuff the way I want it, more so than with the default Gnome/Unity/Metacity scheme. This potentially means some short-ish posts here about tweaks &amp;#038; tips for working with i3.&lt;/p&gt;
&lt;p&gt;The first item of business is getting rid of Caps Lock. The example config in xmodmap(1) will &lt;em&gt;swap&lt;/em&gt; your caps lock and control, which is definitely not what I want. The key to the left of the &amp;#8220;A&amp;#8221; (which happens to be labeled Caps Lock) should be treated the same as the left Control key. So I created &lt;code&gt;~/.xmodmap&lt;/code&gt; with the following contents:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
!&lt;br /&gt;
! Make Caps_Lock an additional Control key&lt;br /&gt;
! (This is *DIFFERENT* than *swapping* Caps_Lock and Control, as described&lt;br /&gt;
! in the xmodmap(1) man page.)&lt;br /&gt;
!&lt;br /&gt;
keycode 66 = Control_L Control_L Control_L Control_L Control_L Control_L Control_L Control_L&lt;br /&gt;
clear lock&lt;br /&gt;
add Control = Control_L&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then, in your &lt;code&gt;~/.i3/config&lt;/code&gt; add:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
exec_always xmodmap ~/.xmodmap&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(Note that if you use the xmodmap commands provided in the xmodmap man page, then restarting i3 will &lt;em&gt;toggle&lt;/em&gt; that key between Caps_Lock and Control, which is probably not what you want! It seems that you also lose the swap if you do things like run xev.)&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=iexshiDZpyA:6oufFHR6wzc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=iexshiDZpyA:6oufFHR6wzc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=iexshiDZpyA:6oufFHR6wzc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=iexshiDZpyA:6oufFHR6wzc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=iexshiDZpyA:6oufFHR6wzc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/iexshiDZpyA" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/making-caps-lock-an-additional-control-in-xwindows#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/making-caps-lock-an-additional-control-in-xwindows/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/making-caps-lock-an-additional-control-in-xwindows</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[GTK3 Example Code]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/jfLjvA4mrqQ/gtk3-example-code" />
		<id>http://blog.bstpierre.org/?p=413</id>
		<updated>2012-05-06T03:34:46Z</updated>
		<published>2012-05-07T09:38:18Z</published>
		<category scheme="http://blog.bstpierre.org" term="user-interface" /><category scheme="http://blog.bstpierre.org" term="gtk" /><category scheme="http://blog.bstpierre.org" term="gui" /><category scheme="http://blog.bstpierre.org" term="tutorial" />		<summary type="html"><![CDATA[Over the past year or so I&#8217;ve been doing a fair bit of GUI programming &#8212; both in ${DAYJOB}s and otherwise. Until just recently most of my GUI experience has been with wxWidgets (and most of that via wxPython). Lately I&#8217;ve wandered to GTK. The documentation for both toolkits is pretty good. I&#8217;ve found GTK&#8217;s [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/gtk3-example-code">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/gtk3-example-code";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "GTK3+Example+Code";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;Over the past year or so I&amp;#8217;ve been doing a fair bit of GUI programming &amp;#8212; both in ${DAYJOB}s and otherwise. Until just recently most of my GUI experience has been with wxWidgets (and most of that via wxPython). Lately I&amp;#8217;ve wandered to GTK.&lt;/p&gt;
&lt;p&gt;The documentation for both toolkits is pretty good. I&amp;#8217;ve found GTK&amp;#8217;s API reference documentation to be very thorough and mostly well detailed. The tutorials are especially good for an experienced programmer who knows his way around a GUI and just needs to learn how the toolkit works.&lt;/p&gt;
&lt;p&gt;What I find lacking are a comprehensive set of tightly focused example programs. Take the &lt;a href="http://developer.gnome.org/gtkmm-tutorial/3.0/sec-clipboard-examples.html.en"&gt;clipboard example&lt;/a&gt; from gtkmm, for instance. It&amp;#8217;s supposed to be showing how to access the clipboard, but it&amp;#8217;s all cluttered up with irrelevant buttons and signals and stuff. Sure, it&amp;#8217;s not &lt;em&gt;that&lt;/em&gt; hard to read through the code to pick out the relevant pieces, but why not produce a simple example app that&amp;#8217;s &lt;em&gt;all&lt;/em&gt; relevant (or nearly all &amp;#8212; you can&amp;#8217;t avoid some of the boilerplate)?&lt;/p&gt;
&lt;p&gt;And some topics are not covered at all &amp;#8212; like accelerator groups, where the API documentation says &amp;#8220;you won&amp;#8217;t usually need these&amp;#8221;. But sometimes you &lt;em&gt;do&lt;/em&gt;, and then it&amp;#8217;s hard to find an example of correct usage. (Yes, I figured it out, and it didn&amp;#8217;t take too long using the API reference, but a 25-line example program would have saved me some time.)&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t misunderstand the point of this post: I&amp;#8217;m not complaining about the state of the documentation, which is better than the docs for 98.3% of FOSS projects. Instead I&amp;#8217;m proposing a collection of &lt;a href="https://github.com/bstpierre/gtk-examples"&gt;ultra-focused example programs&lt;/a&gt; for the breadth of the API. This will be a complement to the tutorials and reference docs.&lt;/p&gt;
&lt;p&gt;It will ideally be against multiple language bindings (though I&amp;#8217;ve found that an example in the C API is informative on how things should work in the Python or C++ binding, and vice versa). I&amp;#8217;ve already got a few examples (C only so far) in the GitHub repository, and if life doesn&amp;#8217;t get in the way, I&amp;#8217;ll be adding more on a regular basis. In my dreams, I&amp;#8217;ll post some of the examples here with more explanation, but we&amp;#8217;ll see how that goes&amp;#8230;&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;d like to contribute a tightly focused example on some GTK feature, send a pull request on GitHub. If you&amp;#8217;d like to &lt;em&gt;request&lt;/em&gt; an example, open an issue ticket there.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=jfLjvA4mrqQ:C4oDr_xpSv0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=jfLjvA4mrqQ:C4oDr_xpSv0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=jfLjvA4mrqQ:C4oDr_xpSv0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=jfLjvA4mrqQ:C4oDr_xpSv0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=jfLjvA4mrqQ:C4oDr_xpSv0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/jfLjvA4mrqQ" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/gtk3-example-code#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/gtk3-example-code/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/gtk3-example-code</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[User Interface Hall of Fame]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/W5o5P7HK34c/user-interface-hall-of-fame" />
		<id>http://blog.bstpierre.org/?p=409</id>
		<updated>2012-05-06T02:38:05Z</updated>
		<published>2012-05-06T02:38:05Z</published>
		<category scheme="http://blog.bstpierre.org" term="user-interface" />		<summary type="html"><![CDATA[A long, long time ago, I talked about a poor user interface. This is the follow-up &#8220;good user interface&#8221; post that I promised. I&#8217;d like to talk about Anki, which is a flashcard program. The user interface is well done for several reasons: It is uncluttered: in the main screen you are presented with the [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/user-interface-hall-of-fame">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/user-interface-hall-of-fame";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "User+Interface+Hall+of+Fame";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;A long, long time ago, I talked about a &lt;a title="User Interface Hall of Shame" href="http://blog.bstpierre.org/user-interface-hall-of-shame"&gt;poor user interface&lt;/a&gt;. This is the follow-up &amp;#8220;good user interface&amp;#8221; post that I promised.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d like to talk about Anki, which is a flashcard program. The user interface is well done for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is uncluttered: in the main screen you are presented with the flash card decks that you have downloaded. You can open a deck (i.e. to study the deck) by clicking the button right next to the deck. The number of cards that you have &amp;#8220;due&amp;#8221; to study today is shown right there.&lt;/li&gt;
&lt;li&gt;When you&amp;#8217;ve opened a deck, you are presented with the &amp;#8220;Study Options&amp;#8221; screen. At this point, the main thing you want to do is review your cards. Again, this is a big &amp;#8220;review&amp;#8221; button, and it is selected/highlighted by default so you can just press enter/spacebar to move into review mode.
&lt;ul&gt;
&lt;li&gt;(I will note that the Study Options screen might be overcomplicated. There are a number of options here, and some information presented that does not seem essential. I&amp;#8217;d say it&amp;#8217;s a minor fault that does not detract overall from the simplicity of this application.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When reviewing, you are presented with one &amp;#8220;face&amp;#8221; of a flashcard and a &amp;#8220;Show Answer&amp;#8221; button. Again the button is selected/highlighted by default so you can just press spacebar to see the answer.&lt;/li&gt;
&lt;li&gt;Once the answer is revealed, you click a button to say if you got the answer correct, and how easy it was for you to know the answer. So, for example, you&amp;#8217;re studying a French-&amp;gt;English deck, and the face of the card is &amp;#8220;non&amp;#8221;. Well, that&amp;#8217;s an easy one, it&amp;#8217;s &amp;#8220;no&amp;#8221;. So when asked, you press the Very Easy button. Or, in a nice interface touch, you press &amp;#8220;4&amp;#8243;, since the buttons are mapped to the first four number keys: &amp;#8220;Again&amp;#8221; (meaning incorrect) is 1, &amp;#8220;Good&amp;#8221; is 2, &amp;#8220;Easy&amp;#8221; is 3, and &amp;#8220;Very Easy&amp;#8221; is 4.
&lt;ul&gt;
&lt;li&gt;Because of the layout of the buttons, the UI can be driven very quickly and easily from the keyboard: see a card, say the answer, press space to show the answer with the thumb, press 1-4 with one of the fingers, and then the next card is shown.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Unobtrusive status information is shown in the bottom left statusbar. It shows the number of failed cards that you need to review, the number of cards awaiting review, and the number of new cards today. It also shows the amount of time that it expects you have remaining to study, based on your average time to answer each card and the number of cards remaining. And then there are small graphs that indicate by color and size whether you&amp;#8217;ve done well (green, &amp;gt;80% correct) or poorly (red, &amp;lt;50% correct).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anki also has a facility for editing cards, but I&amp;#8217;m not going to review that. The primary study feature is really the key piece of the application, and it deserves a spot in the UI Hall of Fame.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=W5o5P7HK34c:lQ4UtAHQg7Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=W5o5P7HK34c:lQ4UtAHQg7Q:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=W5o5P7HK34c:lQ4UtAHQg7Q:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=W5o5P7HK34c:lQ4UtAHQg7Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=W5o5P7HK34c:lQ4UtAHQg7Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/W5o5P7HK34c" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/user-interface-hall-of-fame#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/user-interface-hall-of-fame/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/user-interface-hall-of-fame</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[User Interface Hall of Shame]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/h0VKevdqU2E/user-interface-hall-of-shame" />
		<id>http://blog.bstpierre.org/?p=400</id>
		<updated>2012-02-21T17:09:50Z</updated>
		<published>2012-02-22T15:06:11Z</published>
		<category scheme="http://blog.bstpierre.org" term="user-interface" />		<summary type="html"><![CDATA[I&#8217;m taking MIT&#8217;s 6.831: User Interface Design and Implementation through their free OpenCourseWare website. One of the homework assignments is to find two examples each for the &#8220;UI Hall of Shame&#8221; and the &#8220;UI Hall of Fame&#8221;. This post is for shame &#8212; and since the nominee has so many things to discuss I&#8217;m only [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/user-interface-hall-of-shame">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/user-interface-hall-of-shame";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "User+Interface+Hall+of+Shame";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;I&amp;#8217;m taking &lt;a href="http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-831-user-interface-design-and-implementation-fall-2004/index.htm"&gt;MIT&amp;#8217;s 6.831: User Interface Design and Implementation&lt;/a&gt; through their free OpenCourseWare website. One of the homework assignments is to find two examples each for the &amp;#8220;UI Hall of Shame&amp;#8221; and the &amp;#8220;UI Hall of Fame&amp;#8221;. This post is for shame &amp;#8212; and since the nominee has so many things to discuss I&amp;#8217;m only doing one; I&amp;#8217;ll follow up with fame in another post.&lt;/p&gt;
&lt;p&gt;My nominee for the UI Hall of Shame is &lt;strong&gt;gmusicbrowser&lt;/strong&gt;, which has a number of UI problems. I used this app for a while last year because it has a couple of neat features that I liked, but I got frustrated by it (and it doesn&amp;#8217;t tie into my multimedia keyboard play/stop/forward keys), so I moved on to something else.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.bstpierre.org/wp-content/uploads/2012/02/Screenshot-gmusicbrowser.png"&gt;&lt;img class="aligncenter size-medium wp-image-401" title="gmusicbrowser screenshot" src="http://blog.bstpierre.org/wp-content/uploads/2012/02/Screenshot-gmusicbrowser-300x152.png" alt="Screenshot of gmusicbrowser for UI Hall of Shame." width="300" height="152" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A minor point, but the &amp;#8220;About&amp;#8221; dialog is not on the Help menu, it&amp;#8217;s on &amp;#8220;Main&amp;#8221; (which is nonstandard; it&amp;#8217;s where you&amp;#8217;d normally find a &amp;#8220;File&amp;#8221; menu).&lt;/li&gt;
&lt;li&gt;There isn&amp;#8217;t a &amp;#8220;Help&amp;#8221; menu.&lt;/li&gt;
&lt;li&gt;The two (three? four?) icons below the menu are confusing at best. None of the following behaviors are what you&amp;#8217;d expect, and not everything is consistent.
&lt;ul&gt;
&lt;li&gt;To the right of the icons is a pair of numbers, like &amp;#8220;4972/6158&amp;#8243;. This represents the sequence number of the playing song and the number of total songs in the currently displayed playlist. Nothing wrong with this &amp;#8212; but we&amp;#8217;ll come back to this in a minute.&lt;/li&gt;
&lt;li&gt;The first icon can be clicked to toggle between in-order and weighted-random modes. By right-clicking you can get a context menu to adjust the in-order mode (e.g. Artist/Album or Path/Track#). The selection for weighted-random mode is on a submenu of that same context menu.&lt;/li&gt;
&lt;li&gt;When you select a mode, that menu item gets a little indicator dot. It might be my desktop color scheme, but white-on-gray is hard to see with a dot that small. Firefox, for example, uses a checkmark which is easier to see even though it&amp;#8217;s still the same low contrast.&lt;/li&gt;
&lt;li&gt;Choosing a weighted-random mode changes the icon to dice.&lt;/li&gt;
&lt;li&gt;You can choose &amp;#8220;Shuffle&amp;#8221; from the menu, in which case the icon changes to playing cards.&lt;/li&gt;
&lt;li&gt;Clicking (left-click) on the dice or cards icon changes it back to the arrow icon and sets the mode to an in-order mode.&lt;/li&gt;
&lt;li&gt;Clicking on the arrow icon changes it to whichever random/shuffle mode was previously in use.&lt;/li&gt;
&lt;li&gt;The second icon starts as a book. I&amp;#8217;m not sure what this is supposed to mean. When you hover over it, it says &amp;#8220;Playlist Filter: All&amp;#8221;. Again you can right click for a context menu of filters to apply to the playlist, in which case the icon changes to a funnel. (And if a song is playing, it will abruptly change to whatever is first in the selected filter.)&lt;/li&gt;
&lt;li&gt;Clicking (left-click) on the book icon doesn&amp;#8217;t seem to do anything.&lt;/li&gt;
&lt;li&gt;Clicking on the funnel changes it back to a book (and the &amp;#8220;All&amp;#8221; filter?).&lt;/li&gt;
&lt;li&gt;Not that it would make much sense, but for consistency I&amp;#8217;d expect a left click on this icon to toggle between &amp;#8220;All&amp;#8221; and the last selected filter.&lt;/li&gt;
&lt;li&gt;Next to the book/funnel icon is a blank space&amp;#8230; that becomes an arrow/triangle (&amp;#8220;play button&amp;#8221;) icon when you hover, with the tooltip &amp;#8220;Queue empty&amp;#8221;. And when you move your mouse off the icon, it disappears.&lt;/li&gt;
&lt;li&gt;If you enqueue a song, that queue icon appears. And the pair of numbers mentioned above is replaced by the text &amp;#8220;1 song in queue&amp;#8221;. But the playlist doesn&amp;#8217;t change! If it&amp;#8217;s still got 50 songs, you&amp;#8217;re still listening to, say, 12/50.&lt;/li&gt;
&lt;li&gt;Clicking on the queue icon&amp;#8230; empties the queue! Which is very much not what you&amp;#8217;d expect. Of course, since the queue is empty, the icon disappears and we get back our &amp;#8220;NNN/XXX&amp;#8221; text mentioned in the first bullet above.&lt;/li&gt;
&lt;li&gt;Now let&amp;#8217;s say you&amp;#8217;ve got 5000 songs in your collection, but you&amp;#8217;re listening to a playlist that has 10 songs. You see, say, 2/10 in the indicator, and you&amp;#8217;ve got the funnel icon (not the book). Just for fun, you enqueue a song using the main browser window. After the current song is playing, your queued song will play &amp;#8212; and the funnel icon will switch to the book icon: your selected filter has been cancelled.&lt;/li&gt;
&lt;li&gt;There are more unpredictable behaviors buried in these icons, but &lt;strong&gt;what all of this boils down to&lt;/strong&gt; is that there are too many modes, they are not orthogonal, it&amp;#8217;s too easy to accidentally change from one mode to another, it&amp;#8217;s not easy to know what mode you&amp;#8217;re about to switch into, and it&amp;#8217;s &lt;em&gt;really&lt;/em&gt; easy to lose work &amp;#8212; by accidentally clearing a bunch of queued songs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Just below those icons are a mostly standard set of back/stop/play/forward icons&amp;#8230; and a volume control that is really hard to use. Clicking the volume icon pops up a slider that disappears as soon as you release the mouse button. If you hold down the mouse button, the slider stays displayed, but you can&amp;#8217;t move the slider thumb. Double clicking the icon (which I discovered accidentally) makes the slider stay, and then you can move the thumb &amp;#8212; as long as you don&amp;#8217;t accidentally move the pointer outside the slider, in which case it disappears again. Right clicking toggles mute, which isn&amp;#8217;t intuitive, but if you &lt;em&gt;really&lt;/em&gt; want to tie a behavior to right clicking on that icon, I suppose is reasonable. For mute, however, it&amp;#8217;s totally unusable: that icon is too small of a target, and when I want to mute, I&amp;#8217;m usually trying to do it somewhat quickly &amp;#8212; so I can answer a ringing phone, for example. The mute button on my &amp;#8220;multimedia&amp;#8221; keyboard is a much easier target to hit quickly.&lt;/li&gt;
&lt;li&gt;The main browser window is a mystery to me. Starting at the top, there are two tabs: Library and Context. The only thing in the Context tab is a checkbox for &amp;#8220;Follow Playing Song&amp;#8221;; I&amp;#8217;m not really sure what this does. Assuming it does something meaningful, it would make much more sense to put this on a menu somewhere.&lt;/li&gt;
&lt;li&gt;The Library tab is where you can browse your music library. There are three listboxes at the top of the window, each with the same set of tabs. Those tabs change the listbox contents so you can choose various filters. Selecting a filter in the leftmost box (e.g. clicking on an album name after you&amp;#8217;ve clicked the Album tab in that box) filters the contents of the left two listboxes. In this way you can drill down by choosing up to three filters. E.g. &amp;#8220;Rock&amp;#8221; in the left list from the Genre tab, then 1988 in the middle list from the Date tab, then Money for Nothing in the right list from the Album tab. This is kind of a clumsy approach to filtering, but in practice you don&amp;#8217;t need more than three filter selections to narrow even a large library significantly. The filters are a clumsy but reasonable approach. The difficulties start with the bells and whistles. You can right click on any of the three listboxes for a context menu.
&lt;ul&gt;
&lt;li&gt;There&amp;#8217;s no other way to access the features in the context menu except by right clicking on the list. But right clicking on the list selects the list item where you clicked &amp;#8212; a minor annoyance.&lt;/li&gt;
&lt;li&gt;One of the menu options is &amp;#8220;Show Buttons&amp;#8221;, which makes a toolbar appear below the listbox. Seriously? Why not just show the toolbar all the time?&lt;/li&gt;
&lt;li&gt;A minor point: one of the buttons is a broom icon for &amp;#8220;Clear Selection&amp;#8221;. When you click this, the selected item in the listbox above is deactivated. But the item is still selected. The selection should instead be removed.&lt;/li&gt;
&lt;li&gt;The buttons that are displayed depend on which tab is selected. This is nonstandard: normally you &lt;em&gt;disable&lt;/em&gt; a button instead of hiding it if the functionality is unavailable for the current mode.&lt;/li&gt;
&lt;li&gt;There&amp;#8217;s an &amp;#8220;Intersection Mode&amp;#8221; toggle button. I haven&amp;#8217;t been able to figure out what this does; nothing meaningful as far as I can tell.&lt;/li&gt;
&lt;li&gt;There&amp;#8217;s an &amp;#8220;Options&amp;#8221; button that displays a menu of display options.&lt;/li&gt;
&lt;li&gt;There are a confusing array of display options, all of which depend on the currently selected filter tab. When looking at the Date tab, for example, you can choose between a standard list or &amp;#8220;cloud&amp;#8221; mode. (I&amp;#8217;ll admit that having cloud mode available is kind of nice &amp;#8212; I can see 30+ years all at once instead of having to scroll.) If I switch to the Album tab, there are many more choices: six different sort modes; optionally displaying year, song count and running length of each album; five choices for showing album pictures and size to show; and the choice of cloud or &amp;#8220;mosaic&amp;#8221; mode. Mosaic mode is like &amp;#8220;Icon View&amp;#8221; in Nautilus &amp;#8212; albums are listed left-to-right with art shown where present and text where no image is available.&lt;/li&gt;
&lt;li&gt;I won&amp;#8217;t get into all of the behavior here, but the bottom line is: &lt;strong&gt;too many modes&lt;/strong&gt;, which are not orthogonal, and your options disappear depending on mode &amp;#8212; without having a clear path to getting back to the option you were using.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Just below the listboxes (and optionally the listbox-specific toolbars) is another toolbar with a filtering control, a few buttons, and some menus. The menus don&amp;#8217;t belong here: they belong in the app&amp;#8217;s main menu bar.&lt;/li&gt;
&lt;li&gt;The &amp;#8220;Saved List&amp;#8221; feature is completely unusable. There&amp;#8217;s a menu option &amp;#8220;Save current list as&amp;#8221; that can only be found on the Saved tab in the filter listboxes &amp;#8212; but you have to be careful to click on the &amp;#8220;Saved Lists&amp;#8221; item in that list, because it&amp;#8217;s the only place you can right click that won&amp;#8217;t alter the filter contents displayed in the main window. I don&amp;#8217;t know if the feature is buggy or what, but clicking on a saved list doesn&amp;#8217;t consistently display the contents of that list.&lt;/li&gt;
&lt;li&gt;Overall, I&amp;#8217;d put it down to a bad case of featuritis. I don&amp;#8217;t think there&amp;#8217;s a widget that hasn&amp;#8217;t been used in the UI, things are in nonstandard places, features are hidden in context menus, and there are way too many unexpected behaviors.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If I were going to implement a similar music player with advanced, highly flexible filtering; playlist construction; an ad-hoc queue; and flexible playback sequencing (e.g. in-order with various sorts, or weighted random according to various criteria) I would:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make three explicit playback modes: queue, filter, or playlist. You can edit any object regardless of which is playing, but, for example, changes made to the queue don&amp;#8217;t affect playback in playlist mode. This makes it easier for the user to figure out what he&amp;#8217;s currently working with &amp;#8212; and would actually enable new features like &amp;#8220;save current queue to playlist&amp;#8221;.&lt;/li&gt;
&lt;li&gt;Similarly make three explicit editor/browser modes. You&amp;#8217;re editing a &lt;em&gt;specific&lt;/em&gt; (i.e. named) filter or playlist, or you&amp;#8217;re modifying the queue.&lt;/li&gt;
&lt;li&gt;The player and the browser/editor would be distinct. Changes in the browser don&amp;#8217;t implicitly change what&amp;#8217;s happening in the player (except for the queue &amp;#8212; which you expect to make fluid changes to the player). If you&amp;#8217;re editing the actively playing playlist, you have to explicitly &lt;em&gt;save&lt;/em&gt; your changes to the playlist for them to take effect. There are no editing controls in the player (e.g. moving songs up and down in the list).&lt;/li&gt;
&lt;li&gt;Retain some of the context menus where they apply to the selected object (e.g. &amp;#8220;Song Properties&amp;#8221; when you click on a song in a list), but I would move many options into the main menu.&lt;/li&gt;
&lt;li&gt;Use a more familiar UI for building filters. Something like what you see in the &amp;#8220;Rules&amp;#8221; window for email clients, for example &amp;#8212; AND/OR selections along with different filter rules. This would let the user build filters just as complex as gmusicbrowser allows but easier to navigate (in fact, gmusicbrowser has a window with this sort of interface).&lt;/li&gt;
&lt;li&gt;Retain (and expand) the status information: song index, total song count, total play time, remaining play time, etc. Probably in a status bar, but possibly in the header of the player.&lt;/li&gt;
&lt;li&gt;I didn&amp;#8217;t mention it above, but I&amp;#8217;d retain the awesome bulk modify feature with some tweaks for usability. (Feature is cool, usability in gmusicbrowser is fair to poor.) This feature allows you, for example, to rename a whole batch of files according to a template, e.g. &amp;#8220;&amp;lt;ALBUM&amp;gt; &amp;#8211; &amp;lt;TRACK#&amp;gt; &amp;#8211; &amp;lt;TITLE&amp;gt;.mp3&amp;#8243;. It also allows you to make bulk changes to the ID3 tags on a bunch of files all at once.&lt;/li&gt;
&lt;li&gt;Integrate with mmkeys.&lt;/li&gt;
&lt;li&gt;Minimize to the tray, and possibly have a shrunken player window that just shows a standard set of stop/play/pause/forward/backward icons, title, etc &amp;#8212; instead of needing a big library browser and/or playlist window open all the time.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=h0VKevdqU2E:uk9XJYBurIU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=h0VKevdqU2E:uk9XJYBurIU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=h0VKevdqU2E:uk9XJYBurIU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=h0VKevdqU2E:uk9XJYBurIU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=h0VKevdqU2E:uk9XJYBurIU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/h0VKevdqU2E" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/user-interface-hall-of-shame#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/user-interface-hall-of-shame/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/user-interface-hall-of-shame</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[Maintaining &#8220;Privacy&#8221; Under the New Google Privacy Policy]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/QxP3Pw-fcLs/maintaining-privacy-new-google-policy" />
		<id>http://blog.bstpierre.org/?p=388</id>
		<updated>2012-02-02T19:39:39Z</updated>
		<published>2012-02-03T02:59:01Z</published>
		<category scheme="http://blog.bstpierre.org" term="security" />		<summary type="html"><![CDATA[I put &#8220;privacy&#8221; in quotes, because under the scheme below you&#8217;re still giving up a lot of data, but you can (I think) still maintain &#8220;silos&#8221; of data so that, for example, your search data isn&#8217;t correlated with your YouTube or GMail data. See What Actually Changed in Google’s Privacy Policy from the EFF for [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/maintaining-privacy-new-google-policy">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/maintaining-privacy-new-google-policy";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "Maintaining+%26%238220%3BPrivacy%26%238221%3B+Under+the+New+Google+Privacy+Policy";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;I put &amp;#8220;privacy&amp;#8221; in quotes, because under the scheme below you&amp;#8217;re still giving up a lot of data, but you can (I think) still maintain &amp;#8220;silos&amp;#8221; of data so that, for example, your search data isn&amp;#8217;t correlated with your YouTube or GMail data.&lt;/p&gt;
&lt;p&gt;See &lt;a href="https://www.eff.org/deeplinks/2012/02/what-actually-changed-google%27s-privacy-policy"&gt;What Actually Changed in Google’s Privacy Policy&lt;/a&gt; from the EFF for a good description of the substantive changes in Google&amp;#8217;s new privacy policy.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what I&amp;#8217;m doing to try to preserve some of my data in silos. &lt;em&gt;This is based on my understanding of the way the new privacy policy works, which could be faulty. Remember that you&amp;#8217;re still giving up your data by using these services.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In Firefox, I&amp;#8217;ve installed &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/bing/"&gt;Bing&lt;/a&gt; as a search engine, and I use it as the default. I&amp;#8217;ve been using this for a couple of weeks now, and it doesn&amp;#8217;t suck. As far as I can tell, it&amp;#8217;s on par with the results I used to get through Google. &lt;em&gt;This keeps your search data away from Google.&lt;/em&gt; I don&amp;#8217;t (knowingly) share anything else with Microsoft (my house is all-Linux), so this keeps my search data in a silo.&lt;/li&gt;
&lt;li&gt;In Firefox, I&amp;#8217;ve installed &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/ghostery/"&gt;Ghostery&lt;/a&gt;. This blocks all kinds of trackers, &lt;em&gt;including Google Analytics&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;I&amp;#8217;ve switched from using the GMail web UI to a desktop client. Google still sees all my email, but I don&amp;#8217;t have to remain logged in to that account in the browser. (See #4.) &lt;em&gt;This effectively makes the mail account a silo; none of the data is used elsewhere.&lt;/em&gt; I occasionally have the fantasy that I&amp;#8217;m going to move my domain off Google Apps and go back to self-hosting, but that&amp;#8217;s unlikely to happen in the near future.&lt;/li&gt;
&lt;li&gt;When I&amp;#8217;m browsing, I&amp;#8217;m logged into a second Google account that is disconnected from my primary mail account. (See #3.) This means that, for example, videos that I watch on YouTube aren&amp;#8217;t correlated to the content of my mail.&lt;/li&gt;
&lt;li&gt;In Firefox, I&amp;#8217;ve installed &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/adblock-plus/"&gt;Adblock Plus&lt;/a&gt;. &lt;em&gt;This cuts down on &lt;strong&gt;tons&lt;/strong&gt; of ads; which might avoid leaking your data to advertisers.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;I haven&amp;#8217;t done it yet, but I plan to find a desktop RSS reader that doesn&amp;#8217;t suck and delete everything from Google Reader.&lt;/li&gt;
&lt;li&gt;I&amp;#8217;ve stopped checking in at Google News. Instead I pick one of CNN, News360, BBC, or other news outlet.&lt;/li&gt;
&lt;li&gt;I&amp;#8217;m not sure what it would be, but if I&amp;#8217;m browsing stuff that I don&amp;#8217;t want tracked, I&amp;#8217;ll fire up a Chrome Incognito session and proxy everything through Tor. (The only reason for using Chrome is that I typically don&amp;#8217;t want to interrupt a Firefox session to drop into Private Browsing mode there.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;#8217;sworth noting that I don&amp;#8217;t use G+, so I&amp;#8217;m not doing anything specific to maintain a silo there.&lt;/p&gt;
&lt;p&gt;As noted above, most of this doesn&amp;#8217;t vastly enhance your privacy. You&amp;#8217;re still handing out a lot of data every time you browse the web; it&amp;#8217;s a fact of life. And it is, after all, very convenient to have access to your search history &amp;#8212; I often find myself trying to figure out what that thing was that I found during a search a couple of weeks ago but can&amp;#8217;t remember the terms I used. But I&amp;#8217;m hoping that it cuts down on the amount of data correlation between my various online activities.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=QxP3Pw-fcLs:jXSuORVag1I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=QxP3Pw-fcLs:jXSuORVag1I:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=QxP3Pw-fcLs:jXSuORVag1I:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=QxP3Pw-fcLs:jXSuORVag1I:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=QxP3Pw-fcLs:jXSuORVag1I:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/QxP3Pw-fcLs" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/maintaining-privacy-new-google-policy#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/maintaining-privacy-new-google-policy/feed/atom" thr:count="1" />
		<thr:total>1</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/maintaining-privacy-new-google-policy</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[Turning Photos to a DVD Slideshow]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/EgeoBqBVORM/photos-to-dvd-slideshow" />
		<id>http://blog.bstpierre.org/?p=385</id>
		<updated>2012-05-06T02:37:53Z</updated>
		<published>2012-01-24T15:36:00Z</published>
		<category scheme="http://blog.bstpierre.org" term="linux" />		<summary type="html"><![CDATA[The task: take a bunch of photos from my digital camera and burn them to a DVD that would play the photos as a slideshow in any DVD player. (Actually, the task was to figure out how to do this in the simplest possible way, and make a set of instructions for an unsophisticated user [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/photos-to-dvd-slideshow">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/photos-to-dvd-slideshow";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "Turning+Photos+to+a+DVD+Slideshow";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;The task: take a bunch of photos from my digital camera and burn them to a DVD that would play the photos as a slideshow in any DVD player. (Actually, the task was to figure out how to do this in the simplest possible way, and make a set of instructions for an unsophisticated user to follow.)&lt;/p&gt;
&lt;p&gt;The result: several hours of fighting with a dozen different applications before I actually had photos displayed on my TV. And this post.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t understand why what seems like a fairly simple task is so complicated.&lt;/p&gt;
&lt;p&gt;This is what I found to be the easiest recipe on a stock Ubuntu 11.10 installation. Fair warning: this is quick &amp;amp; dirty, you don&amp;#8217;t get special effects, you don&amp;#8217;t get music, etc.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Required software (load through the software center, or via apt-get): imagination, devede, brasero.&lt;/li&gt;
&lt;li&gt;Open Imagination. Click the import photos icon (it is a terrible choice of icon &amp;#8212; there&amp;#8217;s no clue that you should want to click on the black square to import photos) and choose your photos.&lt;/li&gt;
&lt;li&gt;Export video. Choose DVD for output; to keep it organized, drop the video file in the Videos directory in your home directory. This can take a while if you have a slow computer and/or a lot of photos.&lt;/li&gt;
&lt;li&gt;Open DeVeDe. Configure the title. Import the video you just generated.&lt;/li&gt;
&lt;li&gt;Generate the DVD ISO image; again save the image to your Videos folder.&lt;/li&gt;
&lt;li&gt;Insert a DVD in the drive. Open your Videos folder. Right click on the ISO image and choose Write to Disc.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Some notes, in no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you want to tweak the slideshow, imagination will let you play around with transitions, slide duration, etc.&lt;/li&gt;
&lt;li&gt;If you want to import video clips, use Openshot instead of Imagination. It&amp;#8217;s harder to use (and overkill) compared to Imagination if all you want to do is produce a static photo slideshow. But if you want to do any video editing, it&amp;#8217;s a good combination of power and ease of use.&lt;/li&gt;
&lt;li&gt;If you want music, Openshot might also be your best bet. I didn&amp;#8217;t look at adding music via Imagination or DeVeDe.&lt;/li&gt;
&lt;li&gt;Don&amp;#8217;t try to use the Brasero application directly. I experienced crashes/lockups while using it, but it worked well when all I did was right click the ISO and choose Write to Disc. (It&amp;#8217;s also an ugly, hard to use piece of junk.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Things I tried and rejected:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;K3b: After Brasero failed miserably twice, I tried K3b. Rejected it in favor of not pulling in a bunch of KDE infrastructure that I wasn&amp;#8217;t using anyway, and also in favor of the simplicity of just directly burning the file without having to explicitly open a separate app.&lt;/li&gt;
&lt;li&gt;dvd-slideshow: This command line app does appeal to my inner geek, but I can&amp;#8217;t recommend it for users who want a GUI. (Even the inner geek appeal isn&amp;#8217;t enough to make me want to use it when the combination outlined above works well.)&lt;/li&gt;
&lt;li&gt;Mistelix: As good as Imagination, and I would have selected it if I had quickly found a way to rotate a photo from within Mistelix. Photos that showed up auto-rotated in other apps showed up sideways in Mistelix and I didn&amp;#8217;t see an obvious rotate button. Imagination did the right thing.&lt;/li&gt;
&lt;li&gt;Bombono: Junk. Don&amp;#8217;t bother with it. I opened it, saw that the tabs were overlapping the menus, couldn&amp;#8217;t figure out how to import any photos, and purged it from my system.&lt;/li&gt;
&lt;li&gt;Videoporama: Development is dead. It wasn&amp;#8217;t immediately obvious that it was going to be easy to use for the simple task of creating a DVD from a set of photos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The software stack above would be 10x better if Imagination implemented a feature to export a DVD ISO. It would be 100x better if it had a &amp;#8220;Burn DVD&amp;#8221; button that spit out a shiny disc that I could drop into a DVD player.&lt;/p&gt;
&lt;p&gt;(To be fair, the whole video situation is 1000x easier than it was 5 or 6 years ago when I tried to do something similar, realized how much work it was going to be, and walked away in frustration. The tools have come a long way.)&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=EgeoBqBVORM:am1LEUOrJH0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=EgeoBqBVORM:am1LEUOrJH0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=EgeoBqBVORM:am1LEUOrJH0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=EgeoBqBVORM:am1LEUOrJH0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=EgeoBqBVORM:am1LEUOrJH0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/EgeoBqBVORM" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/photos-to-dvd-slideshow#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/photos-to-dvd-slideshow/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/photos-to-dvd-slideshow</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Brian St. Pierre</name>
						<uri>http://blog.bstpierre.org</uri>
					</author>
		<title type="html"><![CDATA[Tightening UFW Firewall Rules to Limit SSH Access]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TheDailyBuild/~3/DHoxFYpkd9s/ufw-firewall-limit-ssh" />
		<id>http://blog.bstpierre.org/?p=371</id>
		<updated>2011-12-08T13:55:21Z</updated>
		<published>2011-12-08T23:54:21Z</published>
		<category scheme="http://blog.bstpierre.org" term="linux" /><category scheme="http://blog.bstpierre.org" term="security" /><category scheme="http://blog.bstpierre.org" term="firewall" /><category scheme="http://blog.bstpierre.org" term="ssh" />		<summary type="html"><![CDATA[The auth.log on one of my servers (really, on all of the servers I have access to) is full of stuff like this: Dec 8 03:19:33 localhost sshd[4718]: User root from 10.1.2.3 not allowed [...] Dec 8 03:19:35 localhost sshd[4721]: Invalid user db2inst1 from 10.1.2.3 Dec 8 03:19:38 localhost sshd[4723]: User root from 10.1.2.3 not [...]]]></summary>
		<content type="html" xml:base="http://blog.bstpierre.org/ufw-firewall-limit-ssh">&lt;div style="float: right; width: 42px; padding-right: 10px; margin: 0 0 0 10px;"&gt;
		&lt;script type="text/javascript"&gt;
		&lt;!--
		digg_url = "http://blog.bstpierre.org/ufw-firewall-limit-ssh";
		digg_bgcolor = "#FFFFFF";
		digg_skin = "";
		digg_window = "";
		digg_title = "Tightening+UFW+Firewall+Rules+to+Limit+SSH+Access";
		digg_media = "news";
		digg_topic = "";
		digg_bodytext = "";
		//--&gt;
		&lt;/script&gt;
		&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;&lt;/div&gt;&lt;p&gt;The auth.log on one of my servers (really, on &lt;em&gt;all&lt;/em&gt; of the servers I have access to) is full of stuff like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Dec  8 03:19:33 localhost sshd[4718]: User root from 10.1.2.3 not allowed [...]
Dec  8 03:19:35 localhost sshd[4721]: Invalid user db2inst1 from 10.1.2.3
Dec  8 03:19:38 localhost sshd[4723]: User root from 10.1.2.3 not allowed [...]&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;fail2ban is configured to (temporarily) block these after a certain number of attempts, but they keep coming back. One particular IP address was hitting ssh constantly (except for the ban periods) for several days, so I added a rule to drop everything from that address &amp;#8212; but this strategy isn&amp;#8217;t scalable.&lt;/p&gt;
&lt;p&gt;The simple, obvious solution is to only allow access from known hosts. It would be very rare that I need to access this server from anywhere except a small number of addresses. I started with a ufw (Ubuntu&amp;#8217;s &amp;#8220;uncomplicated firewall&amp;#8221;) ruleset like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;% sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
Anywhere                   DENY        10.1.2.3
Anywhere                   DENY        172.16.99.88
22                         ALLOW       Anywhere&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;To avoid getting locked out, I added (temporarily) a crontab entry for root:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*/15 * * * * /usr/sbin/ufw allow ssh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will allow access to ssh from any un-banned IP address (the current policy) every 15 minutes. Then I inserted a rule that allows access to ssh from my home ISPs netblock. (You can figure out the netblock by doing a whois lookup on your external IP address; you may need to add multiple netblocks if your ISP has several allocated. Be careful: it&amp;#8217;s no fun to get locked out!) This action is safe because I have not yet removed global ssh access. Note that I&amp;#8217;m using &amp;#8220;insert 3&amp;#8243; to add this rule at a specific position in the list.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo ufw insert 3 allow proto tcp from 10.9.8.0/18 to any port 22&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And I added a rule to permit access from another server with a fixed IP I have access to (for the rare case where I need to access this server when I&amp;#8217;m not at home):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo ufw insert 3 allow proto tcp from 172.17.101.102 to any port 22&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now my ruleset looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Status: active

To                         Action      From
--                         ------      ----
Anywhere                   DENY        10.1.2.3
Anywhere                   DENY        172.16.99.88
22/tcp                     ALLOW       172.17.101.102
22/tcp                     ALLOW       10.9.8.0/18
22                         ALLOW       Anywhere
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far, so good, but ssh access is still permitted from anywhere &amp;#8212; because of that last rule. This is the dangerous part&amp;#8230; you could get locked out if you haven&amp;#8217;t set the rules correctly. (You set up that crontab entry, right?)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo ufw delete allow ssh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait for the prompt&amp;#8230; hooray, I&amp;#8217;m still connected! After checking that I can access ssh from home and the other server, I know it&amp;#8217;s safe to remove the crontab job. (If the cron job has already fired, you&amp;#8217;ll need to rerun the &lt;code&gt;ufw delete allow ssh&lt;/code&gt; command.)&lt;/p&gt;
&lt;p&gt;At this point I can delete the first two rules that ban specific IPs, since they&amp;#8217;re outside my netblock and won&amp;#8217;t be allowed anyway.&lt;/p&gt;
&lt;p&gt;Now I can enjoy quieter logs without all those access attempts from China and Croatia!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=DHoxFYpkd9s:xEAhITxV6TE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=DHoxFYpkd9s:xEAhITxV6TE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=DHoxFYpkd9s:xEAhITxV6TE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TheDailyBuild?a=DHoxFYpkd9s:xEAhITxV6TE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TheDailyBuild?i=DHoxFYpkd9s:xEAhITxV6TE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheDailyBuild/~4/DHoxFYpkd9s" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://blog.bstpierre.org/ufw-firewall-limit-ssh#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://blog.bstpierre.org/ufw-firewall-limit-ssh/feed/atom" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://blog.bstpierre.org/ufw-firewall-limit-ssh</feedburner:origLink></entry>
	</feed>

