Sunday, March 25, 2012

LightDM: Switch user from the command line

Say you're on Ubuntu 11.10 or later, or any other distribution that uses LightDM. What would you do to go back to the greeter window where you can choose another user without logging out? In most other shells, there is a graphical option for it. In StumpWM you can use the dm-tool utility:
dm-tool switch-to-greeter

Friday, March 23, 2012

PPTP from Command Line

Although this blog is supposed to be about StumpWM, there are things unrelated to the window manager that one needs to do in order to make the transition easier. Since the network manager applet is not available in StumpWM (unless you use a systray program like trayer), you need to know how to do certain tasks without it.

I'm comfortable configuring my network from command line. There was one thing though that I had always done using Network Manager applet; setting up pptp. I googled for it and quickly found this which explains how I can use pptp from the command line.

First you create a file in /etc/ppp/peers. Name the file whatever you want, like myvpn. Put this inside that file:

remotename myvpn
linkname myvpn
ipparam myvpn
pty "pptp <host> --nolaunchpppd "
name <username>
usepeerdns
require-mppe
refuse-eap
noauth

# adopt defaults from the pptp-linux package
file /etc/ppp/options.pptp
Fix the host name and the user name accordingly. Then add a line like this to /etc/ppp/chap-secrets:

<username> myvpn <password> *

Again obviously you need to put your own username and password plus the correct connection name.

I have also created two scripts in /etc/ppp/ip-up.d/ and /etc/ppp/ip-down.d/ to set up the default gateway properly. These scripts are tailored for my own system and you might need to adapt them. the one in ip-up.d/ removes the current default gateway and adds a new one. The other one reverses this.

/etc/ppp/ip-up.d/myvpn:
#!/bin/bash

if [[ $PPP_LOCAL = 192.168.2.* ]]; then
    route del default gw 192.168.1.1
    route add default gw 192.168.2.100
fi
/etc/ppp/ip-down.d/myvpn:
#!/bin/bash

if [[ $PPP_LOCAL = 192.168.2.* ]]; then
    route add default gw 192.168.1.1
    route del default gw 192.168.2.100
fi
Don't forget to make the scripts executable. Also notice that ip-up.d/ and ip-down.d/ are only available in Debian and its derivatives (to learn more about the arguments passed to them and the available environment variables, see the Debian /etc/ppp/ip-up and /etc/ppp/ip-down scripts). Other distros use slightly different paths.

Sunday, March 18, 2012

urxvt: looking better and with tabs

urxvt is a great terminal emulator, but I don't particularly care for it's default look and feel. It's not very difficult to make it look better though.

This page explains how you can make urxvt look like gnome-terminal by adding a few lines to your .Xdefaults file. This is how my .Xdefaults looks like:
URxvt*background: #000000
URxvt*foreground: #00ff00
! black
URxvt.color0  : #000000
URxvt.color8  : #555555
! red
URxvt.color1  : #AA0000
URxvt.color9  : #FF5555
! green
URxvt.color2  : #00AA00
URxvt.color10 : #55FF55
! yellow
URxvt.color3  : #AA5500
URxvt.color11 : #FFFF55
! blue
URxvt.color4  : #0000AA
URxvt.color12 : #5555FF
! magenta
URxvt.color5  : #AA00AA
URxvt.color13 : #FF55FF
! cyan
URxvt.color6  : #00AAAA
URxvt.color14 : #55FFFF
! white
URxvt.color7  : #AAAAAA
URxvt.color15 : #FFFFFF

URxvt*font: xft:Monospace:pixelsize=18

URxvt*letterSpace: -1

URxvt.perl-ext-common : default,matcher
URxvt.urlLauncher     : firefox
URxvt.matcher.button  : 1


! scrollbar style - rxvt (default), plain (most compact), next, or xterm
URxvt.scrollstyle: plain

URxvt.perl-ext-common:  default,tabbed
Also, if you like to have tabs, you can run urxvt like urxvt -pe tabbed, or you can add this line to your .Xdefaults.
URxvt.perl-ext-common:  default,tabbed
 In order to open a new tab, press C-M-Down (that is, control and alt and down arrow). To switch tabs use C-M-Left and C-M-Right. To move the current tab, use C-Left and C-Right. I wish I could change these key bindings since the arrow keys are two far away from my comfort zone, but I haven't find a way to do that, yet. Well, nothing is perfect!

For more urxvt customizations, see this page.

By the way, this is the commands I've put in my .stumpwmrc in order to have urxvt as my default terminal emulator. Notice that the class attribute is URxvt not Urxvt as one might expect.
(defcommand urxvt () ()
  "Start a urxvt instance or switch to it if already running"
  (run-or-raise "urxvt" '(:class "URxvt")))
(define-key *root-map* (kbd "c") "urxvt")
(define-key *root-map* (kbd "C-c") "urxvt")
 If you're ever in doubt about the class attribute of a certain window, just switch to it, press C-t : and then type in (stumpwm::window-class (stumpwm::current-window)).

Saturday, March 17, 2012

Making Firefox keyboard friendly

If you're using StumpWM, chances are you don't like to use "the rat" a lot. There is also a good chance that you're an avid emacs user and while typing in Firefox you frequently try pressing C-a to go the beginning of the line and instead have everything selected. No worries! Firefox extensions are, as always, to the rescue.

Mouseless Browsing is a Firefox extension that helps you keep your hands on the keyboard by adding small numeric tags to (almost) everything clickable. Instead of clicking those, you can simply type in the numbers. If you want to open a link in a new tab, just press Alt while typing. If you're in a text area and don't want the numbers ended up in there, hold Ctrl while typing. There are a few other shortcuts too, all configurable in the extension preferences. Another useful option is to have the have the tags hidden by default (they sometimes makes a mess of some pages) and instead have them shown when you press a certain shortcut key.

Firemacs is another helpful extension; one that emacs users will love. It simply changes many of the Firefox's key bindings to things emacs users are more accustomed to (C-a instead of Home, C-f instead of right arrow and so on). You might want to disable making ESC work as Meta (that is, Alt) key. While the trusty C-g works most of the time, there are certain situations (like in menus) that you have to use ESC.

Again, Firefox's extensions are keeping me tightly where I am, stopping me from switching to other browsers. Damn you Firefox, you're locking me in!

Controlling VLC

After fixing the issue of volume control, now I wanted to be able to use my multimedia keys to play/pause VLC. To do that, I used VLC telnet interface and telnetlib which is a very useful library almost equivalent to the Python library of the same name. Of course, I finally learned that I can use VLC's global hotkeys to achieve this, without the problems I encountered, but I'm gonna post what I came up with just for future reference.

Using telnetlib is very straightforward. The code is pretty self-explanatory.
;; vlc control. vlc telnet interface should be enabled.
(defcommand vlc-play () ()
  "start/resume vlc playback"
  (telnetlib:with-telnet-session (tn "localhost" 4212)
    (telnetlib:read-until tn "Password: ")
    (telnetlib:write-ln tn "admin")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "play")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "quit")))

(defcommand vlc-pause () ()
  "pause vlc playback"
  (telnetlib:with-telnet-session (tn "localhost" 4212)
    (telnetlib:read-until tn "Password: ")
    (telnetlib:write-ln tn "admin")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "pause")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "quit")))
Obviously, VLC's telnet interface should be active. I found no way to find out if playback is paused in VLC or not. There are two commands that looked like they should help, but they don't. Telnet command is_playing only returns 0 if playback is stopped, not paused. status command for some reason always says "( state paused )". Anyway, I'm glad that VLC itself can create global key-bindings, so I'm happy with my current situation.

Mail Notification

I want to have a visual indicator for when I have unread mail in my inbox. I'm gonna use the SCROLL LOCK LED for this. For controlling the LED I'll use the ledcontrol package which consists of a daemon (ledd) and a few utilities like the ledcontrol command. These enable you to use your LEDs very effectively. There is also a ledcontrol-gtk package which is a graphical frontend for this program. It is useful for learning ledcontrol commands.

This is the code I'm currently using:
;; mail notification
(defvar *unread-mail-count* 0)
(defcommand check-mail () ()
  "Checks an email account and if there is unread mail in the inbox
makes the scroll lock led to slowly blink. Returns the number of
unread messages. Needs the ledcontrol command available and the ledd
daemon pipe file (/var/run/ledd-pipe by default) should be accessible
by normal users."
  (let ((sock (clonsigna:make-imap :host "imap.gmail.com" :port 993 :ssl-p t)))
    (unwind-protect
         (progn
           (clonsigna:cmd-connect sock)
           (clonsigna:cmd-login sock "username" "password")
           (clonsigna:cmd-select sock "inbox")

           ;; cmd-search will return something like (("* SEARCH 2461
           ;; 2465 2471")) The numbers are message ids, that's why we
           ;; split the string by spaces, count the parts and then
           ;; subtract two for the "* SEARCH" part
           (setf *unread-mail-count*
                 ( - (length
                      (cl-utilities:split-sequence
                       #\Space
                       (first
                        (clonsigna:cmd-search sock :criteria "UnSeen"))))
                     2))

           ;; if there is unread mail, have the scroll lock led blink
           ;; for one second every five seconds
           (if (zerop *unread-mail-count*)
               (run-shell-command "ledcontrol set s9 off")
               (run-shell-command "ledcontrol set s9 dutycycle 5000 1 100 20"))

           *unread-mail-count*)
      (clonsigna:cmd-close sock))))

(defvar *mail-notification-timer* (run-with-timer 1 120 'check-mail))
The check-mail function uses the clonsigna package (for IMAP).  When there is unread mail, it sets the SCROLL LOCK LED to blink for one second every five seconds. It also sets the global variable *unread-mail-count* to the number of unread messages.

StumpWM's run-with-timer function is used to have the function called every two minutes.

This simplistic approach is far from perfect. One major problem for me is that if I go to my mail program and read all the unread messages, it will take a while for the LED to stop blinking.

Another problem is that this is not how email clients show the unread mail notifications. They show the number of new unread messages. That is, if there are five unread messages, and you switch to your mail client but don't read them, the notification disappears. Next time when say, two new messages arrive, you are only notified of two new messages, not seven.

The obvious way to do this is to write a plugin for my mail client (currently Thunderbird), but I'm afraid I don't have the time (and interest) to read up on how I can do that, so I'll stick with this for now.

Friday, March 16, 2012

Volume Control

So, I've finally started using StumpWM on my desktop (still on Ubuntu though) and I need to address some more practical matters. One of these is changing sound volume.

There's a handy tool called amixer that ships with Ubuntu and Debian (and probably other distros). It can be used to change many parameters of the mixer. Here we simply use it like amixer sset Master 5%+ which simply raises the master volume by 5 percent. That line also prints out the current volume (among other things) which we will use in order to show the user the current volume. I've added this snippet to my .stumpwmrc file:
;; setup volume control key bindings
(defcommand volume-up () ()
  "Increases master volume by 5 percent."
  (let ((result (run-shell-command "amixer sset Master 5%+" t)))
    (cl-ppcre:register-groups-bind (pct) ("\\[(\\d+)%\\]" result)
      (message "~a%" pct))))
(define-key *top-map* (kbd "XF86AudioRaiseVolume") "volume-up")

(defcommand volume-down () ()
  "Increases master volume by 5 percent."
  (let ((result (run-shell-command "amixer sset Master 5%-" t)))
    (cl-ppcre:register-groups-bind (pct) ("\\[(\\d+)%\\]" result)
      (message "~a%" pct))))
(define-key *top-map* (kbd "XF86AudioLowerVolume") "volume-down")

(defcommand volume-mute-toggle () ()
  "Mutes/Unmutes the master volume."
  (let ((result (run-shell-command "amixer sset Master toggle" t)))
    (cl-ppcre:register-groups-bind (state) ("\\[(on|off)\\]" result)
      (if (equalp state "off")
          (message "muted.")
          (message "unmuted.")))))
(define-key *top-map* (kbd "XF86AudioMute") "volume-mute-toggle")
This defines three commands (volume-up, volume-down and volume-mute-toggle) and binds them to the multimedia volume control keys. This works fine on my computer. If the multimedia keys are not available for you, this page suggests adding these lines:
(define-keysym #x1008ff11 "XF86AudioLowerVolume")
(define-keysym #x1008ff12 "XF86AudioMute")
(define-keysym #x1008ff13 "XF86AudioRaiseVolume")
UPDATE: I just noticed that the code for mute does not work on my Desktop (with Ubuntu Precise) though it's perfectly fine on my laptop (which runs Debian Squeeze). After some poking around, I found out that apparently when pulseaudio is present, amixer cannot unmute sound. I looked around for a pulseaudio equivalent and found pactl. But unlike amixer, pactl does not print out the current state of things after running a command and it also (as far as I know) does not provide a toggle command. What I did was to run pactl list first. This command prints out a lot of information from which we can find out if sound is muted or not. In the following snippet, I'm using a very simplistic regular expression to extract this information. It might not work correctly on a different setup
(defcommand volume-mute-toggle () ()
  "Mutes/Unmutes the master volume."
  (cl-ppcre:register-groups-bind (state)
      ("Mute: (yes|no)" (run-shell-command "pactl list" t))
    (cond ((equalp state "yes")
           (run-shell-command "pactl set-sink-mute 0 0")
           (message "unmuted."))
          (t
           (run-shell-command "pactl set-sink-mute 0 1")
           (message "muted.")))))

Better Console Font (in Arch)

In order to use Terminus as my console (tty) font, I simply installed the package terminus-font with pacman (includes both console and X11 ...