this is aaronland


“Like Twitter, for photos”

Steve Jobs' comments about the iPhone's controlled environment were probably the best thing the people at Nokia heard all week.

I occasionally get asked how I got in to computer programming and why I keep at it. The answer is pretty simple : Because no one else seems to want to write the kinds of applications that I want to use. This is even more true of mobile-computing-device-phones :

Sometime between 2007 and 2014 these photos were lost in translation.

There's still a lot of polish needed on this thing, but the basic framework is there to aggregate, trigger an alarm (read: make the phone vibrate) and display photos from any Flickr API method that returns the standard photos response. It looks like this :

1  | # s60_include : /home/asc/lib/python/s60-simplejson/
2  | # s60_include : /home/asc/lib/python/s60-simplehttp/
3  | # s60_include : /home/asc/lib/python/s60-simplestore/
4  | # s60_include : /home/asc/lib/python/s60-simplenumbers/
5  | # s60_include : /home/asc/lib/python/s60-simpleflickr/
6  | # s60_include : /home/asc/lib/python/s60-simpleapp/
7  | # s60_include : /home/asc/lib/python/s60-simpleflickrapp/
8  |
9  | class flickrwidgt (simpleflickrapp) :
10 |
11 |     def get_flickr_photos (self) :
12 |          return self.flickr_api_call("" , {'count':50})
13 |
14 | if __name__ == '__main__' :
15 |
16 |    key    = 'yer flickr api key'
17 |    secret = 'yer flickr app secret'
18 |    token  = 'yer flickr auth token'
19 |
20 |    app = flickrwidgt(key, secret, token)
21 |    app.loop()

Which is convenient since the method could just as easily be dropped in and Python could do something crazy like ... talk to a GPS device and show nearby photos. I actually had a no-less finished version of this working for 2nd Edition Python so it ought to be easy enough to get it working for 3rd edition. Easy.

The part where you have to hard-code the Flickr API tokens is not a feature. I just haven't figured out what or how I'm going to do about it. If I can get at whatever folder SMS messages or web downloads are stored in then I suppose I will just try to read configs from there.

Until then, here's the un-SIS-ified source code if you've got the stomach to plug in your own values and bundle it up in to a binary :

Finally, if I rebuild the Twitter notification agent with all the s60-* libraries listed above and it Just Works™, then I will spend my morning coffee this week writing documentation and releasing proper packages.

Alpha Alpha! Disco Ball!!

At this point, I am just writing documentation away from releasing proper packages for the code that runs my new minty fresh Twitter notification agent (that actually works under Series 60 3rd Edition Python).

Aside from the part where it sits in the background and asks Twitter for updates every ten minutes, it will also make your phone vibrate when new messages arrive and display a little floating window indicating the number of unread messages.

The Twitteriness of the application is kind of secondary, really. It's certainly nice given the lack of a proper mobile website for the service and the cost (both financial and psychological) of being clubbed by text messages but simply creating yet another delivery mechanism for your friend's idle banter is not going to make anything move beyond your phone.

The thing that I like is that it can double as the rough skeleton to handle the boring bits for any old notification / aggregation agent. Other obvious candidates include recent activity on your Flick photo stream or recent photos from your contacts using the nifty floating window to display thumbnail versions of the images. But the point is : The phone is connected to the Internets and there is no end to the sorts of things you could do.

(Finally being able to to scratch an itch is pretty nice too.)

Presumably it won't be long before someone comes along and says this is what [insert yer syndication format of choice here] is for. This is true except for the part where it's not. At least not the way feed aggregators are currently designed (and, as I never get tired of pointing out, because Series 60 Python doesn't have a built-in XML parser).

Bouncing dock indicators are nothing new on the desktop and it would be easy enough to add similar event handlers to the Series 60 syndication app or even to have it make the phone vibrate. But a calendar is also a kind of aggregator when you get right down to it and few people would suggest, with a straight face, that managing dates and events in a river of news is useful or practical. Exaggerating a little, you might say :

They illustrated the truth that when public housing is at stake, there is not always much to choose from between left and right: Franco's Spain produced the same results as Brezhnev's Russia or Pompidou's France, because abstraction, incuriousity, and greed are among the common attributes of mankind.

— Robert Hughes, Barcelona

(Also : the first one of you to say that a calendar's day view is a river of news gets a river of shut the fuck up.)

Your SMS inbox is an aggregator (a literal river of bells and whistles) and mobile carriers have had SMS updates of all flavours for a million years. People have been using both in droves but that doesn't change the part where SMS itself pretty much sucks. People use it in the absence of anything better. Or in the case of many of my own friends and Twitter, not at all.

The de facto syndication framework(s) that have grown up around weblogs are fine but there is more to sharing stuff on the Internet than just shoving everything into the same format. It would be easy to pick on HTML email (or wacky ideas like broadcasting web server logs as RSS) but one has only to look at the never-ending debate about what and how to pass around the contents of a feed item to understand that one size breaks all.

The adoption of RSS by the weblogging community was a fortunate and convenient hack but it's worth remembering that it wasn't until, what?, last week that Blogger added support for the most basic of syndication elements : titles.

I wouldn't want to leave you with the idea that I think that anything I've done is necessarily better. The instant messaging hooks for Twitter have, by all accounts, been a huge success because they've allowed people to use the service in a way that fits their daily habits rather than suffering the siren calls of text messaging. Since instant messaging on the phone is either too painful or too expensive to be useful, I'm just happy that I have the beginnings of the tools to do things on my own terms.

See also : Like an IM thingy.

This is the part where the conversation rapidly descends into hand-waving and teeth-gnashing rants about doing everything on the web / in HTML (in fairness, Nokia's new browser is a pretty good argument for that; it has become the main reason I don't want to use 2nd Edition Series 60 phones...), the inability of browsers to interact with the rest of the operating system and the best way to scrumjax your phone whether it's using a separate built-in webserver or with some sort of glue between JavaScript and the core APIs. Securely. And abstractly. And easily.

Pick two.

The great thing about being able to see the future on the horizon is that there are so many different ways to try and arrive...

Meanwhile, in the Boring Details department :

The application does not have support for keyboard events (yet) because these are apparently not accounted for in the list of capabilities included with the developer's certificate. I'd like to believe that this heralded a near (field) future where I could control my Nokia device-phone with my mind but somehow I doubt that is the case. I will get this one sorted out because being able to add a global keyboard listener is going to be important to toggle between images, from the default standby screen, for any sort of Flickr application.

Generating a working SIS file is now a three step process : Write the code; Buildify the code to squirt in the source for the various shared libraries; Finally generate a signed SIS file.

Or :

$> python ~/lib/python/s60-tools/ buildify ./ > ./

$> py2sis--caps="LocalServices+NetworkServices+ReadUserData+WriteUserData+UserEnvironment" \
         --verbose ./                     

Or :

 1 | # -*-python-*-
 2 |
 3 | __package__    = ""
 4 | __version__    = "1.0"
 5 | __author__     = "Aaron Straup Cope"
 6 | __url__        = ""
 7 | __cvsversion__ = "$Revision: 1.6 $"
 8 | __date__       = "$Date: 2007/01/21 04:45:49 $"
 9 | __copyright__  = "Copyright (c) 2006-2007 Aaron Straup Cope. Perl Artistic License."
10 |
11 | # s60_include : /home/asc/lib/python/s60-simplejson/
12 | # s60_include : /home/asc/lib/python/s60-simplehttp/
13 | # s60_include : /home/asc/lib/python/s60-simplestore/
14 | # s60_include : /home/asc/lib/python/s60-simplenumbers/
15 | # s60_include : /home/asc/lib/python/s60-simpleapp/
16 |
17 | import time
18 |
19 | class twitter (simpleapp) :

Or :

  1. simplejson.pyEverytime you use an angle bracket, God kills a member of the W3...I mean, a kitten.
  2. — Nothing special; just your standard HTTP GET and authentication cruft.
  3. simplestore.pyWe've secretly replaced support for anydbm, in 3rd Edition Python, with support for e32dbm. Let's see if anyone notices!
  4. — Pass it a number and the code will generate a pixelated image of it. This is used in conjunction with the new topwindow module to display a persistent hovering window containing the number of unread posts. (It's also a handy indicator of whether or not the OS has killed off the application as Series 60 is want to do without warning...) I wrote it mostly because there's a known bug with 3rd Edition Python builds where text doesn't render properly in image objects. And big square numbers. Obviously.
  5. — All the standard set up and take down code for a Series 60 Python app, plus glue for handling notices and error messages.
  6. — Simple. Tools.

All of which means the rapid part of developing applications for Series 60 in Python is kind of a joke but in the grand scheme of things it's probably worth it to keep all that code in separate files.

So, until the final testing and packaging is done :