cycle_xrandr.py : dual and single displays on Ubuntu

July 10, 2008 at 06:24 AM | categories: python, linux | View Comments

Linux power management has gotten good recently. My last two laptops (HP dv9000 and Macbook Pro) have supported hardware suspend mode out of the box. I'm impressed!

Being that I hardly ever turn off the laptop (I just suspend now) I'm left with an annoyance: I use two displays at work and one everywhere else. In Ubuntu, I was easily able to setup dual and single modes such that when I boot up, Xorg detects how many displays are connected appropriately. But now that I don't turn off the machine, I want to be able to just plug in another monitor and go. I don't want to have to reboot the computer. I don't even want to have to log out. I want to plug the monitor in, leave all my apps running and in the state they are in.

Xrandr does this and it works great. But what if I'm in dual display mode but I only actually have one monitor connected? Can I get to an open terminal to use xrandr? Easily? Probably not.

I wrote the following python script to take care of this. It detects all of the modes that xrandr knows about and cycles to the next size listed. I then bind this script to a custom keyboard shortcut so I don't have to type or even see anything on the screen:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Ryan McGuire (ryan@enigmacurry.com)"
__date__   = "Thu Jul 10 15:27:18 2008"

"""Cycle through all screen resolutions detected by xrandr"""

from subprocess import Popen, PIPE
import re

size_re = re.compile("^   ([0-9]*x[0-9]*)\W*[0-9]*\.[0-9]*(\*)?")

def list_sizes():
    """List all sizes detected by xrandr,
    ordered by the next resolution to cycle to"""
    p1 = Popen(['xrandr'], stdout=PIPE)
    sizes = []
    current_size_index = 0
    for line in  p1.communicate()[0].split("\n"):
        m = size_re.match(line)
        if m:
            sizes.append(m.group(1))
            if m.group(2) == "*":
                current_size_index = len(sizes) - 1
    return sizes[current_size_index+1:] + sizes[:current_size_index+1]

if __name__ == '__main__':
    Popen(['xrandr','-s',list_sizes()[0]])
Read and Post Comments

New Slacker Screenlet released

April 04, 2008 at 10:43 PM | categories: python, linux | View Comments

Check it out: I updated my Slacker Screenlet today.

New in this version:

  • Bug fixed where the screenlet-manager would respawn infinitely
  • Integrated LastSlacker support

You can read more about the original version in my previous post.

LastSlacker is a way to scrobble what you listen to on Last.FM. This lets you share a log of what you listen to with friends. I've been meaning to add this feature for a long time now, until today it's been in a sorta working state for months! It feels good to have finally gotten this project pretty much finished.

Read and Post Comments

Backing up my (online) brain

February 22, 2008 at 11:22 PM | categories: backups, gmail, linux | View Comments

Files from my computer are disappearing.

No worries though, this is intentional.

As time goes on, more and more of my files are ending up in places like:

  • Google
  • Flickr
  • Del.icio.us
  • Facebook

And things are great. I can access these services from anywhere in the world, from any computer. What a great time to be alive!

But there is a bit of uneasiness in the back of my mind about all of this. Yes, these services liberate me (as well as my data), but at the same time, I've become a new breed of slave -- my data is no longer mine to control.

Privacy concerns aside, the biggest thing that haunts me is what if one of these services were to blow up? My data would be gone. When the data resided on my computer I could back it up myself anytime I wanted and have some sense of safety. With data on Google's server, honestly I feel pretty darn safe, but the cost of losing my data is still quite high.

My goal: Get my data back into my hands.

I'd like to start writing up my experiences on wrangling all of my data from my online services back onto media I control.

If you want to follow along, I'll be tagging these posts 'Backups'.

Gmail

The first service I'll start with is Gmail. Google, in the realm of free mail hosts, is very accommodating when it comes to accessing your mail in bulk. They have both POP3 and IMAP access. Retrieving your mail with any number of clients is trivial.

But there's more to Gmail than just your email: tags. POP3 won't get the tags, but IMAP will organize tags into folders. However, most IMAP clients only download messages on-the-fly as you read them, not all at once (like for backups).

Solution: OfflineIMAP.

OfflineIMAP will completely download all your Gmail messages into folders corresponding to all your tags. It actually does much more than this, OfflineIMAP is a full two-way synchronization of your email. Once you've downloaded your email you can take it with you while you're offline, read it, delete it and when you come back online you synchronize with gmail again deleting those same messages off of the server and retrieving new messages.

OfflineIMAP works really well for it's stated purpose: using IMAP offline. It is also useful for backing up IMAP accounts but you have to understand how it works so that you don't accidentally start deleting mail from your gmail account. Since we're using OfflineIMAP as a backup device instead of a tool to read our email I would recommend that you never open the email that it downloads with any sort of mail reader. If you do, and you accidentally move messages to a different location (mutt does this to read messages for instance), OfflineIMAP might think you deleted the message and it will delete the same message off your server (In Gmail's case it actually just removes the tag and keeps the message in All Mail, but still..) If you ever need to use the downloaded email, its safer to use a copy instead.

Caveat Emptor. Onward to configuring OfflineIMAP.

On Ubuntu:
sudo apt-get install offlineimap

Create a file called ~/.offlineimaprc :

[general]
accounts = GMail
maxsyncaccounts = 3

[Account GMail]
localrepository = Local
remoterepository = Remote

[Repository Local]
type = Maildir
localfolders = /storage/Gmail_Backup

[Repository Remote]
type = IMAP
remotehost = imap.gmail.com
remoteuser = your_username@gmail.com
remotepass = your_password
ssl = yes
maxconnections = 1

#Setting realdelete = yes will Really Delete email from the server.
#Otherwise "deleting" a message will just remove any labels and 
#retain the message in the All Mail folder.
realdelete = no

The things you need to change are:

  • localfolders - This is the full path to where it will save the email
  • remoteuser - This is your gmail email address
  • remotepass - This is your gmail password (required for automated backups, otherwise it asks everytime)

You can now run offlineimap and you should start to see it download your email. By default, OfflineIMAP gives you a graphical or textual interface that shows you what it is doing. This is good especially for the first time you download your email.

After you've downloaded all of your email, you'll want to automate the task so it runs at least every day:

Put the following in your crontab:

00 23 * * * offlineimap -u Noninteractive.Quiet

This will run OfflineIMAP everyday at 11PM.

Again, because OfflineIMAP is not technically a backup solution in itself, you might also care to make a seperate rsyncd copy of the mail somewhere else:

rsync -a /storage/Gmail_Backup/ /storage/Gmail_Backup_Copy

You can similarly run rsync in your crontab after your offlineimap finishes. By making this seperate copy, you avoid the possible deletion of emails by OfflineIMAP. This second copy will also retain messages that you delete later on in Gmail (The offlineimap syncd copy will not). This may or may not be what you want.

Stay tuned for the next installment: Flickr backups!

Read and Post Comments

Slacker Screenlet

November 20, 2007 at 12:54 PM | categories: python, linux | View Comments

Showing of the Slacker Screenlet

Having an absurdly large music collection can sometimes have it's downsides. Slacker is a nice way to listen to music when you can't decide what to listen to. Like with Pandora or Last.fm, you can create your own radio station by telling the player what kind of music you like and the player will automatically choose music to play for you. With Slacker, you can customize how much or how little new music you want to allow into the mix, which is the main reason I prefer it over Pandora.

On Windows, Slacker has created a nice standalone player. On Linux or Mac you're stuck with the web player. The nice thing about a standalone player is it won't interfere with my habit of closing my browser (thus killing my music). I decided I needed to find a way to separate the player from my main browser.

Screenlets are little, graphical, single-purpose eye-candy (written in Python :)). They can do things like show you the time or the current weather forecast, CPU load, the word of the day etc. Compiz allows these applications to run in their own layer such that they can appear and disappear quickly with the press of a button. They are quick and easy to get to, but stay out of your way when not needed.

I decided a screenlet for Slacker would be ideal, so I wrote one.

You can download my Slacker Screenlet for yourself.

Also see the following:

Read and Post Comments

Building Multi-TTY Emacs from CVS on Ubuntu Gutsy Gibbon

October 21, 2007 at 06:25 PM | categories: emacs, linux | View Comments

(Historical note May 2008: The build instructions below, while they should still work, are unnecessary as Multi-TTY has been merged into the main Emacs 23 branch and is available in ubuntu repositories: apt-get install emacs-snapshot)

Last spring I wrote an article about Multi-TTY Emacs. I had promised that I would update instructions for building it on Ubuntu, but since then I have been mainly using Gentoo on my laptop and never got around to updating it. Sorry :)

I switched to Ubuntu Gutsy Gibbon yesterday. I also got Multi-TTY Emacs running, and here's the video to prove it (If this is too small to see, download the original ogg theora version) :

Building CVS Emacs the old fashioned way

For those of you that want the easy way out, I've prebuilt an emacs CVS package that includes the Multi-TTY patch. I've tested that the package works on both Gutsy as well as Feisty.

For those of you that would like to learn how this is done, here's my recipe:

Install all the dependencies

sudo apt-get install build-essential cvs texinfo libx11-dev libxpm-dev libjpeg-dev \
libpng-dev libgif-dev libtiff-dev libgtk2.0-dev checkinstall

Check out the Emacs code from CVS

cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/cvsroot/emacs co emacs

Compile the source

cd emacs
./configure --with-gtk --prefix=/usr/local
make bootstrap
make

Checkinstall will build a basic emacs package for us with a minimum of fuss. We don't want to automatically install this package though for reasons we'll see below

sudo checkinstall -D --install=no

Checkinstall will ask you to change some values. I changed the maintainer email and the version number.

Checkinstall is great, and works for 99% percent of the packages that I've tried it with. Emacs is a bit different though -- the package that checkinstall creates doesn't include everything that emacs requires, like all the .el files in the lisp folder among other things. So we have to edit the package a bit. For the following code, we'll assume the .deb file that checkinstall creates is just called "emacs_cvs-10202007-1_i386.deb", so adjust for whatever checkinstall called your .deb file:

Extract the data from the .deb

dpkg-deb -x emacs_cvs-10202007-1_i386.deb emacs_cvs-10202007-1_i386 
#Or whatever your .deb is called

Extract the control information from the .deb

dpkg-deb -e emacs_cvs-10202007-1_i386.deb emacs_cvs-10202007-1_i386/DEBIAN

Now we need to add some of the files that checkinstall left out of the package

cp -a lisp/* emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/site-lisp/
mkdir emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/lisp
mkdir -p emacs_cvs-10202007-1_i386/usr/local/libexec/emacs/23.0.50/i686-pc-linux-gnu
cp -a etc emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/
mkdir emacs_cvs-10202007-1_i386/etc
ln -s ../usr/local/share/emacs/23.0.50/etc/termcap.src emacs_cvs-10202007-1_i386/etc/termcap

Rebuild the modified package

dpkg-deb -b emacs_cvs-10202007-1_i386 emacs_modified.deb

To totally revolutionize the way you use Emacs, remember to check out my earlier post on Multi-TTY Emacs.

Read and Post Comments

« Previous Page -- Next Page »