Release notes are the new novel
It goes without saying that (nearly) everyone brought their laptops to the News Years weekend in Sonoma.
I played a game of semantic bullshit and brought only a
fancy-pants Nokia tablet. One of the things I like the
most about the new OS2008
models is the polite
throbber that gently blinks when you receive email, or an
instant message or some other event that an application
thinks it should tell you about.
You can see where this is going.
There are even Python bindings for sending various types of notifications but since I still haven't figured out the magic to talk to the throbber I spent the weekend periodically poking at the plain old web to see what was going on.
Of course, when I got home all the little Growl-based notification agents I've been writing woke up and spewed four days worth of hot friend action all over my screen. Computers. They're dumb like that.
So, now you can specify a
skip_items_older_than
preference in the config
file and ignore anything older than an hour or a day or whatever.
I suppose it might be neat to write some magic to set
that option dynamically based on the last time an
application was able to register the presence of your
pho^H^H^Hdevice, but not today.
Instead, there is only the quick and dirty :
- growler.py 1.1
- flgrowler.py 1.1
- twgrowler.py 1.1
Meanwhile, here's a long photo of us eating dinner.
This blog post is full of links.
#growler11old(1.0) != new(1.0)
The code discussed in this post has been pulled apart and packaged in handy little feature-specific bundles complete with proper Python installation scripts. They are :
- growler.py, a base class for creating Python daemons to poll services and displaying updates with Growl notifications
- flgrowler.py, a base class
and three separate applications :
- flactivity, to display recent activity on your photos
- flcontacts, to display recent photos from your contacts
- flavourites, to display photos recently favourited by your contacts
- twgrowler.py, a base class
and one application :
- twgrowler, to display recent Twitter messages from your contacts
The only caveat is a known bug where searching for nearby Bluetooth devices will get stuck in some sort of infinite loop. I don't know why or, even, how to reproduce the problem. From a distance it appears to be something happening at the (OS X) operating system layer but more investigating is necessary.
As mentioned, there is nothing especially OS X specific about any of this beyond the Growl bindings and every operating system has at least one functional equivalent. At some point, I may also port it to use any number of notification agents.
But not today.
This blog post is full of links.
#growler10My Inbox is full of rocks
This morning, I was reminded of the quick-and-dirty-and-ugly Perl module for graphing the relationships between email messages that I wrote a few years ago. As usual there is no magic since it simply hands all the hard work to GraphViz and treats everything as sticks and rocks.
I know that some people like to imagine that there is
actual knowledge (or if you are a timesome doorknob,
agency
) to be teased out these things but I prefer to
think of them more as Auggie Wren devices. The value for me is to collect a lot of them and then try to feel the elephant over time; to imagine the patterns as a halftone screen with which to rasterbate everything else.
With that in mind I dug out the code just to see if it still worked and, in the process of all the usual bugfixes, decided to teach it a few new tricks.
Here's my Inbox, with just basic To:
,
From:
and Cc:
relationships
plotted :
Here's the same thing with three sets of email addresses treated as equivalent and aliased to each other when the whole thing is rendered :
Here's the same thing with both equivalencies and a
cluster
of email addresses — for example, all
the addresses for a group of people who work together
— represented by ... a box. Oh well :
Finally, the code to do all of this is :
my $graph = ASCOPE::Email::Graph->new({'obscure' => 1}); $graph->add_mbox("/path/to/mbox"); $graph->add_equivalencies(["me\@work.net", "me\@home.net", "me\@gmail.com"]); $graph->add_equivalencies(["buddy\@cheezburger.com", "bud.dy\@ohhai.com"]); $graph->add_equivalencies(["girly\@cheezburger.com", "grrrr.ly\@ohrly.com"]); $graph->add_cluster(["buddy\@cheezburger.com", "bud.dy\@ohhai.com", "girly\@cheezburger.com", "grrrr.ly\@ohrly.com"], "cheezburger"); $graph->as_png("/path/to/graph.png");
Clearly the next thing to do is to teach the code to read in an address book and generate those equivalencies and clusters on the fly. Maybe I will do that before another three and half years have passed. Colour-coded arrows too but that looks like it might require actual work...
Related, there are some interesting threads to pull by
FOAF-ifying all those addresses and feeding them back in to the cloud. (The code already supports the hashing of addresses; I
just obscured everything in the examples above because I
ph33r you.) I doubt this will ever happen because one
side-effect of the current social share-my-graph fetish is
that it will be even easier to dereference and harvest
mbox_sha1sum
addresses — and the Creepy People
surely will — but there are certainly some possibilities to explore.
Meantime : ASCOPE::Email::Graph.pm 0.2
This blog post is full of links.
#rocksYour door is an Interjar
With the enormous amount of money and effort it takes to get together with people you barely see, all of the tensions will be exaggerated. I can see people saying,
I spent all this money, I came all this way and for what?It’s supposed to be a certain way. It puts an enormous amount of pressure on those kinds of contacts and connections that wouldn’t be there normally.
ZOMG!! ADDRESSBUCKET RUN OUT OF INODEZ!!!!
There's a pretty great video, making the rounds, of Dan
Hill's presentation at Interesting South titled : The
Well-Tempered Personal Environment
.
It's basically the idea of displaying real-time consumption stats on or nearby your fantastic Earth-destroying lifestyle-enhancers (read: the faucet) to help you better appreciate the old saw about thinking globally and acting locally. Fantastic! Everyone loves data pr0n and to the extent that it reminds people that we still live in a community of individuals I am all for it.
As an (increasingly tangential) aside, the only part that
irks me is where the whole idea is wrapped up the games
and play
. spandex. This is standard
design-for-shame, as well it should be, and pushes all the
same buttons that make you invite people over for dinner in
order to force yourself to mop the floors. I like playing
games too (actually, that's a lie) but this is a perfectly
acceptable crutch while we work on the larger issue of human
sloth and greed so let's at least be honest about our
motivations.
But that's not what I wanted to talk about.
At one point he says Well, these are just mock-ups. We
probably don't want to walk around with big numbers floating
over everything. We'll want something more in the
design of everyday
things vein.
Which I thought was curious because it seems so very wrong. Or rather, no one really wants to interact with any of this data. They just want it to be continuously partially present.
Consider Twitter : The part where your phone is either pestering you its horrible YOU HAVE A NEW TEXT MESSAGE sound every two or three minutes, just so someone can tell you they're making hummus — or the part where Continuous Partial Attention is greedspeak for Death By Micropayments if you don't have a phone with unlimited text messages — generally means that people turn off the notify-by-SMS feature.
I would have never bothered with Twitter if I hadn't able to have incoming notifications sent to my IM client where I can continously partially ignore them.
ZOMG!!! WE IS TEH ROBOT SOCIALLORDZ IN UR SAVIN!!!!
But when I woke up with a hangover, last week, I couldn't even be bothered to reach out and switch windows, and then fiddle with tabs, just to know that Dunstan was doing push-ups in bed. I did not want to move but I was awake and staring vaguely at my screen hoping that the power of my social network would simply give me Digital Brain Rub.
Having nothing at all to do with hangovers, you can trace this long line of desire from the movies,
to television, to IRC backchannels and hecklebots at
conferences, to Twitter itself and then the public Twitter display at
SXSW in 2007 (hardly novel, O'Reilly also did something
similar with its attention stream
at ETech in 2005), to
screensavers, to digital frames ranging from consumer level
devices tied to partner providers to spaceship-aware
Linux distributions wrapped up in shiny paper all the way to
full-on Ray Bradbury
installations.
I know some people who say things like : I want to be permanently
jacked-in to the Internet! I want to have a direct IRC-link to my brain!! I
WANT TO SEE LOGFILEZ ON UR FACE!!!!
Okay, no one's
actually said that last part but it's what they're
thinking. And while I think it's mostly crazy talk —
try to imagine the world around you pulling a cover flow everytime you turned your head
— I also think it ultimately comes from a good
place.
One really fantastic by-product of the Network is that it has afforded people, still separated by the cold hard heart of flesh and blood and time and space, the ability to maintain enough shared experience to keep relationships in bloom. Make no mistake : We all die some day and no one wants to be lonely in the tiny bookends we manage to tease out of time's ... continuous partial attention.
The argument that Internet is, as the
drunken 23-year old PolySci student I lishly tried to have a
rationale argument with described, a great
isolator
has some merit. Watching people pass hours in front of their
computers playing games, writing code or ranting (is there a
difference?) otherwise indifferent to any warm-blooded
creature nearby is enough to give anyone pause.
I've watched the cycle enough, though, to be pretty certain that's not the case. Sooner or later all communities that comes together online meet offline whether it's gamers who fly to distant towns to, yes, play games together in the same room, or Flickr users who meet to take pictures together, to the 2 to 70 people who have met regularly every month for six years running and share nothing more in common than a city and an appreciation of weblogs, the Internet and beer.
I think everybody instinctively knows that a life online
is not enough by itself but that understanding is also not
always enough to push us beyond the predjudices and insecurities
we bring to a room
full of strangers. When it works, the Internet and an
individual's ability to project something about
themselves out there
provides just enough of a bridge
between people who've never met to want to entertain the
idea of a friendship.
Societies have always had norms and conventions for doing the same thing and they've always kept pace or adapted themselves to the available technologies. That the Internet allows people to More Better dance the tune on their own terms I think is an improvement.
But I was talking about Twitter, wasn't I?
ZOMG!! I WAS YAWNING AND THEN I BURPED!!!!
If the Internet is a single bridge connecting two people at the start of a relationship I like to imagine it becoming a series of bridges over a canal that keep the land on either side of the water from straying too far.
Again, you could replace Internet
with
available media
and follow the same thread back
through history as
far as you wanted.
What's changed obviously is the collapsing of the space between the sending out and receiving of our bird calls. A permanent arrivals and departures lounge of human relationship, where everyone you know is paging you on the white courtesy phone (in your pocket).
This too has long been talked about but since it's only now becoming a practical day-to-day reality so we're finally struggling to figure out whether or not it was a good idea.
Chris summed it up nicely earlier this year : Of course, it doesn’t mean anything will necessarily
happen, but you’ve created a possibility space for things to
happen in.
I sometimes complain about especially enthusiastic Twitter contacts
but, really, I am delighted by the whole thing. I love
being a able to share a frame of reference — a pithy
text messages or photos or music; anything important
(important
) enough that you might share it over a meal,
— with people who can't
be near, either because of geography or mundane daily
circumstances. It's a kind of jerky stop-motion animation frame
of reference, for sure, but without it you are deaf to the tiny
anecdotes in a person's life; the daily rituals and gradual
changes in tone and focus that help to nuture the understanding
and appreciation of a friendship.
A possibility space
.
ZOMG! IM IN UR MEMREEZ PRETENDIN I WUZ THERE!!!!!
Of course, it doesn't take long before it becomes a lot of, and usually too much, work to sift through all that chatter. Especially when you're hungover. Which is why I sitting there, drinking coffee, thinking : Wouldn't it be really nice if new messages could Just Appear in tasteful, discrete windows. Something like Growl notifications. Then the nice people at Google reminded me that I had already written the thing that I was looking for.
At the time, I still wanted to get notitications on my
phone but found everything about the experience of receiving
them via SMS unpleasant. Instead of my phone acting like a hyper-active
personal assistant
squealing with delight every time
a new message arrived, I wanted something more like ... a
mood ring.
It would be silent, except for maybe the option to
vibrate and instead of conventional system notifications it
would just hover a great big number over the idle
screen indicating the number of unread messages. Okay,
that's a half-truth if there ever was one : I did add the
big floating numbers but that was as much to act as an
indicator that the phone's operating system hadn't silently
terminated my application.
Since then I've grown fond of the big numbers on their own merits. What I'd really like is to fill the idle screen — when the phone is, uh, idle — with those big numbers.
Possibly ambient.
I wrote a Growl enabled version, using the Twitter API, mostly as an afterthough because it seemed like a neat trick and it was an additional 4-5 lines of code.
I never got very far with it. The actual interface for reading the messages was crude at best and I had spent most of my time thinking about and then building the floating numbers. It was also during a period when the Twitter API itself was pretty flakey so the messages I did receive always seemed strangely out of sync with reality. It was also around the time the mobile version of the site went live and, experience porn aside, that ultimately proved less demanding to use.
As for the desktop version, it suffered from the same problem that plagues feed aggregators : keeping track of what has or hasn't been seen. Not a hard problem but it's an extra bit of complexity (remember, I was also trying to write an underlying layer of code that would continue to work on my phone...) that makes you wonder whether you couldn't be doing something more fun with your time. I also tend to work on a variety of different computers and the nuisance of doing the magic sync dance between them, so that I don't always seen the same 25 notifications everytime I log in to a different computer, finally answered the question for me.
ZOMG! IM IN UR CLOUD CRYIN UR TEARZ!!!!
Did I mention that I was hungover and I was smitten, once again, with the idea of little, well-behaved messages hovering on the periphery?
I often work in the kitchen when I'm at home and what what I've
wanted for a long time was a sexy hecklebot, hanging over
the counter, that could talk
to all the various APIs out there and show
me what's
going on in a world that consists only of my
friends.
There's a reasonable argument to make that this is what services like Facebook do but since I hate Facebook it's not.
This has always been my attraction to the RedPost/Kit digital frame which does something like this already for Flickr feeds. Maybe still but I wasn't about to get one that afternoon so I continued to sit and stare at my laptop.
There was no blinding flash of insight or anything.
I had already resigned myself to the constaints that Growl imposes on its notification windows : icons are a fixed size; there is no (easy) way to define custom callbacks when a message window is clicked and no way to render or format messages as anything but plain text. The only issue was how to deal with keeping track of messages across multiple computers. I had decided to build myself a notification system for Flickr events.
Or, in the English people who aren’t venture capitalists use,
I don’t kill my own chicken for Sunday dinner anymore, why should I provision my own server?
I don't actually agree with the underlying argument
that's being made there but it does nicely sum up the part
where in order to do anything across multiple computers you
need something that looks like a database (even if it's just
a list of unique identifiers) and then some sort of web
interface and then a security model and then all the other
crushingly boring details just so you can say :
26452625141 = 1
.
It's possible that my reluctance to use any of the web services (AWS) that Amazon has been releasing over the years has been motivated more by ph33r rather than reason but I've never completely understood what or why they were getting at by offering any of this stuff so I've kept to the sidelines and watched.
I have already used del.icio.us and Stikkit as floating databases for other projects but using either to store nothing more than a boolean value or a timestamp seemed about as classy as asking Flickr to store text files
.
Even the still nascent DWIMD^H^H^HSimpleDB (which will probably do more to advance the ideas behind the Semantic Web than all the articles TBL could write on the subject in a lifetime) is overkill, though it might be sort of interesting to go back and build a day-by-day scrapbook of notifications.
But I digress. I decided to bite the bullet and try S3.
ZOMG!!! MOUTHFACE FULL OF WORDZ!!!!!
Instead of reading or writing a flag to a local database,
the code
fetches or creates a web page whose URL contains that flag. Pedants will
tell you that is to : GET
or POST
a resource
on the Internet;
which is also why they're a bunch of tiresome doorknobs.
This has the advantage of being both portable and fantastically easy as well as flexible since the thing at the end of the URL is, ultimately, just a text file that we can append stuff to ad nauseam (or up to 5GB if you are a tiresome doorknob).
And is costing me both cash dollars and some amount of privacy.
S3 is a billable service and Amazon is a big centralized for-profit company with a penchant for data-mining. I have yet to get my first bill but between local caching, the relatively tiny rates of data transfer I am doing and the quick-look-over-here truly micro-payments schedule that Amazon has put in place I figure it's worth trying until my next credit card bill arrives.
The privacy thing is stickier and I remain skeptical about putting anything I really care about in Amazon's cloud. In principle, the things I'm looking at on Flickr could come back to haunt me but my gut tells me that there's nothing I wouldn't freely admit to and if I really feel like that's a plausible risk, today, we're already fucked. Plus I am hashing the keys for every event notification.
Then I remembered that this entire exercise was about active notifications and not building an answering machine in the cloud :
$> python ./bin/flickr/flgrowler/flcontacts.py -c flgrowler.cfg [Thu Dec 20 21:44:58 2007][flcontacts] sleep for 120 seconds [Thu Dec 20 21:47:13 2007][flcontacts] can not find beaconing device, skipping [Thu Dec 20 21:47:13 2007][flcontacts] sleep for 120 seconds [Thu Dec 20 21:49:28 2007][flcontacts] 0a:18:42:b8:30:4a is nearby [Thu Dec 20 21:49:40 2007][flcontacts] received 17 new events (50 total) [Thu Dec 20 21:49:58 2007][flcontacts] sleep for 120 seconds
(If blog posts had code-names (we would be doomed) then this one would be : To Timo, with love.)
I have given the near-field communication
people a
hard time over the years mostly because some of the
creepier privacy and security issues are waved away with
Dubya-like assurances of technological advances
that
do not inspire confidence, but
even I can see the potential. I just think — hope
— that after it's baked for a while it will be more
... yes, serendipitous in nature than
utilitarian
or a tool for discovering
the
nearest
fucking Starbucks.
A couple of the projects at the UK Hack Day event, in London this summer, were built performing magic with the Bluetooth network but when they got up to demo there were so many Bluetooth devices in the audience that the software was crushed under the weight of the possibilities.
Anyway, if two machines are running event listeners
simultaneously — each reading and writing to the S3
cloud — and you don't happen to be in front of the
one that receives an event first you'll never see it since
by the time the second computer finds out about it it will
have been marked as seen
.
So, accepting the truism that people generally keep their phon... I mean, their devices nearby (enough), this is how we handle the problem :
- Start the application or wake up from a previous cycle.
- If the config file has a list of Bluetooth devices :
- First check to see we have the address of a previously seen device and explicitly request the device name
- If not, or the operation fails, perform a general query of devices nearby, and look for a match with the list defined in the config file.
- If present, store it in memory so that we don't
(necessarily) need to do a broad poll on the next
pass. This may just be a function of my not
understanding how the PyObjC Bluetooth bindings work
but in casual testing a broad
find devices
query would often time out without necessarily getting to a known-good device. So this is just easier. - Also, I know about
and love the Lightblue Python Bluetooth
bindings but if you call the
finddevices
method a second time before the first instance has completed it will make your CPU cry. Talking to the Bluetooth frameworks directly is easier which should tell you something given how bent programming in Objective C is...
- Open the datastore.
- If the config defines the datastore as an AWS S3
bucket then the application will reach out across
the network and ask AWS for a list of all the
buckets associated with the access key defined in
the config file. If the bucket described in the
s3_bucket_prefix
config is not present it will be created.
- If the config defines the datastore as an AWS S3
bucket then the application will reach out across
the network and ask AWS for a list of all the
buckets associated with the access key defined in
the config file. If the bucket described in the
- Fetch and parse a list of
events
via the Flickr API. Events is just fancy-talk for a list of results for a question you've asked Flickr : What sort of activity has there been on my photostream? What photos has this user favourited? And so on - For each item returned generate a unique identifier and
check to see if there is a corresponding key in the
datastore. If there is, the item is considered as having
already been seen and is skipped.
- If the config defines the datastore as an AWS S3
then the application will reach out across the network
to see if there is an actual
thing
on the Internet that can be addressed with the UID.
- If the config defines the datastore as an AWS S3
then the application will reach out across the network
to see if there is an actual
- For any remaining items, the application will build
a custom message, fetch a thumbnail for the corresponding
photo and issue a notification request to the Growl
daemon.
- At the moment thumbnails are stored in what your
operating system thinks is its
temporary
directory. There is currently no attempt to clean up old images. That, along with a user-defined directory in which to store thumbnails, will be added in future releases.
- At the moment thumbnails are stored in what your
operating system thinks is its
- Add an entry for the unique identifier in the
datastore. If the identifier is the key in the datastore
then the value is the current time formatted as a Unix
timestamp.
- If the config defines the datastore as an AWS S3
then the application will reach out across the network
and create a
resource
on the Internet that can be addressed with the UID.
- If the config defines the datastore as an AWS S3
then the application will reach out across the network
and create a
- Sleep for (n) seconds as defined in the application's config file.
In the end it looks something like this :
ZOMG!!! NO BUKKAKE IN UR CLOUD!!!! FAIL!!!!!!
There are three event listeners, so far :
- flactivity, which polls the flickr.activity.userPhotos API method for any new activity on your photos in the last two days.
- flcontacts, which polls the flickr.photos.getContactsPhotos API methods for new photos from your contacts.
- flavourites, which polls the flickr.favorites.getList API method for newly favourited photos from a pre-defined (in a config file) list of your contacts.
The core event listener functionality will shortly be packaged as a separate library so that I can write a Dopplr agent, finally rewrite the Twitter version and then whatever else comes to mind.
Aside from the limits in functionality imposed by Growl itself there are two immediate concerns I'd like to address next :
The first is what to do about window spam after you've been away from your computer for a while. When I sit down at my laptop in the morning the first pass of the newly active listeners will tile my entire screen with event windows. I have taken to scanning them quickly and then just restarting Growl since clicking on each window, to close it, is really boring. Perhaps, the easiest thing to do would be to create a digest of all activity older than, say, an hour and display it as a single notification...
The second issue won't be an problem until I work up the courage to port all of this to Series60 Python but when I do the NFC beaconing code will need to be rewritten to check not only that a given device is within range to display events but also to stop displaying events if another device is within range. That way, you could receive notifications on your phone while you're out and about and then have them switch your computer when you get home.
Or, more likely, have notifications automatically disabled whenever your boss gets within 32 feet...
ZOMG!!! I R NOT LOLCOLORZ!!! BUCKET FULL OF FREEDOM!!!!!
Finally. I still find the whole river of dashboard
metaphor, in which I would include the Growl-y bits I've been working on, mostly boring.
I use a feed aggregator for anything that could loosely be classified as news and lifestyle porn and it works great. I even use it to find out when people I actually care about have posted something to their weblog but I absolutely hate it for reading what they've written. Maybe I am the hold-out but I still value the web for the time and effort and consideration that a person puts in to their web pages and I think that gives whatever they are talking about context.
If I want to be notified at all of when something new has happened, I would like a way to feel the (proverbial) elephant rather than have it join me at the table. It's a bit vague, obviously, but there's got to be something more interesting — more fun — than the way we recycle everything as slices of 99 cent pizza, today.
You'd be forgiven if your bullshit detectors are ringing right now because it's definitely a bit pie-in-the-sky. What little I am sure of is that I don't enjoy the way we leave markers in the forest of songlines that the Internet has become and that there's room for a little more art in it all (and maybe an overdue appreciation of Josef Albers) because that is what relationships are made of.
So, yeah. Big floating number friends : flgrowler.py 1.0 and beyond.
ZOMG!! IM IN UR INTENT RUNNIN FROM UR INTERPRETIN!!!!
Update.
Not long after this piece was first posted Adam Greenfield found it in his referer logs and wrote a frank and biting rejoinder. I mention it, here, because :
- Questions about my biases aside, he makes a compelling argument and has a point.
- I wouldn't change
anything I wrote. Or, put another way :
From : Aaron Straup Cope To : Adam Greenfield Subject : point taken If there was intent, vis-a-vis the ratio of male to female pointers, in that post then it certainly wasn't conscious. As for the bit with the bukkake, there's really nothing to read into that. Really. Bad taste? Perhaps. I can live with that. If someone wants to read anything more than me making a silly joke about the underwhelming nature of the post -- which was really a ridiculous amount of background leading up to some pretty Spartan code -- then I'll meet them at the bar because we'll have an argument to work through. But, point taken. Cheers,
The only part that I will take exception to is the
pithy comment about the del.icio.us-style
links at the top
of these pages.
They are, in fact, a collection of links that the people in my del.icio.us network have posted, pulled automatically from the page's RSS feed, out of which a new list containing the most recent post per contact is generated. If that list happened to contain a perceiv^H^H^Hambient gender bias on the day that Adam came by, then ... I guess I blame Joshua.
I expect that we'll see more misunderstandings like this, where meaningful intent is confused with the automated faceting of a person's presence on the Network, going forward.
Anyway, if you've made it this far go read what Adam has to say.
This blog post is full of links.
#zomg