I've been through all the BIOS screens looking for a setting to flip, but there's nothing there. Some web searching told me that under Windows, there's a setting you can change that will affect this, but I couldn't find anything similar for Linux, until finally drc clued me in to /proc/acpi/wakeup.
cat /proc/acpi/wakeupwill tell you all the events that can cause your machine to wake up from various sleep states.
Unfortunately, they're also obscurely coded. Here are mine:
Device S-state Status Sysfs node SLPB S4 *enabled P32 S4 disabled pci:0000:00:1e.0 UAR1 S4 enabled pnp:00:0a PEX0 S4 disabled pci:0000:00:1c.0 PEX1 S4 disabled PEX2 S4 disabled pci:0000:00:1c.2 PEX3 S4 disabled pci:0000:00:1c.3 PEX4 S4 disabled PEX5 S4 disabled UHC1 S3 disabled pci:0000:00:1d.0 UHC2 S3 disabled pci:0000:00:1d.1 UHC3 S3 disabled pci:0000:00:1d.2 UHC4 S3 disabled pci:0000:00:1d.3 EHCI S3 disabled pci:0000:00:1d.7 AC9M S4 disabled AZAL S4 disabled pci:0000:00:1b.0
What do all those symbols mean? I have no clue. Apparently the codes come from the BIOS's DSDT code, and since it varies from board to board, nobody has published tables of likely translations.
The only two wakeups that were enabled for me were SLPB and UAR1.
SLPB apparently stands for SLeeP Button, and Rik suggested UAR
probably stood for Universal Asynchronous Receiver (the more familiar
term UART both receives and Transmits.)
Some of the other devices in the list can possibly be identified by
comparing their pci: codes against lspci, but not those two.
Time for some experimentation. You can toggle any of these by writing to the wakeup device:
echo UAR1 >/proc/acpi/wakeup
It turned out that to disable mouse and keyboard wakeup, I had to disable both SLPB and UAR1. With both disabled, the machine wakes up when I press the power button. (What the SLeeP Button is, if it's not the power button, I don't know.)
My mouse and keyboard are PS/2. For a USB mouse and keyboard, look for something like USB0, UHC0, USB1.
The UAR1 setting is remembered even across boots: there's no need to do anything to make sure the setting is remembered. But the SLPB setting resets every time I boot. So I edited /etc/rc.local and added this line:
echo SLPB >/proc/acpi/wakeup
It is sad to see the demise of Metacity, but its legacy will not be forgotten. Obviously there is Mutter, and of course Compiz, but i think most modern window managers owe a tip of the hat to Metacity; it brought a love of standards, simplicity and of course integration.
It was not without the doubters though, and it certainly felt unloved toward the end (despite the ongoing work of Thomas Thurman and whoever wrote the compositor? Ian…?). The problem with Metacity, for me, was that it was just never that predictable, I’m not really fussy with focus issues but Metacity still seemed to grate on me, it always felt very incomplete, it always felt just not right - probably because people (I blame Ubuntu, but I blame them for everything) jumped on the Compiz bling wagon far too early when what was needed was boring bug fixes to Metacity for a better window manager experience. The problem with Compiz was that it became very apparent that those who shouted loudest were more interested in how their menus exploded rather than how their windows were managed.
The Metacity blog was always an interesting read as well which I guess will go out the window now, people just aren’t interested in window managers unless a) they tile (which is foolish) or b) they have stupid effects. I hope Mutter is a solid window manager with tasteful warranted effects that aid usability and maybe even accessibility. Gnome-shell right now look wholly underwhelming but that might be a good thing?
Metacity still has the best simple composite manager for my money and I’d love to see something like it in Openbox ;)
I quite enjoy the competitive undercurrent of ping pong pair programming. As the person writing the implementation code, it is fun to write something that will turn a test green, but still not necessarily do what my partner was expecting. Taking this approach has also been helpful for improving our specs. Take this example controller spec:
describe ArticlesController do
describe "handling create" do
before(:each) do
@article = mock_model(Article, :save => nil)
Article.stub(:new).and_return(@article)
@user = mock_model(User)
controller.stub(:current_user).and_return(@user)
end
it "should build a new article from posted data" do
Article.should_receive(:new).with('title' => 'Test Post')
post :create, :article => {:title => 'Test Post'}
end
it "should assign the current user as the article's author" do
@article.should_receive(:author=).with(@user)
post :create
end
it "should save the article"
@article.should_receive(:save)
post :create
end
end
endThis looks like a reasonable set of concise, clear examples, but you can easily make them all pass and without building a controller action that does what you expect:
class ArticlesController < ApplicationController
def create
@article = Article.new(params[:article])
@article.save
@article.author = current_user
end
endThis satisfies the examples, but saving the article before assigning the current user as author isn’t what we would have intended. Enter RSpec’s ordered message expectations. These allow you to specify the order in which you expect an object to receive message calls.
describe ArticlesController do
describe "handling create" do
it "should save the article after assigning the current user as author"
@article.should_receive(:author=).with(@user).ordered
@article.should_receive(:save).ordered
post :create
end
end
endThis example would fail with the above controller action, and force us to write it properly:
class ArticlesController < ApplicationController
def create
@article = Article.new(params[:article])
@article.author = current_user
@article.save
end
endThe result is a controller that does what you expect, a stronger set of specs, and an increased capacity for true behaviour driven development. Win, win, win!
We’ve been really hitting the Cucumber hard in the recent few iterations of our current project. Now that we’re ping pong pair programming, the Cucumber story is the first thing we write, and we revisit regularly during the red-green-refactor cycle.
To make this easy, we place a @wip work in progress tag at the top of the current stories:
Feature: Make coffee
# This one is done.
Scenario: First coffee of the day
# This is the one we're working on.
@wip
Scenario: Afternoon perk upThen we use cucumber -t wip to run just the stories in progress. Once the stories are green and we’re happy to move on, we often forget to remove the @wip tags before committing. I wrote a little sed command in a bash alias to make this easier:
# Remove any @wip tags from Cucumber features.
alias dewip="sed -E -i '' -e '/^[[:blank:]]*@wip$/d;s/,[[:blank:]]*@wip//g;s/@wip,[[:blank:]]*//g' features/**/*.feature"Throw it in your .bash_profile for ease of access! Here’s a gist for your forking pleasure.
Anyone who’s been around the Internet long enough should remember The Geek Code. This meme sought to provide a – however obsbcure – succinct textual distillation of the attributes and interests of any geek.
GED/J d-- s:++>: a-- C++(++++) ULU++ P+ L++ E---- W+(-) N+++ o+ K+++ w---
O- M+ V-- PS++>$ PE++>$ Y++ PGP++ t- 5+++ X++ R+++>$ tv+ b+ DI+++ D+++
G+++++ e++ h r-- y++**This geek code block represents someone trained in education and law who is tall and dresses casually, knows his way around Linux and Ultrix pretty well, hates emacs, but loves indulging in a little Dilbert. Look it up, it’s elaborate.
Today, a Rails developer can provide a template for generating new apps that can uniquely embody all their development tools and preferences in a single place.
gem 'haml'
gem 'mislav-will_paginate', :lib => 'will_paginate', :source => 'http://gems.github.com'
gem 'chriseppstein-compass', :lib => 'compass', :source => 'http://gems.github.com'
gem 'thoughtbot-paperclip', :lib => 'paperclip', :source => 'http://gems.github.com' if yes?('Paperclip gem?')
gem 'authlogic' if yes?('Authlogic gem?')You’re a haml guy? Right on. Plus compass for CSS! You must like really things semantic.
file '.testgems',
%q{config.gem 'rspec'
config.gem 'rspec-rails'
config.gem 'notahat-machinist', :lib => 'machinist', :source => 'http://gems.github.com'
config.gem 'ianwhite-pickle', :lib => 'pickle', :source => 'http://gems.github.com'
config.gem 'webrat'
config.gem 'cucumber'
}
run 'cat .testgems >> config/environments/test.rb && rm .testgems'RSpec along with Cucumber backed by Machinist and Pickle for test data factories. You must be Australian. But that’s cool, that’s a pretty helpful combo for tests.
git :init
git :add => '.'
git :commit => '-a -m "Initial commit from AMC Rails template"'Building a complete Rails template has been really useful for us at the AMC. We’re often asked to bring up quick, single-purpose apps alongside the many components that we’re building in our mostly service-oriented architecture.
Our template is available on GitHub for your perusal and reuse. It does everything from setting up plugins and gem dependencies, to generating a deploy script using our custom capistrano extensions, to including a default layout and stylesheet. This is how we roll, captured in a single file.
Our current work project is a long-overdue rebuild of a critical business system as a modern Rails web app. We’re building this thing according to agile practices to the best of our ability. Each week we provide a new, working release that is an incremental improvement on the last. We’re not looking to replace the current system in a single swoop, and expect the new system to work alongside the old one for quite a while.
This means that we’ll need to maintain the same data in both systems for the duration of their lives together. We don’t want the new Rails app to access the data directly from the old app’s database, since this would prevent us from following the conventions that makes working with Rails so pleasant. Instead, we’ve come up with a way to import the legacy data into a new database.
In doing this, I’ve built a Rails plugin to make the experience easier. It is called Acts as Importable and it is now available on GitHub. This article will show our technique for importing the legacy data and how Acts as Importable helps.
We use ActiveRecord to access the legacy data. It takes a bit of legwork to shoehorn the legacy schema into ActiveRecord models, but once that is done, we have satisfactory access to the data we want to import.
The first thing we do is provide a Legacy::Base model from which all other legacy models can inherit. This provides a single place to define access to the legacy database.
class Legacy::Base < ActiveRecord::Base
self.abstract_class = true
establish_connection "legacy_#{Rails.env}"
acts_as_importable
endYou can setup the extra database connections in config/database.yml, like below. Our legacy connection is to an MS SQL server via ODBC. Tim Lucas has an excellent tutorial on how to get that set up.
legacy_development:
adapter: sqlserver
mode: odbc
dsn: LEGACY
autocommit: true
host: localhost
username: NTDOMAIN\username
password: passwordNow, here are a couple of the legacy models that inherit from Legacy::Base to access the legacy database. For the sake of this article, consider the code examples to come from a quiz application with models for categories, questions, and responses.
class Legacy::Question < Legacy::Base
set_table_name 'quiz_questions'
set_primary_key 'QuestionNumber'
belongs_to :category,
:class_name => 'Legacy::Category',
:foreign_key => 'CategoryCode'
end
class Legacy::Category < Legacy::Base
set_table_name 'quiz_categories'
set_primary_key 'Code'
endThese are simple examples, but you get the idea. set_table_name and set_primary_key are your friends when you have table names and keys that defy Rails’ conventions. If you want to use ActiveRecord associations to access your legacy data, you will also want to become familiar with the options available for specifying things like the class, join table and column names. Check the rdocs for has_many, belongs_to and has_and_belongs_to_many and look out for options like :class_name, :foreign_key, :join_table, and :association_foreign_key.
Each of the legacy models provides a to_model method that returns a new model ready to be saved into the new, non-legacy database.
# New model
class Category < ActiveRecord::Base
end
# Legacy model
class Legacy::Category < Legacy::Base
set_table_name 'quiz_categories'
set_primary_key 'Code'
def to_model
::Category.new do |c|
c.name = self.Description
end
end
endNow that the import rules are defined for all the legacy models we care about, how do we get them all into the new database? This is where Acts as Importable comes in. This plugin helps to smoothen the import of an entire system’s worth of legacy data. You saw it enabled above in the Legacy::Base class:
class Legacy::Base < ActiveRecord::Base
self.abstract_class = true
establish_connection "legacy_#{Rails.env}"
acts_as_importable
endActs as importable will let you import your legacy models in different ways:
# Import a single question
Legacy::Question.import(123)
# or
Legacy::Question.find(123).import
# Import all questions
Legacy::Question.import_all
# Import all the questions, 1000 at a time
Legacy::Question.import_all_in_batchesThese are all different ways of instantiating your legacy models, calling the to_model method, and saving the returned object. The value of the plugin is that it adds a little bit of extra smarts to this basic premise.
Acts as Importable provides a lookup class method for finding the new ID of an imported legacy model. When each legacy model is imported using the above methods, Acts as Importable saves the legacy model’s class name and ID along with the rest of the data in new model (be sure to provide legacy_class and legacy_id columns for this to work). The first time you lookup a legacy record, it uses ActiveRecord::Base#find with the appropriate values for legacy_class and legacy_id as conditions. It will save the ID in a lookup hash in memory, so that the next time you want to lookup from the same ID, the result is returned without a trip to the database.
This is really best seen in action:
# New models
class Question < ActiveRecord::Base
belongs_to :category
has_many :responses, :dependent => :destroy
end
class Category < ActiveRecord::Base
has_many :questions
end
# Legacy model
class Legacy::Question < Legacy::Base
def to_model
::Question.new do |q|
# import the category association
q.category_id = Legacy::Category.lookup(self.category.try(:id__))
end
end
endSetting the id for associations directly like this is important for conserving trips to the database importing a model’s belongs_to relationships, just like the one above. Be wary when using lookups for large data sets, however, as it will likely consume quite a bit of memory to store the ID mappings.
As an aside, we use #try(:id__) on the legacy model to provide the ID for the lookup, because #id on a nil value actually returns its #object_id. If the associated object doesn’t exist, we don’t want to pass a bogus ID. Acts as Importable provides Object#try and the ActiveRecord::Base#id__ to id alias for you.
The lookups will work automatically if the class name of the model you’re importing is the same as the legacy model’s, eg. Legacy::Question to Question. If the class name of the model you’re creating is different, you can tell that to Acts as Importable so that the lookups can continue to work:
# New model
class DifferentThing < ActiveRecord::Base
end
# Legacy model
class Legacy::Thing
acts_as_importable :to => 'DifferentThing'
def to_model
::DifferentThing.new
end
endYou can import has_many relationships quite easily, using the #build method on the association proxy. Here it is in action, expanding on the Question’s #to_model method from above:
# New models
class Question < ActiveRecord::Base
belongs_to :category
end
class Response < ActiveRecord::Base
belongs_to :question
end
# Legacy model
class Legacy::Question < Legacy::Base
def to_model
::Question.new do |q|
q.category_id = Legacy::Category.lookup(self.category.try(:id__))
# Build the responses
(1..5).each do |i|
q.responses.build(:body => self.send(:"response_#{i}"))
end
end
end
endWhen you save the new model, the newly built associated models are saved too.
We ran into some slowness importing legacy models with large numbers of records, or with other models with large amounts of data in particular fields. To get around this, we use #import_all_in_batches, which only retrieves 1000 models at a time for processing. This is based on Jamis Buck’s technique for faking cursors in ActiveRecord, and as such, it requires a numeric primary key for the legacy models (you’d normally expect this to be the case, but it isn’t for a few of our legacy tables).
As I mentioned in the introduction, the legacy app we’re replacing will remain in use as we incrementally build the new system. We will need to continue to synchronise the legacy data with the new system during this time. We’ll therefore need our import process to be idempotent, meaning that multiple imports can run and result in the same set of data at the other end. Mostly, this just means that we’ll want to avoid creation of duplicate records in the new database.
We approach this pretty simply. Each night the old records are deleted and new ones re-imported in their place. You’ll want to pick an approach that best suits your situation.
There is one complication, however, insofar as the new system is used to create some entirely new content that relates to the imported models. If models are deleted and re-imported from the legacy system every night, their IDs would be different each time. To get around this, we hard-code the ID of certain imported models to the same value as their respective legacy model’s ID. This is very simply done:
class Legacy::Question < Legacy::Base
def to_model
::Question.new do |q|
# Hard-code the ID
q.id = self.id
q.category_id = Legacy::Category.lookup(self.category.try(:id__))
(1..5).each do |i|
q.responses.build(:body => self.send(:"response_#{i}"))
end
end
end
endThere are two final pieces to our import system. Firstly, a way to control the order of the imports:
class Legacy::Importer
def self.run
Legacy::Category.import_all
Legacy::Question.import_all_in_batches
# Flush all the lookup tables
Legacy::Category.flush_lookups!
Legacy::Question.flush_lookups!
end
endIt is important to control the order if your imported models are going to relate to each other. Some records will need to exist before the others can link to them.
And finally, a rake task:
namespace :legacy do
desc "Import the legacy data."
task :import => :environment do
Legacy::Importer.run
end
endThat’s it! This approach certainly works to our liking, but I would love to hear your thoughts on this issue. Please feel free to post a comment below.
These articles were of great use in getting our legacy imports up and running:
Like many keystroke-efficient Rails hackers, I’ve long had a line in my .bash_profile file to alias sc to script/console, along with a host of other tricks.
This shortcut was more than sufficient until recently, when I started writing Sinatra apps. The minimal framework that it is, Sinatra doesn’t provide a console script like Rails, but I found you can easily achieve the same effect by running irb -r your_sinatra_app.rb.
Not wanting my fingers to have to deviate from habits long held, I changed my sc alias into a full-blown bash function that will drop you into a Rails console, Sinatra console or just a plain irb console based on your location within the filesystem:
function sc {
if [ -x script/console ]; then
script/console
else
sinatra_rb=`egrep -l "^require.+sinatra.$" *.rb 2>/dev/null`
if [ -e $sinatra_rb ]; then
irb -r $sinatra_rb
else
irb
fi
fi
}Throw it in your .bash_profile and have fun!

Thanks to the amazing support from the GNOME Travel Committee, I will be attending my first GUADEC this year in Gran Canaria! I am very thankful for their commitment to accomodate my needs and I’ll try to make the most of it!
I’ll be arriving July 3rd around lunch time and will stay until the 11th, so there will be plenty of time to meet up and discuss. I’m mostly interested in localization, accessibility, and tests automation but am equaly interested in community building and the organization toward GNOME 3.0!
If you see some really fast crutches running around the terminals in Boston or Madrid, come by and say hi to me!
Why not? Well, I updated my kernel to tweak some ACPI parameters
(fruitlessly, as it turns out; I'm trying to get powertop to give
me more information but I haven't found the magic combination of
kernel parameters it wants on this machine) and so I did a
make modules_install. And it seems that
make modules_install starts out by doing
rm -rf /lib/modules/VERSION/kernel which removed
my externally built beep module along with everything else.
I couldn't find documentation on this, but I did find Intel Wireless bug 556 which talks about the issue. Apparently somewhere along the way 2.6 started doing this rm -rf, but you can get around it by installing outside the kernel directory.
In other words, instead of
cp beep.ko /lib/modules/2.6.29.4/kernel/drivers/input/misc/do
cp beep.ko /lib/modules/2.6.29.4/drivers/input/misc/Then your external module won't get wiped out at the next
modules_install.
I've let the maintainer of Fancy Beeper know about this, so it won't be a problem for that module, but it's a good tip to know about in general -- I'm sure there are lots of modules that hit this problem.
It has come to my attention that I have generally knocked out a blag every month, it seems a shame to break this amazing run.
I have nothing much to reckon really, but I have started to learn how to use GIT, which is sort of interesting. I’m using github as it seems the easiest way to get started and i don’t know enough to overly criticism it in anyway. I am more or less incapable of coding to an acceptable standard, so my repos are all theme related. I hope to add a couple of little hacks when I move on to learning how to fork or whatever, and possibly some php frame work stuff - which isn’t real code ;) But right now I just need *something* to learn with.
It is mostly older stuff that I update a bit but never really publically make any ‘releases’
They are all here. There are a couple of icon themes (Eggshell should really be a branch of Ecru) and a meta-theme (metacity, openbox, gtk) and other themes maybe.
Anyway that is all.
I was going to try to stick to OpenStreetMap and other existing mapping applications like TangoGPS, a neat little smartphone app for downloading OpenStreetMap tiles that also runs on the desktop -- but really, there still isn't any mapping app that works well enough for exploring maps when you have no net connection.
In particular, uploading my GPS track logs after a day of mapping, I discovered that Tango really wasn't a good way of exploring them, and I already know Merkaartor, nice as it is for entering new OSM data, isn't very good at working offline. There I was, with PyTopo and a boring hotel room; I couldn't stop myself from tweaking a bit.
Adding tracklogs was gratifyingly easy. But other aspects of the code bother me, and when I started looking at what I might need to do to display those Tango/OSM tiles ... well, I've known for a while that some day I'd need to refactor PyTopo's code, and now was the time.
Surprisingly, I completed most of the refactoring on the trip. But even after the refactoring, displaying those OSM tiles turned out to be a lot harder than I'd hoped, because I couldn't find any reliable way of mapping a tile name to the coordinates of that tile. I haven't found any documentation on that anywhere, and Tango and several other programs all do it differently and get slightly different coordinates. That one problem was to occupy my spare time for weeks after I got home, and I still don't have it solved.
But meanwhile, the rest of the refactoring was done, nice features like track logs were working, and I've had to move on to other projects. I am going to finish the OSM tile MapCollection class, but why hold up a release with a lot of useful changes just for that?
So here's PyTopo 0.8, and the couple of known problems with the new features will have to wait for 0.9.
How do you find all the methods in a given class, object or module?
Ideally the documentation would tell you. Wouldn't that be nice? But in the real world, you can't count on that, and examining all of an object's available methods can often give you a good guess at how to do whatever you're trying to do.
Python objects keep their symbol table in a dictionary
called __dict__ (that's two underscores on either end of the word).
So just look at object.__dict__. If you just want the
names of the functions, use object.__dict__.keys().
Thanks to JanC for suggesting dir(object) and help(object), which can be more helpful -- not all objects have a __dict__.
Well its getting hot, and nothing like having to wear long sleeves in your job when your outside all day in the blistering sun !!
But the Intel dual-Atom board doesn't seem to support a system beep -- there's no obvious place on the motherboard to plug in the connector going to the case speaker. How odd!
With the alternative being no beep at all,
I dusted off my old blog post and went to see if
Fancy Beeper
Daemon kernel module still existed. Happily, it does, and it's
up-to-date for current kernels, so all I had to do was download the
latest and build it. Easy! Then I added "beep" to the list of
automatically loaded modules in /etc/modules,
blacklisted the pcspkr module using the
/etc/modprobe.d/00local
technique, and I was all set.
Except for the really important question: what sound to choose? I did a little web searching for free sounds and downloaded some samples to try out. Then I added a few bird calls from my Stokes Field Guide to Western Bird Songs CD, editing them in audacity to make them shorter and more appropriate for system beeps.
But I still couldn't decide on just one ... and why should I? I've really been enjoying my random wallpaper: every time I log in, I get a different desktop background. It's fun to see a new picture every day. Why not do the same for my system beep?
That's no problem, using the same randomline script I use for wallpaper. I just put this in my .xinitrc:
$HOME/bin/mybeepd `find $HOME/Music/beeps -name "*.wav" | randomline` &and now I get a different beep sound each day.
Yesterday it was a loon. Today it's a cow mooing.
GeekDeck has just released Issue 3, including;
What are you waiting for? Go read it now!
To make it clearer, I wanted to print out handouts people could take home summarizing some of the most common closed formats, along with open alternatives.
Surely there are lots of such tables on the web, I thought. I'll just find one and customize it a little for this specific audience.
To my surprise, I couldn't find a single one. Even openformats.org didn't have very much.
So I started one: Open vs. Closed Formats. It's far from complete, so I hope I'll continue to get contributions to flesh it out more.
And the talk? It went over very well, and people appreciated the handout. There's a limit to how much information you can get across in under ten minutes, but I think I got the point across. The talk itself, such as it is, is here: Open up!
But what I want to know about Bing is this:
Why does it think we're in Portugal when Dave runs it under Omniweb on Mac?
In every other browser it gives the screen you've probably seen, with side menus (and a horizontal scrollbar if your window isn't wide enough, ugh) and some sort of pretty picture as a background. In Omniweb, you get a cleaner layout with no sidebars or horizontal scrollbars, a different pretty picture -- often prettier than the one you get on all the other browsers, though both images change daily -- and a set of togglebuttons that don't show up in any of the other browsers, letting you restrict results to only English or only results from Portugal.
Why does it think we're in Portugal when Dave uses Omniweb?
Equally puzzling, why do only people in Portugal have the option
of restricting the results to English only?
Celebrating my 35th birthday today! A year older, a year (hopefully) wiser, and every day glad to have the life I have! Can’t wait to see what the next year will bring!
The really puzzling thing, though, wasn't the crashes, but the fact
that X acceleration didn't work at all. Programs like tuxracer
(etracer) and Google earth would display at something like one frame
update every two seconds, and glxinfo | grep renderer said
OpenGL renderer string: Software Rasterizer
But that was all on my old desktop machine, with an ATI Radeon 9000 card that I know no one cares about much. I have a new machine now! An Intel dual Atom D945GCLF2D board with 945 graphics. Finally, a graphics chip that's supported! Now everything would work!
Well, not quite -- there were major teething pains, including returning the first nonworking motherboard, but that's a separate article. Eventually I got it running nicely with Intrepid. DRI worked! Tuxracer worked! Even Google Earth worked! Unbelievable!
I copied the Jaunty install from my old machine to a partition on the new machine. Booted into it and -- no DRI. Just like on the Radeon.
Now, there's a huge pile of bugs in Ubuntu's bug system on problems with video on Jaunty, all grouped by graphics card manufacturer even though everybody seems to be seeing pretty much the same problems on every chipset. But hardly any of the bugs talk about not getting any DRI at all -- they're all about whether EXA acceleration works better or worse than XAA and whether it's worth trying UXA. I tried them all: EXA and UXA both gave me no DRI, while XAA crashed/rebooted the machine every time. Clearly, there was something about my install that was disabling DRI, regardless of graphics card. But I poked and prodded and couldn't figure out what it was.
The breakthrough came when, purely by accident, I ran that same
glxinfo | grep renderer from a root shell. Guess what?
OpenGL renderer string: Mesa DRI Intel(R) 945G GEM 20090326 2009Q1 RC2 x86/MMX/SSE2
As me (non-root), it still said "Software Rasterizer." It was a simple permissions problem! But wait ... doesn't X run as root?
Well, it does, but the DRI part doesn't, as it turns out. (This is actually a good thing, sort of, in the long term: eventually the hope is to get X not to need root permissions either.)
Armed with the keyword "permissions" I went back to the web, and the Troubleshooting Intel Performance page on the Ubuntu wiki, and found the solution right away. (I'd looked at that page before but never got past the part right at the beginning that says it's for problems involving EXA vs. UXA vs. XAA, which mine clearly wasn't).
In Jaunty, the user has to be in group video to use DRI in X. But if you've upgraded from an Ubuntu version prior to Jaunty, where this wasn't required, you're probably not in that group. The upgrader (I used do-release-upgrade) doesn't check for this or warn you that you have desktop users who aren't in the video group, so you're on your own to find out about the problem. Fixing it is easy, though: edit /etc/group as root and add your user(s) to the group.
You might think this would have been an error worth reporting, say, at X startup, or in glxinfo, or even in /var/log/Xorg.0.log. You'd think wrong. Xorg.0.log blithely claims that DRI is enabled and everything is fine, and there's no indication of an error anywhere else.
I hope this article makes it easier for other people with this problem to find the solution.
Well another week of work over with, whew. Mandatory OT coming up shortly so less and less time to do things a guy wants to do.
The Walden West pond is hopping -- literally!
This afternoon around 3pm the pond's resident bullfrogs,
who normally just float quietly in the scum on the surface,
would suddenly hop out of the water for no obvious
reason, then settle back down a few feet away.
One pair was apparently mating like that, the larger frog hopping
onto the back of the smaller frog, then immediately off again.
And the pond was full of sound, sometimes with two or more
frogs booming at once. Bullfrogs in stereo!
I didn't have the SLR along, but some of the frogs were close enough (and calm enough not to submerge when we got near them) that I was able to get a few decent shots.
But I really wanted to capture that sound. So I put the camera in video mode and shot a series of videos hoping to catch some of the music ... and did. They sound like this: bullfrog (mp3, 24kb).
Despite the title of this entry, the recording doesn't have any interesting stereo effects; the only microphone was the one built in to my Canon A540. It did okay, though! You'll just have to use your imagination to place two frogs as you listen, one 20 feet to the left and the other 15 feet to the right.
Extracting the audio was a little tricky. I found lots of pages ostensibly telling me how to do it with mencoder, but none of them seemed to work. This did:
mplayer -vc null -af volume=15 -vo null -ao pcm -benchmark mvi_8992.avi
I added that -af volume=15 argument to make the sound
louder, since it was a bit quiet as it came from the camera.
That produced a file named audiodump.wav, which I turned into an mp3 like this:
lame audiodump.wav bullfrogs.mp3
Most of the replies involved "just edit the XML." Sure, GPX files are pretty simple and readable XML -- but a user shouldn't ever have to do that! Gpsman and gpsbabel were also mentioned, but they're not terribly easy to use either.
That reminded me that I had another XML-parsing task I'd been wanting to write in Python: a way to split track files from my Garmin GPS.
Sometimes, after a day of mapping, I end up with several track segments in the same track log file. Maybe I mapped several different trails; maybe I didn't get a chance to upload one day's mapping before going out the next day. Invariably some of the segments are of zero length (I don't know why the Garmin does that, but it always does). Applications like merkaartor don't like this one bit, so I usually end up editing the XML file and splitting it into segments by hand. I'm comfortable with XML -- but it's still silly.
I already have some basic XML parsing as part of PyTopo and Ellie, so I know the parsing very easy to do. So, spurred on by the posting on OSM-newbies, I wrote a little GPX parser/splitter called gpxmgr. gpxmgr -l file.gpx can show you how many track logs are in the file; gpxmgr -w file.gpx can write new files for each non-zero track log. Add -p if you want to be prompted for each filename (otherwise it'll use the name of the track log, which might be something like "ACTIVE\ LOG\ #2").
How, you may wonder, does that help the original poster's need to separate out waypoints from track files? It doesn't. See, my GPS won't save tracklogs and waypoints in the same file, even if you want them that way; you have to use two separate gpsbabel commands to upload a track file and a waypoint file. So I don't actually know what a tracklog-plus-waypoint file looks like. If anyone wants to use gpxmgr to manage waypoints as well as tracks, send me a sample GPX file that combines them both.
I was trying to get the adobe air iplayer thingy working in openbox, it turns out it is crap anyway.
But to find out that it is was a waste of time I had to figure out how to pretend I had a gnome session going on; so it would even bother to load in the first place.
Normally you will get the:
Unknown desktop manager, only Gnome and KDE are supported
It turns out gnome session doesn’t really do much in this area and the checks performed are poor and depreciated.
Anyway, you can just dump these in your openbox session or .xinitrc or somewhere?
export DESKTOP_SESSION="gnome"
export GNOME_DESKTOP_SESSION_ID="openbox"
The first line might not even be needed, but it is nice anyway.
Another side effect of this is that it will work for other apps (which may suck less than the iplayer app), notably tweetdeck which the kids love, apparently.
I guess you could make a new openbox session like this which would be very fake gnome-y.
#!/bin/sh
if test -n "$1"; then
echo "Syntax: openbox-session"
echo
echo "See the openbox-session(1) manpage for help."
exit
fi
export OOO_FORCE_DESKTOP="gnome"
export WINDOW_MANAGER="/usr/bin/openbox"
export DESKTOP_SESSION="gnome"
export GNOME_DESKTOP_SESSION_ID="openbox"
if test -e $AUTOSTART; then
. $AUTOSTART
else
if test -e $GLOBALAUTOSTART; then
. $GLOBALAUTOSTART
fi
fi
AUTOSTART="$HOME/.config/openbox/autostart.sh"
GLOBALAUTOSTART="/etc/xdg/openbox/autostart.sh"
exec /usr/bin/openbox "$@"
Been quite busy at work these days, as well as playing the host to my parents during the holidays. I did keep up with what was happening around the world, thanks to my G1 (I love this gadget!), and wanted to share a few nice nuggets.
I have been working on a little aggregator for my ‘homepage‘ which is a glorified index page to many directories of files and crap, but over time I have become fond of it and decided it might need some love. The best idea I could come up with was to aggregate all the feeds of sites I use, such as twitter, my blag and flickr (for now) as a sort of centralised hub.
I am going to have to re-assess all my hosting and whatnot at some point (for money reasons) and centralise everything in one place, I have a few domains but I will probably keep chalkskeletons, even though the comic/original idea is very dead, I have had it a while and i am fond of it.
I am currently auditioning a centralised bookmark things, obviously delicious is an option as is google bookmarks, but i am not sure what is out there these days?