Watershed du jour – 3D coming of age

While software and hardware have made great strides, some things still remain in the realm of specialized software. One way to look at this is, what can you still not do on the web? I can think of a few things: 3D, sound synthesis, video editing. I have hopes for all of these, but 3D in particular looks to be on the edge of a real breakthrough, and not necessarily from where I expected it.

For years I have been tracking X3D, the XML-based 3D specification that is the successor to VRML. I’ve been watching and working with the open-source FreeWRL tool, and it has been making good progress. However, the Age of Plugins appears to be on the decline. If it isn’t built-in to the browser (or ubiquitous, like Flash, and I have doubts about the long-term viability of Flash), there is little chance of getting viewers to install a plugin for your media format. That’s why I’m excited to see that Firefox is experimenting with a 3D context for the <canvas/> element, which will base its API on OpenGL ES, and significantly will support import of Collada models (presumably Collada Digital Asset Exchange, or .dae files).

But Firefox alone does not make a viable ecosystem. The other things I have come across recently that have convinced me that Collada models are going to springboard 3D into the hands of ordinary users are that Spore patch 5 (available now for PC, coming soon for Mac) supports exporting creatures (with textures and ready for animation) in Collada format, so you can work with them in the 3D tool of your choice, and that the next major release of Mac OS X, Snow Leopard, will support Collada as a built-in file type (scroll down to “Digital Asset Exchange support”). Collada has kept pretty quiet, at least in my world, but the support for it is pretty widespread, including open-source tools such as Blender and OGRE, plus all the usual suspects such as Maya and 3dsMax. Sadly, my editor of choice, Cheetah3D does not yet support it, but I understand they’re working on it.

I, for one, welcome our new 3D asset exchange overlords. Along with improved user creation tools like Spore, SecondLife, and SketchUp, 3D is almost ready for prime time.

Tab Dumping with AppleScript and back to Python

Rock

Goal: Iterate through all my (OS X Safari) browser windows and make a list of titles and urls which is then placed in the clipboard ready to be pasted into an email or blog post.

This is an update to Tab Dumping in Safari. That still works well as the basis for extending any Cocoa-based application at runtime, but it relies on SIMBL, which while it is a great bit of code, essentially is abusing the InputManager interface. Some developers and users shun such hacks, and at least one Apple application checks for them at startup and warns you from using them.

I have been running the WebKit nightlies, which are like Safari, but with newer code and features (most importantly to me right now, a Firebug-like developer toolkit). WebKit warns at startup that if you’re running extensions (such as SIMBL plugins) it may make the application less stable. I was running both Saft and my own tab dumping plugin, and WebKit was crashing a lot. So I removed those and the crashes went away. I miss a handful of the Saft extensions (but not having to update it for every Safari point release), and I found I really miss my little tab-dumping tool.

I toyed with the idea of rewriting it as a service, which would then be available from the services menu, but couldn’t figure out how to access the application’s windows and tabs from the service. So I tried looking at Safari’s scriptable dictionary, using the AppleScript Script Editor. Long ago, John Gruber had written about the frustration with Safari’s tabs not being scriptable, but a glance at the scripting dictionary showed me this was no longer the case (and probably hasn’t been for years, I haven’t kept track).

I am a complete n00b at AppleScript. I find the attempt at English-like syntax just confuses (and irritates) me no end. But what I wanted looked achievable with it, so I armed myself with some examples from Google searches, and Apple’s intro pages and managed to get what I wanted working. It may not be the best possible solution (in fact I suspect the string concatenation may be one of the most pessimal methods), but it Works For Me™.

In Script Editor, paste in the following:

set url_list to ""
-- change WebKit to Safari if you are not running nightlies
tell application "WebKit"
  set window_list to windows
  repeat with w in window_list
    try
      set tab_list to tabs of w
      repeat with t in tab_list
        set url_list to url_list & name of t & "\n"
        set url_list to url_list & URL of t & "\n\n"
      end repeat
    on error
      -- not all windows have tabs
    end try
  end repeat
  set the clipboard to url_list
end tell

I had to use AppleScript Utility to add the script menu to my menu bar. From there it was easy to create script folders that are specific to both WebKit and Safari and save a copy of the script (with the appropriate substitution, see comment in script) into each folder. Now I can copy the title and URL of all my open tabs onto the clipboard easily again, without any InputManager hacks.

I had some recollection that is a way to do this from Python, so I looked and found Appscript. I was able to install this with a simple easy_install appscript and quickly ported most of the applescript to Python. The only stumbling block was that I couldn’t find a way to access the clipboard with appscript, and I didn’t want to have to pull in the PyObjC framework just to write to the clipboard. So I used subprocess to call the command-line pbcopy utility.

#!/usr/local/bin/python
from appscript import app
import subprocess
tab_summaries = []
for window in app('WebKit').windows.get():
    try:
        for tab in window.tabs.get():
            name = tab.name.get().encode('utf-8')
            url = tab.URL.get().encode('utf-8')
            tab_summaries.append('%s\n%s' % (name, url))
    except:
        # not all windows have tabs
        pass
clipboard = subprocess.Popen('pbcopy', stdin=subprocess.PIPE)
clipboard.stdin.write('\n\n'.join(tab_summaries))

The remaining hurdle was simply to put the Python script I’d written into the same Scripting folder as my AppleScript version. For me this was ~/Library/Scripts/Applications/WebKit/. When run from the scripts folder, your usual environment is not inherited, so the #! line must point to the version of Python you are using (and which has Appscript installed). You should also make the script executable. Adding .py or any other extension is not necessary.

Overall, while I found AppleScript to be very powerful, and not quite as painful as I remembered, I found the Python version (warts and all) to be easier to work with. Combined with the fact that the script folder will run non-Applescript scripts, this opens up new worlds for me. I have hesitated in the past to write a lot of SIMBL-based plugins, tempting though it may be, because they are hacks, and they run in every Cocoa-based application. But adding application-specific (or universal) scripts, in Python, is pure, unadulterated goodness.

in earth dreams

This is a collaboration that Daniela and I did together. Her words and voice, my scripting and adding some titles. The words to the poem can be found on her site here (or actually, on any page of her site since it is currently in her sidebar). The animation itself was done in NodeBox (so this example is Mac-only, but it could probably be adapted easily to Processing.

from math import radians, sin, cos
from random import seed

POEM = '''
in earth dreams
her limbs 		are all sky
her body		inhabited
by wild birds		and busy
mammals
an endangered 		species
she lost		 her head
where reason 		gives
the impression 		everything is
clear
she motions 	to dance
a rhythm			spins
and turns		attracted
to light
if she had eyes 		I would see
the stars		she holds
dear
then 		there are 		all
the words		she escapes
slips past 		their curved
seashell ears	as they listen
to capture 		her
on the page		 my words
are already	changing her
while she weaves 	gossamer
and soft moss		to hang
in autumn 	woods
'''.split()

size(320,240)
speed(30)

class Vector(object):

    def __init__(self, idx):
        self._starting_angle = self.angle = radians(random(360))
        self.rate = random(0.5,2.5)
        self.distance = sin(radians(idx * 2) + 180) * 100
        self.x = 0
        self.y = 0

    def step(self):
       self.angle = self._starting_angle + FRAME * radians(self.rate)
       self.x = cos(self.angle) * self.distance
       self.y = sin(self.angle) * self.distance
       return self.rate, self.x, self.y

class Word(object):

    index = []

    def __init__(self, idx, word):
		self.red = random()
		self.green  = random(0.4, 0.75)
		self.blue = 0.4
		self.vector = Vector(idx)
		self.word = word
		self.size = 10 + 2 * len(word)
		self.duration = 3 * (len(word) + 2)
		Word.index += [idx] * self.duration

    def step(self, alpha=1.0):
		fill(self.red, self.green, self.blue, alpha)
		rate, x, y = self.vector.step()
		push()
		rotate(rate * FRAME)
		font('Georgia', self.size)
		text(self.word, x, y)
		pop()

def setup():
    global words
    seed(0)
    words = [Word(idx, word) for idx,word in enumerate(POEM)]

def draw():
    translate(WIDTH/2 -50,HEIGHT/2)
    background(1.0, 0.97, 0.86)
    # Add one word at a time, then show all words for 100 frames more
    if FRAME < len(Word.index):
        last = Word.index[FRAME]
        for word in words[:last]:
            word.step()
    # Now fade out and have blank screen for titles
    elif FRAME < len(Word.index) + 100:
        alpha = 1.0 - 0.01 * (FRAME - len(Word.index))
        for word in words:
            word.step(alpha)

I used iMovie '08 to mix the voice and animation and to add the titles. I wasn't very happy with the changes to iMovie, I found the earlier versions were much more flexible and easy to use. On the other hand, I tried Norrkross Movie, that I actually had to buy, and was unable to do it at all. Next time I will just add the titles in NodeBox and only use iMovie to add the soundtrack.

My Python script could probably be cleaned up too. This was what I had after many iterations and experiments to get the timing, color, and rotation where we were both happy with it.

This was my first time uploading to YouTube and the resulting movie is very jumpy, in the original movie I uploaded was not. If anyone has suggestions how to avoid that (whether pre-processing or a better movie hosting service), please let me know in the comments. Overall I was happy with how it turned out and I'm looking forward to our next collaboration.

The Apple Tablet

So last year I got tired of waiting for Apple to come out with a tablet computer (which Jobs will never purposely do, even though Ink Services are built right into OS X). I also got sentimental for the Newton that I outlined my thesis on, lo these many years ago. My sentimental reflections were enhanced by this article by Phillip Torrone on building a sub-$100 laptop out of an old eMate from eBay. I had never used eBay, so as an experiment (one of two: I also picked up a copy of the long out of print Avalon Hill board game Dune) I found myself a Newton MessagePad 110. Which, by and large, does nothing.It boots OK, but I’m reluctant to use it for anything besides a conversation piece unless I can get my data back off of it (and it would be nice to load new apps on it as well). Since none of my Macs have AppleTalk serial ports, I’m not sure how to get the Newton talking to them. I’ve checked the Newton sites, but what instructions there are appear to be dated and complex (perhaps it just is complex, I’m not ruling that out). So, LazyWeb, I invoke thee! What is the best way to get an OS X box talking with a Newton?My email is below. I’ll quote from (and credit) responses unless requested not to. Any help in reifying my nostalgia is appreciated.

Mac OS X Software Favorites Part One: Basics

Yesterday was my last day at my job for the past five years, and with it I left my Macbook Pro (it was a nice tool, but they own it). Coincidentally, I’m now setting up my new Macbook. Since I know several other people who are setting up new Macs, I thought I’d give my thoughts on some of the best software available. Since that’s a big topic, I’m going to break it up into several posts, starting with the basics: Application Launcher, Text Editor, Web Browser, Newsreader

Macbook vs. Macbook Pro

Before diving into the software, just a note on the hardware. I’m going with a black Macbook for several reasons. First, it looks really cool, and I can’t deny that appeals to me. Second, it is somewhat smaller and lighter than the smallest Macbook Pros, and since I carry my laptop to and from work every day by foot or bicycle, that matters (I’m getting two power bricks so I can leave one in each location to save even more weight). Third, the wifi reception is much better. Encasing an antenna in plastic appears to work better than encasing it in aluminum, go figure. Macbook Pros are more powerful, but only a bit, and mainly for heavy-duty 3D, which isn’t really my thing. We’ll see how much this matters in practice. White vs. Black Macbook: the white ones are rumored to stain really easily, plus did I mention that the black ones look really freaking cool? The Macbook is cheaper than the Macbook Pro, but that’s not a big factor in why I’m choosing it (since once again, work will own it, just a different work–more on that later). The Macbook also gets better battery life, is slightly less crotch-scaldingly hot, and so far I’m liking the keyboard a lot.

Application Launcher: Quicksilver

I used to use TigerLaunch (free, open source), and still do on other Macs in the family, but once you’ve tried Quicksilver (free, beta) there’s no going back. I’m still working on becoming a Quicksilver power user, but just the app-launching and file-searching facility is worth using this tool for. TigerLaunch is great for its simplicity, and Quicksilver is great for making you wonder how you ever got along without it. I’ve heard wonderful things about PathFinder ($34.95USD) and keep meaning to try it, but haven’t gotten to it yet. First I need to learn how to write Quicksilver plugins in Python…

Editor: TextMate

I used to use Pico on Unix and BBEdit Lite on Mac OS 7, back in the day. I couldn’t stand either vi or emacs. I wanted a T-shirt that read, “I’d rather die than use vi.” Then I worked at a company where the only editor you could count on being installed was vi and I began to get its keystrokes etched into the memory of my fingers. I’m not even that good at it, but sometimes vi can be so damn fast. Of course, I don’t use classic vi, but a nice modern Vim (free, open source). I’ve tried to switch back to Mac editors a few times: TextWrangler (free, the OS X incarnation of BBEdit Lite), SubEthaEdit ($35USD, great for collaborative editing), Smultron (free, open source). These are all great editors, but each one lacked something that kept me from switching over completely. I had been hearing about TextMate (€39EUR) for some time, but had trouble getting excited over a commercial editor when there were so many free ones to choose from. I finally gave it a serious try and I’m hooked. It still isn’t as easy to search as vi is, but the way it can be expanded on with plugins and the general fit and feel are great.

Browser: Safari + Saft

Safari is shaping up to be a great browser, fast and powerful. There are a few details that are missing, but nearly all of them are satisfied with the Saft ($12USD) extension, which provides great ad filtering, improves the way windows and tabs are handled, and gives shortcuts for accessing search sites from the address bar, among many other features. Safari itself takes two kinds of plugins, Netscape-style plugins and WebKit plugins. Unfortunately, these are only triggered when their target mime types are loaded, so they can’t readily be used to extend the way the application itself works. So all of the Safari extensions that I’m aware of are implemented as InputManagers (see my post on TabDump for more on InputManagers). My TabDump extension is the other extension that I find indispensable, which is why I wrote it, but more important than TabDump itself is the example it gives for writing your own extensions to Safari or any other (Cocoa) application. That’s what I love about OS X, you can get into it and take control of your own machine, make it your own. You can do that with Linux, of course, but the high-level of Cocoa applications make a huge difference. Back to browsers, I also recommend the Flip4Mac plugin, to allow your browser to play Windows Media files directly. Finally, I also keep Firefox (free, open-source) around for its advanced features. It’s not my main browser, but it has features that show where the browser (and all applications) will be going in the future. I may have to do a separate post just about the cool features coming in Firefox 2 (currently in beta) and Firefox 3. Other good browsers to keep around for testing are Camino (the Firefox engine with a Cocoa UI) and Opera (free). For more Safari plugins and extensions than you could ever use, check the listings at Pimp My Safari.

Newsreader: NetNewsWire

I realize that Safari now supports RSS feeds in some fashion, but it really isn’t a newsreader. I’m not crazy about trying to put every possible application into the browser. If you have to work betwwen Windows, OS X, and Linux, or some combination thereof, then things like GMail and Bloglines can be a godsend, otherwise you’re probably better off with a dedicated desktop app. NetNewsWire ($29.95USD) is a desktop app that is so good, it was the most popular newsreader (by far) for a long time, even though it only ran on OS X. Since being acquired by NewsGator, it’s still as good, but now synchronizes your feeds with the NewsGator site, so you get the best of both worlds: a top-notch desktop app, and a webapp that stays sychronized with it. I have a feeling that in the near future, nearly all applications will work this way. And if you can’t afford the price, they still offer NetNewsWire Lite for free (and I happily used it for a couple of years before upgrading).

Mail: Mail.app

Apple gives you a decent email program with OS X, nothing too fancy. It keeps getting better (mostly) with each new release. There has been some complaints about Mail.app in OS 10.4 changing to a proprietary format (which they did in order to integrate with Spotlight) and I’ll have more to say about that in a future post. I have tried using Gmail (when I was mostly using Windows at work) and Thunderbird (free, open-source), and coming back to Mail.app is like a breath of fresh air. For nearly everything I do, Mail.app is better. It’s far from perfect, and sites like HawkWings specialize in plugins and extensions for Mail.app, but it sure works for me. I do wonder why email programs are still so hard to get right. Since email is basically the oldest use of the internet (and networks generally), and the original “killer app,” if we don’t know how to do email yet, what hope do we have for anything that’s actually complicated? Of course, perhaps because they have been around for so long, choice of email programs tends to be very personal, so all I can say is, Mail.app works for me. I also recommend the AttachmentScannerPlugin by James Eagan, who also provides a tutorial on writing plugins for Mail.app which is generally applicable to extending Cocoa programs and using their undocumented private APIs. Also, he uses Python and PyObjC to write the plugin, which makes me happy.

Regular reader(s) were probably wondering how I was going to get that plug for Python and PyObjC in there, eh?

« Previous entries Next Page » Next Page »

google

google

asus