this is aaronland

Trying not to cut down the trees for an inability to see the forest

mmPDF.php 0.3

        doap:Version    [
                        doap:revision     "0.3" ;
                        doap:created      "2007-08-14" ;

        asc:changes     [
                        asc:addition      “Support for del:bookmark=geo feeds” ;
        		asc:addition      “Support for KML files from” ;
                        asc:addition      “Basic support for ModestMaps web service” ;
                        asc:addition      “Basic support for indexes at the end of a document” ;
                        asc:addition      “Optional max (items) parameter for 'add_map' method” ;
                        asc:addition      “Include Mike Migurski's JSON PHP class as part of the distribution” ;
                        asc:addition      “Include qr PHP class as part of the distibution” ;
                        asc:addition      “Include pmPDF PHP class as part of the distribution” ;
                        asc:addition      “Include MachineTag PHP class as part of the distribution” ;
                        asc:addition      “Include Restobook PHP class as part of the distribution” ;
                        asc:comment       “Indexes are fugly; eventually this code will be moved in to pmPDF.php“ ;
                        ] .


Actually, enjoy version 0.31, more. Also, pmPDF.php has been updated and released as version 0.5.

Small details, loosely crushing each other

Paris, Rome, London, Montreal, San Francisco and the place where the physical and digital world intersect.

We'll take it as a given that no one has map tiles especially well-suited to piece-of-shit consumer printers, yet. In the meantime, I have added support for maps to the mmPDF PHP classes I wrote for my talk on the Papernet.

mm used to stand for MyMaps. Eventually there was an option to generate map images using ModestMaps; this is done using a bare-bones HTTP interface around the script and will be checked in to the SVN trunk Real Soon Now was checked in as Revision 339 to /trunk/py. Since then, I've also added support to suck places out of Platial and ; again, expect a code release just as soon as I sort out the remaining details — the formatting on the addresses in the screenshot, above, for example — or at least write documentation with the release of mmPDF.php 0.3. So, I guess mm just stands for mm, now.

Oh, and remember the barcodes? Good, now imagine a world where had a proper mobile website for editing and posting addresse...I mean, links. See?

For extra points, consider all the chatter surrounding Atom (the publishing part) and Google Earth...

An update and a tease :

      7 |        require("mmPDF.php");
      8 |
      9 |        $modestmaps = array('server' => '',
    10 |                            'provider' => 'GOOGLE_ROAD',
    11 |                            'marker' => 'YAHOO_AERIAL');
    12 |
    13 |        $qr = array('data' => './qr_data',
    14 |                    'images' => './qr_images');
    15 |
    16 |        $args = array('folds' => 0,
    17 |                      'source' => 'modestmaps',
    18 |                      'modestmaps' => $modestmaps,
    19 |                      'qr' => $qr);
    20 |
    21 |        $pdf = new mmPDF($args);
    22 |
    23 |        $pdf->SetFont('Helvetica');
    24 |        $pdf->SetFontSize(10);
    25 |
   26 |      $pdf->add_map(“chris heathcote's massive mymaps dump of yummy d in paris”, 5);
   27 |      $pdf->add_map(“my geotagged bookmarks for coffee”);
    28 |
    29 |        $pdf->Output();

At this point, I think that the only thing left to do is packaging and documentation in advance of the next code release, including an updated version of the maps web interface. I'm not sure what to do in the way of barcodes for MyMaps feeds so I may just leave that one for later. After that, I will add tag-based (and properly formatted) indexes to the long list of tiny details.

But for now, here's a big PDF file instead.

[N]othing would be gained from pursuing the abstractions...

Yelp released their API the other day so I added hooks to the maps project to pull in Yelp listings within a one-mile radius of any geocoded query. In the screenshot, above, the result for 1062 Valencia San Francisco CA is displayed in the top-left corner and nearby stuff, from Yelp, around it. This is good since it makes it easier to generate restobook style descriptions and generally be more precise (than the freakishly bad reverse-geocoding done by geonames) when tagging neighbourhood and city.

I will post an updated public version next week but in the meantime here's the part about the API that's not mentioned anywhere in the docs :

You can filter search queries by category; more goodness. However not only are those categories not listed anywhere in the documentation they are also not returned as part of the list of categories for an individual search result. For example, El Farolito returns mexican but is filtered on by restaurant, by passing a category parameter. Anyway, if you sniff the URLs in the Browse By Category list on the front page you can find a useful list of terms to limit queries by.

Also, if you think this is all crazy-talk consider the recent announcement about support for Microformats in Google maps.

S60 Stikkit 0.1

I always feel bad when I don't say nice things about Stikkit.

I was poking around, yesterday afternoon, for a recipe for Swedish ginger cookies published a while back in the New York Times.

Eventually I found it on Chowhounds and, for safekeeping, promptly copy-and-pasted it in to Stikkit.

Then I thought about printing out the recipe all properly formatted and nice-like.

Then I simply wrote the recipe down on an index card.

Then I thought about taking the index card — as in the list of ingredients — to the store.

Which got me thinking about printing again which is really a trap door in to the abyss.

Then I got a little depressed.

Then I pressed F12 (the magic key to display the extra handy Stikkit Dashboard widget) a few times and thought : It would be good to have this on my phone. So I wrote an application, in Series60 Python, to just that.

Specifically, it does exactly three things : Lists your (recent) Stikkits; Displays a Stikkit; Allows you to create a new Stikkit. That's it (modulo tweaks to the posting interface because the Series60 Form widget blows).

Then I got depressed, again, because I mistakenly thought that the current release of S60 Python (1.40) was yet-another clusterfuck of undebuggable fatal errors. Eventually, I realized that I had simply forgotten to import generators from the future. Then I got depressed again.

But, at least it works : (S60) Stikkit.SIS 0.1

(Where works means you'll need to get an API key.)

The Scribblenet

Executive Summary : Data, Not Answers

A little over a year ago, I came back from Helsinki and resolved to finally get around to learning Nokia's Series60 Python. This is what I wrote, about a month later, when I posted the first release of an application called restobook :

But I'd managed to do enough hacking to get a feel for how things worked and I started to think about what else I could suck in to the address book. Restaurants seemed like an obvious choice and keeping restaurants listed in also seemed like a good idea. I suppose there are legitimate privacy concerns but to my measure they aren't a big deal and don't outweigh the benefits : Ready-access from any web browser, not having to deal with synching and just otherwise sharing with the community. For example, I spent a lot of time poking around /helsinki and /helsinki+restaurant before I left for Finland and it was very useful.

In March, of this year, I sat on a stage and told people not to despair (too much) since pretty soon all applications would be written as glorified web pages. I was the Doom & Gloom guy on a panel about the current state of mapping, having by then spent more time than is healthy trying to build tools using S60 Python. The short version is that the Symbian 9 security policy, which dictates the functionality an application can use, is dumb and lazy and cumbersome. In effect it makes doing anything so painful as to be impossible.

All the talk about whether Perl, Python, PHP or Java will assume the mantle of lingua franca on the Internets has become moot since JavaScript already is. The recent announcement that Mozilla's next JavaScript engine, Tamarin, will also be a container for functionality written in Python and Ruby (and, one assumes, beyond) is proof that JavaScript is the new Parrot.

In May, I sat in the audience while a nice chap from the Nokia Research Center (NRC) demonstrated an address book application running on the phone and written in HTML + JavaScript, specifically a JavaScript wrapper around the device's core Series60 C++ APIs. At the end of his presentation he sheepishly admitted that they hadn't really bothered to sort out the problem of how to deal with the security restrictions. This was a research project, after all, so they fudged it which is a curious variation on the whole idea of vapourware.

As I started grousing to the person sitting next to me another Nokia employee piped up and demanded whether I thought they should be releasing insecure devices on the market. This is a mostly spurious argument because the answer is obviously no but that is not a justification for the remarkably bad design and implementation of the Symbian 9 security platform which mandates that all applications be signed by Symbian which, at the end of the day, means that all developers are suddenly held hostage.

The mobile community is especially curious in this respect, partly due to the history of cellular phones : They operate under the assumption that you should be grateful you are allowed to build anything in their magic gated communities. It remains a mystery whether they are too dumb, or just willingly ignorant, to see that mobile devices have become nothing more special than really small computers with any number of arbitrary network connections. And like any other computer, or platform, its value is directly tied to the willingness of and the ease with which developers can write tools on top of it.

Whereupon I counter all arguments to the contrary with The Sword of Flawless Victory called Facebook.

In June, Steve Jobs announced that developers could write applications for the iPhone as web applications, with all the usual blather about security and mobile devices. Everyone groaned. As if a company that's been selling operating systems for 20+ years can't figure out how to create an environment where developers and users can play nicely, and safely with each other.

It is worth noting that Apple already has a way for users to develop tools as web applications. They are called Dashboard widgets and while they are still mostly just toys they are also just this : HTML + JavaScript + custom extensions to wrap low-level Objective C functionality. I can only guess that the security model here is the sum total of people (read: users) not being complete morons and the barrier to entry for any sort of programming that requires compiling.

I could easily be wrong but it's hard not to look at the tea leaves and think that applications for the iPhone — because no one can really believe in a world where it continues to exist as a closed device — will be written as widgets. The current thinking is that when the next version of OS X (10.5) is released it will come with all manner of sexy integration with the iPhone. Which is also when Dashcode, the development environment for creating Dashboard widgets is set to be released. My guess is that Dashcode will come with a special iPhone project and a series of, probably restricted, APIs for talking to the address book, and the wireless network and the phone and so on. Basically everything that S60 Python already does. And probably more.

Soon the winter months will come and the Finns will not see each other shielded by their masks of frozen tears.

I still don't own an iPhone and I'm not planning to buy one, any time soon, but all of that was enough to get me to revisit Dashboard which I normally just disable entirely. It continues to be a mostly underwhelming experience except for the Stikkit widget. I really like Stikkit, and it is a pretty fantastic example of what web-based applications can be, but the brutal truth is : I never really used it. It's just too much trouble to deal with in a web browser, whether it's typing out the URLs or clicking the links on the site or waiting for the browser itself. So I stopped bothering.

That is, until it (Stikkit) became nothing more than a really dumb notepad that does three things : 1) sits patiently in the background; 2) loads quickly 3) can be shared between disparate machines. You know, everything that the web is supposed to be. But isn't. There's no capital-R revelation in that one other than to slap the Mozilla will save us people in the face with a soggy fish.

Meanwhile, the NRC's quirky mobile web server has been re-born as a real-live and fully branded application. Which is interesting because under the cover this thing is just Apache (read: HTML) running Python scripts (read: JavaScript (all grown up) with extensions to the core C++ APIs). With permissions to do all the stuff that you can't do as a mere mortal (read: developer).

In May, I also stood in front of a crowd and told them about something called the Papernet citing, in particular, Google's MyMaps as an example of the place where the physical and digital world intersect. To make the point, I wrote mmPDF.php which will take a KML feed and create a nicely formatted PocketMod booklet. And despite the heavy precense of Google weenies, at the conference, telling us about all the magic GData APIs there are still no endpoints for doing anything with MyMaps, programtically.

Which is a shame because MyMaps is a really good candidate for a stripped down Dashboard style local application. Something that would allow a user to quickly enter unstructured data (geocoding and tags), handing off to the computer to do the rest work, storing everything in a standard format (latitude and longitude), and later generating a faceted version (all the restaurants tagged french in San Francisco).

So I wrote my own. Using machine tags and as the datastore.

By which I mean, it is nothing more than a web page that will load a (Yahoo!) map and provide a bare-bones interface for geocoding an address, placing a marker on the location that the geocoder thinks is the best match. The marker can dragged around the map to correct the location. When you double-click the marker, it loads the posting interface in an iframe passing the geocoded address and the latitude and lontigude data along with it. In addition it sends some extra marker tags, notably del:bookmark=geo.

The part where the tools uses an iframe raises at least one issue : It's hard to capture, let alone evaluate, events that occur in the iframe. It would be nice to be able to convert the previously dynamic marker in to a fixed one when the save (to button is pressed but I haven't figured that one out yet... The part where all the login/authentication nonsense is left for to deal with is almost worth it. Almost.

To find all of the things you've assigned geodata to you simply need to start querying for stuff tagged with del:bookmark=geo. Or del:bookmark=geo+restobook. And so on. More likely you'd do something like del:bookmark=geo+paris. If Joshua didn't hate machine tags so much, you might be able to prevail on him for the ability to say : What are the distinct values for, say, geo:locality= tags? That way you could create a nicer interface for browsing the available data and, potentially, make the application a little zippier. Come to think of it, it would be awesome if everyone who offered machine tags did that.

Um. Yeah. Did I mention that I did a whole talk on machine tags in June? Anyway, moving right along...

In principle, you can easily fetch and display those posts on any old web-based map by asking for results output as JSON. In principle because the JSON feeds are restricted to only public bookmarks and because the JSON endpoints are limited to individual users. (It also seems that you can only query on a maximum of two tags.) Which kind of sucks because I would like to see what other people say for helsinki+againagain. But these are design decisions and not anything inherently undoable. There is nothing to stop you from setting up a proxy server that performs authenticated calls to the entire API and sending back JSON.

In it's current iteration, it also does reverse geocoding using the Geonames web service, plucking out the names of each place and assigning them as tags. So far, the anecdotal evidence suggests this should be optional; anyone whose ever spent any time in Montréal know that Longueil is not the same as Little Burgundy. Other caveats include : It is still kind of ugly and I won't be surprised if there are still some gotchas with the draggable markers.

On the upside : It actually works, is easy and really simple to install. And it will Just Work™ with (assuming I ever get around to porting it to Series60 3rd Edition).

One of the next steps will be to update mmPDF.php to fetch a list of data points from I finally got around to writing the web service interface to the ModestMaps compose tool that I threatened about, a while back, so I'd like to try and bundle all of that up in one big release. As usual, we'll see.

And since I seem to be spending lots of time in meetings these days that should offer plenty of chances to clean up the interface. Do not pretend that I think it is pretty but right now my fingers are still bleeding like a thousand callbacks from having to work through all the nonsens... I mean fun that is programming in JavaScript. Suggestions and cluebats are welcome.

So yeah, my maps. My tasty maps.