FlexTime – Still 1.0

August 19th, 2006

It’s been two days now since I released FlexTime 1.0, and lots of people have contacted me to share their ideas and impressions about the software. The great news is that nobody has contacted me to report a crash or other instability. The biggest fear when releasing software is that, in spite of extensive testing, some surprise bug is lurking. Fortunately I think most of the bugs were washed out in the beta cycles. People are reporting ideas to make it even better, not ideas to simply make it work. While there’s no great shame in a quick-turnaround to release a 1.0.1 version of a product, I admit to taking some pride in the fact that so far, this product lives up to the promises of “release quality software.”

It’s been exciting for me to watch as the world reacts. While many people are contacting me privately to share their thoughts, others are writing publicly on their blogs about their experience.

Luis de la Rosa of Happy Apps was an early adopter of FlexTime. He started using the application to help treat his repetitive strain injuries with a relatively primitive beta version a few months back. Now he’s written a blog entry describing the benefits of using FlexTime during his work day. His decision to use it for this purpose helped in guiding some of the core features such as the “show text” cues. Thanks, Luis!

Luis’s use of FlexTime as an RSI helper is just one of the many “surprising uses” that have come up over the months since I’ve shared FlexTime with the public. Now that I’ve released it to a wider audience, more ideas are rolling in. It’s a real treat to see what people come up with, and I often laugh out loud – not because the ideas are funny – but because they’re deliciously surprising.

I’m excited to share more examples in greater detail over the coming months. People are using FlexTime to “enhance” the activities that already fill their days, be it desk work, cooking, or music-making.

FlexTime 1.0

August 17th, 2006

I put FlexTime in the “cold-storage locker” one week ago yesterday and it’s been resting up for its official 1.0 debut.

FlexTime 1.0 is available starting today for $18.95. A free 30 day trial is available and automatically applies to the fully-featured download available here. If you decide to buy it, you may purchase from directly within the application, or online through the Red Sweater Store.

What is the cold-storage locker? It’s my off-the-cuff name for the process of leaving source code unmodified while continuing to test the product. Many smaller businesses fall into the trap of releasing software “hot off the presses,” which often means some bug was fixed mere hours before release, inadvertently introducing five undiagnosed problems for the public to uncover.

The cold-storage locker is a good idea, but this is the first time I’ve diligently employed it. In the past I’ve just succeeded (or to be honest, sometimes failed) on the basis of my relatively careful coding practices. But after hearing enthusiastic endorsements of the policy from friends at Bare Bones and Flying Meat, I’ve decided that I should also adopt this policy going forward. Not only does it give you time to think of the “oh crap” mistakes that you might have made, but it (ideally) gives you have a little pre-launch vacation time to relax and prepare for the (hopefully) large influx of new customers.

It feels good to have FlexTime 1.0 officially under the bridge, so I can get to work on updated versions of it, and some other products I have twinkling in my eyes.

Usable Keychain Scripting

August 11th, 2006

Anybody who’s tried to use Apple’s Keychain Scripting has probably learned that its performance and functionality are both fatally flawed.

The quintessential flaw in Keychain Scripting’s performance can be observed by simply asking it to find a key by some attribute test. If it works, then it will take a long, long time. All of its “whose clause” functionality is extremely slow, but this simple case forces it to go through each item in the keychain, failing to find a key:

tell application "Keychain Scripting"
	set myKey to first key of current keychain ¬
			whose name is "zzzzz"
end tell

Just how bad is it? I knew I had seen times of at least a minute, but I decided to test with Shark just to be sure. I let it rip and to my surprise AppleScript eventually gave up with a “event timed out” error. I stopped shark and observed that Keychain Scripting had used up 2.3 minutes of CPU time (!).

I was anxious to learn how bad it could get so I put a “with timeout of 200000 seconds” around the AppleScript block and ran it again. The pipes must have been warm this time, because Keychain Access came back in a “zippy” 1.3 minutes, finally having failed to locate the item as expected.

Obviously, Keychain Scripting is freaking useless.

I decided to take a stab at writing my own, because I’ve been waiting too long for this to get fixed and I just don’t have any faith left. I figured it was a good opportunity to learn about the Security Framework, with which I have had no prior experience. I used the Keychain Access dictionary as scaffolding for everything I needed to implement, and slowly filled in the gaps, testing each attribute and command before and after implementation, learning the API as I went along. I abided by my policy of ignoring performance considerations until I got something working. Before long, I had completed set of simple Cocoa wrappers around the Security framework, which simply map through to live-fetches of the data from the underlying database.

The results? The script that takes (at best) 1.3 minutes to run in Keychain Access takes 300ms in “Usable Keychain Scripting.” Holy cow manure! That’s a 260x performance improvement, and I haven’t optimized anything. This fruit is so low-hanging it’s practically buried.

OK, you might be thinking this is just an arbitrary example of a bad edge case. How does Keychain Scripting really perform? You know … when you’re looking for something that actually exists. Here’s another arbitrary example, this time collecting the keychain items that have my name in their name:

tell application "Keychain Scripting"
	set myKey to first key of current keychain ¬
			whose name contains "daniel"
end tell

This time it’s 360ms in my Usable version, and uh oh, bad example, simply doesn’t work in Keychain Scripting.

Keychain Scripting got an error: Can’t get key 1 of current keychain whose name contains “daniel”.

Unusable. The same experience applies to most other reasonable attempts to ask it for information.

Usable Keychain Scripting is at least 260x better than Keychain Scripting in the speed of critical lookups, but there are other improvements, too. I fixed up the dictionary to not suck as much, and my code goes directly to the most modern security API, while the Apple version still goes through an outdated “KC” API. Who knows, one of these days maybe I’ll even optimize it. NOTE: the terminology is slightly different from Apple’s Keychain Scripting, but I think my terminology is clearer.

So why would you even want to script Keychain? Well, for one thing if you script Keychain instead of hardcoding passwords in your scripts, things are a lot more secure. Also, there are certain keys for which I find myself constantly going into Keychain Access and looking up the values for. Either Safari forgets how to auto-enter it, or NetNewsWire loses its wits about something. For instance, every once in a while my Daring Fireball subscriber feeds lose knowledge of their password. With the scripting mechanism working as it should, I can keep a short script attached to NNW for refetching it:

tell application "Usable Keychain Scripting" to tell current keychain
	set myPass to password of first internet password ¬
		whose protocol is HTTP and name is ¬
		"daringfireball.net (<my email address>)"
end tell
set the clipboard to myPass

Now the password is in my clipboard and I just paste it into the field as NNW requests.

Note: I have a mechanism in place for setting values of keychain items, but I am wary of making it public yet because of the risk of data loss if I did something wrong. For now just enjoy the speedy access to your existing keychain data.

FlexTime Scripted Cues

August 6th, 2006

I’ve posted FlexTime 1.0b8, which contains a great number of minor fixes, as well as my first stab at built-in Help documentation. While you’re waiting for the excitement of WWDC to commence, why not spend a few minutes optimizing your favorite timed activities?

AppleScript got a great deal of enhancement on this round. I finally implemented a scripting interface for setting cue parameters, and fixed a few little bugs that were preventing FlexTime’s Sofa Control Plugin from working as well as it could.

A scripting feature I didn’t really go into detail about last time is an enhancement I’ve added to the “Run Script” functionality. If FlexTime finds an AppleScript handler called “HandleFlexTimeCue,” it will attempt to call it directly instead of running the script as a whole. This mechanism gives your scripted cues access to information about the activity and routine they are being asked to cue on behalf of. For instance, a simple scripted cue that displays the name of the activity and routine document might look like this:


-- If somebody runs us directly, set them straight
display dialog "This is a FlexTime cue script! " & ¬
	"Don't run me like that!"

on HandleFlexTimeCue(myDocument, myRoutine)
	
	-- Just beep for fun
	beep
	
	-- And ask FlexTime to show a message 
	set routineName to name of myDocument
	set activityName to name of myRoutine
	set myText to "Time to do " & activityName & ¬
		" for " & routineName
	tell application "FlexTime"
		display message myText ¬
			at screen position bottom left ¬
			dismissing after delay 5
	end tell
	
end HandleFlexTimeCue

This script also demonstrates how you might use a “Run Script” cue handler to overcome some of the shortcomings in FlexTime’s built-in cues. For instance, the text message displayed by the above script is configured to automatically dismiss after 5 seconds, and is positioned at the lower-left hand of the screen.

As FlexTime evolves the UI will get more powerful, but it will probably always lag somewhat behind the power exposed by the scripted interface. The Run Script cue is a good option for FlexTime routines that need to push the envelope of possible actions.

Oh, and one more not-so-obvious feature of the “Run Script” cue is that it will launch/run/open practically anything you can think of. It’s using the same mechanism as FastScripts, which is very liberal in its willingness to call something a “script.” It will run shell scripts, launch/activate applications, run Automator workflows – you can even ask it to open a document file for you.

Stay tuned for more on FlexTime’s secret powers :)