GUI app retargeted from SDL to Web with just a little glue

scrottie on 2009-03-06T08:34:07

I was doing some SDL stuff for work and wrote a little wrapper around SDL to make it a bit easier to use. SDL's blit() function wants four arguments, two of which want four more arguments. Really all it needs for the common case is the image to blit and the x, y coordinates to blit it to, called as a method in the target image.

I wrote this app for my own use. I wanted to be able to visualize where the buses were (or rather, where they're supposed to be) when I'm standing at a corner. That way, if I'm going north-west, for example, I know whether to expect a west bound bus first or a north bound bus, or whether I should just start walking. The bus system in Phoenix isn't great. A lot of the time, you'll get there sooner if you just walk a few miles. A previous post talks more about this. Short version is, I have an SDL based app that has a scrollable map with an adjustable "current time", that shows where all the buses are supposed to be at that time. I scraped their website and did my own geocoding. Bus locations are interpolated between stops on the time table.

Having that for myself, the next step was sharing it, and that meant Web, or possibly, an iPhone app or the like.

Turns out that it was easy to retarget it to the web, just by replacing my SDL wrapper. Rather than using SDL, it uses GD. I had to rework the original and the other wrapper a bit but the program is basically agnostic about which it works under.

The window gets output to the browser as one big inline, base64 encoded image with the ismap attribute set. You may have forgotten about this attribute. When an image is inside an anchor (a) tag, ismap causes the x, y location of the click on the image to be added to the URL in the a href. Eg:







A click on that image might cause a hit to, for example, foo.cgi?10,20.

One of the handy things in the wrapper around SDL was a AWT 1.x-like click callback system. Any time a graphic gets blitted, it optionally includes a coderef to be called if the region it gets blitted to gets clicked. In the SDL version, mouse clicks were propogated to the correct callback. In the web version, these ismap clicks are. And of course, the thing was built on top of Continuity. At the end of the request loop, it does this:



my $get_string = $request->request->url->as_string;

if($get_string and $get_string =~ m/\?\d+,\d/) { $graphics->hit($get_string =~ m/\?(\d+),(\d+)/) or $draw_playfield->(); } else { $draw_playfield->(); }

my $png = encode_base64($app->png, '');

$request->print(qq{ }); $request->next;



That's inside of a while(1).

At first, I tried using the bmp dumping methods of SDL, but the images came up blank, and trying to call flip or anything like that made it coredump.

Actually, SDL has been a huge thorn in my side. I'm trying to think how I could finagle using GD as a graphics toolkit for an X window. Some X11::Protocol glue, maybe... or maybe I'll just pick Prima up again.

So, the thing is up at http://slowass.net:8445. Or at least it is sometimes.

It needs a few more things... some the geocoding is wrong, and I need to get another font going for display bus info when individual buses are clicked. It should default to the current time. Buses should indicate which way they're going, which means I need another graphic for them than little balls.

I also made a movie: slowass.net/user/scott/bus.mpg.

That was a bit ago, but I thought I'd finally write this up and share.

If there's interest, I might fix up my wrappers and release them as a pair of modules with the same API, one for web, one for desktop, but I'm still hung up on a few things, such as SDL refusing to render anti-aliased text because it wasn't built with SDL_mixer (wtf?) and taking all available CPU when the event loop is called (gah!). And there's the temptation that if I'm going to release a GUI toolkit, it should be a bit more interesting than just smearing text and images around a pane with callbacks for clicks. Right now, there's no provision at all for data entry fields. The good, nice way to do this would be to add a Web backend to Prima.

-scott


google map, Processing

slanning on 2009-03-12T10:27:53

I know you're doing your own thing, that's cool, but maybe it'd be simpler as a google map app? (If possible.) I guess the problem would be updating the data.

What you're doing reminded me incidentally of using Processing. It's possible to export as either a Java app or as an applet for a browser. (The main problems for me with Processing are: 1) it's Java-based, 2) the IDE seems buggy in Linux (at least I had problems sketches, as it would freeze the IDE).)

Re:google map, Processing

scrottie on 2009-03-16T03:59:25

Yeah, this should have been a Google Maps app. I looked at the API briefly but felt bogged down. Also, I don't have GPRS/EDGE any more, so I wanted something that worked off-line with the on-line version being an after thought. I have played with Processing a bit. Where I got stuck with it was CPU usage and the Flash-like fps thing, where it tries to draw so many frames per second regardless of whether anything has changed on the screen. It had some threads that were very CPU hungry that I really didn't know what were doing. I was trying to re-build the MUD GUI in that. I should have stuck to the raw Java.

But this is kind of an off-shoot of work, too. I'm trying to find and learn some Perl graphical toolkit that doesn't suck donkey dong. SDL is like a chose your own adventure where every pathway leads to coredump and I've wasted too much time navigating its various corridors already. There's Ogre, a wrapper around the open source ogre engine, and PDL::Graphics::X, which lets you use raw PDL arrays as graphic buffers. I need to refresh my memory, but slices in SDL should work fine as a blitter operation. I need to figure out if there's something that would do alpha masking and blending.

I have to admit that I've been pondering how to go about doing a Processing-like thing in Perl. There are quite a few things like Processing but they all seem to suffer from the wrong amounts of complexity in the wrong places, including too little complexity where there should be more. They kind of suffer from the MVC framework problem, where it's really easy to get something up, but really hard to finish it, until you've learned your way around it well.

Wow, I didn't think it was possible, but they made use.perl.org suck even more. I'm afraid this might be my last post here...

-scott