David Sinclair's blog

Simon tip: notify via email

I recently received a question from a potential customer, asking whether Simon has the ability to send a notification via email.

Although I do mention it in a number of places, this wasn't an unreasonable question, particularly if you just download Simon and start playing with it, as no email options appear in the list of available notifiers in the Edit Test window by default.

Why is this? Because unlike the Speech and Sound notifier plug-ins, the Email one requires some configuration before it can be used, so it can't be offered by default.

The way notifiers work is (I hope) pretty intuitive, but a little indirect. Simon provides a number of notifier plug-ins that do the work of notifications, and you configure notifiers to use those plug-ins, then choose notifiers for each test.

These levels of abstraction allow easy re-use of notifiers: a single plug-in can be used by multiple notifiers, and a single notifier can be used by multiple tests, without having to set up the same things over and over again.

For example, you can add an email notifier to yourself for some failures, another email notifier to your clients for other failures, another one for recoveries, and so on, and use whichever ones of those are desired in tens or hundreds of tests, as required, as simply as choosing them from a pop-up menu.

Test Notifiers

So, as I said, there is no email notifier set up by default, since it needs configuration, but you can easily add one. If you're editing a test and realize that you want to receive an email or SMS when this test changes, fails, and/or recovers, you can click the New Notifier... button in the Notifiers section of the Edit Test window, which will open the New Notifier window. You can then choose E-mail from the Notifier Kind pop-up menu, and the controls below will change to those for the email plug-in:

Email Notifier plug-in

You can then configure the email, and save the notifier, which will be available for that test and any others you want to use it in. Easy!

Simon 2.3.1 released

Simon version 2.3.1 is now available. This release is a bug-fix version, with just a few changes:

  • Rewrote the Port service plug-in to use a helper app to do the work, to avoid instability caused by multithreading and resource usage issues.
  • Added support for the Preview function for the Port service plug-in. It displays the session script at the top, and the actual transcript of the check at the bottom.
  • Changed editor windows to not reuse the window instances, to avoid issues with windows appears incorrectly in some circumstances.
  • Added German localization, thanks to Manfred Brandstater.
  • Updated French localization, thanks as always to Philippe Bonnaure.

I'd like to give special thanks to Manfred for his hard work in getting the German localization done, and also to the couple of German Simon customers who provided feedback on pre-release builds. If you have any feedback on the localization (issues, suggestions for improvements, compliments for Manfred, general comments), please let me know.

Also of note in this version is the rewrite of the Port service plug-in. I've had several reports of crashes and other issues with SImon, which on investigation all traced back to the Port services. There was definitely something NQR there. It's a complex plug-in, though not the most complex. I've tried patching it a couple of times in the past, without complete success, so the time had come to refactor it more significantly. I moved the checking work out into a separate helper app (aka an "agent"). The plug-in launches the background-only helper when starting the check, which does the work, then quits itself when done. This allows avoiding multithreading, which I believe was a factor in the problems, along with some other optimizations that will make it more reliable. And worst case, if it does crash, it won't take out Simon in the process. The crashes do seem to be a thing of the past, though, which is great. Thanks also to the customers who tested pre-release builds with this change.

Another benefit of this refactoring is that it has allowed adding Preview functionality. The Port plug-in did allow previewing in an older version, but I had to disable it when I changed the way the plug-ins worked (from keeping an instance around for the life of the app, to using a separate one for each check). But now I've re-enabled this functionality, and improved it. The Preview window for Port-based services now displays the session script at the top of the window, and the resulting transcript of the check at the bottom (much like for Scripts). This is very handy for ensuring that the test is doing the right thing, or seeing more detail about why it is failing - e.g. whether the session script is incorrect, or the server is misbehaving.

Download Simon now!

Be your own customer

A comment by Chris Smolinski of Black Cat Systems on the Mac Small/Software Business mailing list (there doesn't seem to be any consensus if it's "Small" or "Software") inspired me to share my views on this: "Be your own customer."

This was in response to a question on how to get good ideas for software, with the popular opinion being that scratching your own itch can lead to great product opportunities. Find something that irritates you about existing products, or something you want to do that isn't covered by an app already, and create a solution.

I can vouch for this approach. Although my products started out in various ways, most of them started because there weren't any satisfactory solutions at the time. For example, Simon began as a way for me to watch for website updates, and became more sophisticated as it became popular. There weren't any easy-to-use Mac products for site monitoring at the time - and the ones that did exist don't anymore. Similarly, I created Time Out to improve my health, since I can suffer from eyestrain when staring at a computer for hours on end. BlogAssist was written specifically for my wife, who was really into LiveJournal blogging at the time... but I find I use it a lot, too. All of the products have grown and evolved over the years based on customer feedback, but also my own ideas, since I use them myself on a daily basis (e.g. I used BlogAssist's Services window four times to create the links in this post).

When you are your own customer, or "eat your own dog food", to use that colorful and somewhat unpleasant phrase, you notice little irritations in your initial implementation, and can do something about it. Chances are, your paying and potential customers are also noticing such issues. They can can also be a great source of ideas for better ways to do things that you may not have thought of, perhaps because you're so used to a certain way of doing things.

So if you're a developer looking for the next big hit, or just something to get you started, look inside yourself for your inspiration. Sure, an idea has to have some market appeal to be a success, but even seemingly niche products can be successful if you do a good job. Put your heart into it, and people will respect that. Keep working on it, and using it yourself, and word will spread.

Pan-Mass Challenge update

Two of the eBay auctions for Seth Dillingham's Pan-Mass Challenge fundraising have concluded, with fairly healthy final prices - still major discounts on the retail values, too.

A Household license for Dejal Caboodle is also available as part of the latest auction, a "kitchen sink" of 37 great utilities. Check it out!

Software bundle to support cancer research

Seth Dillingham has put in a lot of work collecting Mac apps to bundle together, and they're now available. Unlike typical software bundles, where hundreds of people might get a collection of apps at a discount, this one is a bit different: the bundles are being auctioned on eBay, and distributed (fully licensed) on CDs.

His bundles are fundraising for the Pan-Mass Challenge, which supports cancer research and treatment. A very worthy cause.

I am happy to participate in this effort. A Standard license for Dejal Simon is available in what he describes as the ultimate bundle for creative types, and a Household license for Dejal Caboodle is included in his bundle of games and useful utilities. Each of the bundles include lots of great apps, and in support of an excellent cause. Check out the auctions quickly; they end in a couple of days time.

More recent documents, please

When I moved to a new computer not long ago, I did it the hard way: rather than using the handy Migration Assistant, I copied over my files manually. I did that not to cause myself undue pain and suffering (though there certainly was some of that), but to help clean out several years worth of detritus that had accumulated in my preferences folder and elsewhere.

A result of that, though, was that I needed to reset all of my preferences. For the most complex ones I just copied the pref files over, but others I reset manually, again to clear out old prefs lingering in the files. That was fine, not too difficult.

One of the many preferences I reset was a tip I read on the Mac OS X Hints site. It controls the number of recent documents listed in the Open Recent sub-menu in many applications. I like this feature in document-based apps that use it, but I like to have more than the default 10 documents listed. I prefer 30, which fits on my screen nicely.

So, I fired up my trusty Terminal and entered:

defaults write NSGlobalDomain NSRecentDocumentsLimit 30

And that was that! This command changes the default number of recent documents for all applications to 30 - you can change the number to whatever you prefer. It will take effect when apps are next launched.

I hope this is helpful for others, too.

Tweet tweet tweet

You may have heard of this little thing called Twitter on the intertubes. It's a site where people can post short (140 characters or less) updates on what they're doing, which can be viewed on the web, cellphones, etc. People can "follow" others they're interested in, and others can follow what you're up to. You know, one of those social networking thingies.

I've resisted the siren song of Twitter for quite a while, since I've been somewhat dubious about the value of such short updates, but it does seem quite popular, so I've finally given in. I've enjoyed reading about events in the lives of other Mac developers and Mac bloggers, and it's been useful to get a feel for the C4[1] conference last weekend, which I wasn't able to attend, unfortunately.

You can now see what I'm up to via my Twitter page. We'll see how it goes.

I'm sick of users

There have been a few interesting posts in the blogosphere discussing the word "users", notably one by Josh Bernoff. He argues against using this word, suggesting that the word "users" should be replaced with "customers", "owners", "members", etc:

Users put up with computers. People just do stuff.

I completely agree. I have long disliked the word "users", and try to avoid it. I don't think of the people using my software as "users", but rather as "customers". I write software designed to solve problems, help people achieve tasks, maintain health, monitor sites, and more. They are written by people, for people, for real-world situations.

As I say in my About page, my customers are my friends. I really believe that; it's not just a catchy phrase, but a basic philosophy. When someone writes to me with a question, a problem, or a suggestion, I read it and reply personally, trying to put myself in their shoes and figure out how best to help them. I want them to be happy, not as a user of a product, but as a customer of my company, an existing or potential friend of myself. But my thoughts on customer service is a subject for a future blog post.

Unfortunately, a long history in the computer industry inflicts itself on me when I'm not looking, so the Dejal site does use the word "user" in a few places. For example, I have "User Guides" for my software, and I may use the term in other places. I'm not sure what would be a better term for that, though... "Customer Guide" doesn't sound right. Maybe I should just call it "Simon Guide", "Time Out Guide", etc?

So developers, please consider what words best describe your relationship with your customers. Are they anonymous automatons struggling to use your software, or are they genuine people who find your products useful to help them in their daily activities?

Future and current customers: please remember that I'm a person too, not an faceless corporate entity. I invite you to tell me what you like and dislike about my work, how I can change things to help you better, or simply what you do with my products. I care, I really do! Let's be friends!

Commenting now requires login

I've resisted this move as long as possible, but commenting on Dejal blog entries, forums, etc now requires logging in. I tried using a captcha, and back-end spam detection software, and an approval queue, but while each of those helped keep the spam off the site, I've still had to wade through hundreds of spam comments.

I've noticed that most people seem happy to create an account on the site anyway, so this step shouldn't affect too many people. Creating an account is free and easy, and allows much easier access for subsequent comments, allows posting new forum topics, and allows tracking posts so you're notified when there's a reply, if you so desire.

If you don't want to create an account, you can always contact me privately instead.

Time Out 1.5.1 released

Time Out version 1.5.1 is now available. This is a quick bug-fix release with just two changes:

  • Fixed a bug that caused the Pause Breaks and Reset Breaks commands to remain disabled.
  • Changed the Begin Micro Break command to work if you postponed a Normal break and the Normal break is due very soon; the overlap avoidance feature is inappropriate for manually started breaks.

It's only been a week since the 1.5 release, which I'd normally consider too soon for another release, but these issues seemed important enough to justify it. Not having the Pause and Reset commands available is a major inconvenience for some people, so I wanted to get a fix out quickly for them. If you don't care about these changes, you can skip this update if you wish - but certainly no harm in updating anyway.

Prompt PayPal payment processing, part 3

Here's the remainder of the PHP code for the recent automation of my PayPal-based store, using PayPal's Instant Payment Notification (IPN) service. See part 1 for the introduction and part 2 for the start of the code.

So now we've got a valid transaction, so can begin to process it. As I previously said, I use a shopping cart, so I need to loop over the cart contents. I call the getPayPalShoppingCartValue() function (provided in part 2) to get values specific to a product; shared values can be copied easily. This should all work without a shopping cart, too. I save the values into a $license associative array, which is equivalent to a Cocoa NSDictionary.

    $count = $transaction['num_cart_items'];
   
    if ($count < 1)
        $count = 1;
   
    // Process each shopping cart item as a separate license:
    for ($index = 0; $index < $count; $index++)
    {
        // Construct the license:
        $license = array();
       
        $license['Parser'] = 'PayPal';
        $license['Parameters'] = $transaction;
        $license['Name'] = $transaction['first_name'] . " " . $transaction['last_name'];
        $license['Email'] = $transaction['payer_email'];
        $license['Postal'] = $transaction['address_street'] . ", " . $transaction['address_city'] . ", ";
        $license['Postal'] .= $transaction['address_state'] . " " . $transaction['address_zip'] . ", " . $transaction['address_country'];
        $license['PaymentAmount'] = getPayPalShoppingCartValue($transaction, 'mc_gross', $index);
        $license['TotalAmount'] = $transaction['mc_gross'];
        $license['Quantity'] = getPayPalShoppingCartValue($transaction, 'quantity', $index);
        $license['ProcessorNote'] = $transaction['payment_date'];
        $license['ProcessorTransID'] = $transaction['txn_id'];
        $license['ProcessorName'] = 'PayPal';
        $license['PaymentMethod'] = 'PayPal';
       
        $ref = getPayPalShoppingCartValue($transaction, 'option_selection1', $index);
       
        if (!$ref)
            $ref = 'paypal';
       
        $license['Referrer'] = $ref;
        $license['Special'] = getPayPalShoppingCartValue($transaction, 'option_selection2', $index);
       
        if ($testMode)
            $license['Test'] = 1;
       
        $license['ServerReferrer'] = $_SERVER['HTTP_REFERER'];
        $license['ServerIP'] = $_SERVER['REMOTE_ADDR'];
        $license['ServerAgent'] = $_SERVER['HTTP_USER_AGENT'];
       
        $itemName = getPayPalShoppingCartValue($transaction, 'item_name', $index);
        $isDonation = strcontains($itemName, 'Donation', true);
       
        setLicenseProduct($license, $itemName);

The setLicenseProduct() function simply maps the shopping cart's item name to my own product identifier.

Time to actually add the license. This is done with another function to be left as an exercise for the reader, addLicense(). It takes the $license array we just constructed, adds it to the license database, and returns (by reference) any error. If the sale was a donation for a freeware product or a pending sale, though, the add is bypassed, since a donation doesn't need a license, and a pending sale (if it reaches here) shouldn't be issued one.

We then construct an email to the customer, with different wording for freeware, pending, or normal sales. I'm omitting most of that, since it's specific to your situation:

        // Add the license, unless it's a donation or pending:
        if ($isDonation || $isPending || addLicense($license, $error))
        {
            $productName = $license['ProductName'];
            $version = $license['Version'];
            $name = $license['Name'];
            $email = $license['Email'];
           
            // Donations and pending transactions will use the item name for the product name,
            // as the latter is set in updateLicense(), which isn't called for them:
            if (!$productName)
                $productName = $itemName;
           
            if ($isDonation)
                $body = "Greetings.  Thank you for the $productName!  I appreciate it.\n\n\n";
            else if ($isPending)
            {
                $body = "Greetings.  Thank you for purchasing a $productName.\n\n\n";
                $body .= "Your PayPal transaction is still pending, so you will receive your license when the payment is complete.\n\n\n";
            }
            else
            {
                $body = "Greetings.  Thank you for purchasing $productName.\n\n\n";
                $body .= "Licensed Name: $name\n";
                $body .= "Licensed Email: $email\n";
                $body .= "License Kind: " . $license['KindName'] . "\n";
                $body .= "$productName $version Serial Number: " . $license['Serial'] . "\n\n\n";
                // Instructions on adding the license omitted...
            }
           
            // Info on forums, FAQ, email contacts, etc omitted...
           
            $headers = "From: MyCompany <sales@mycompany.com>\r\n";
            $headers .= "Bcc: MyCompany <sales@mycompany.com>\r\n";
            $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
           
            if ($isDonation)
                $subject = $productName;
            else if ($isPending)
                $subject = "$productName purchase";
            else
                $subject = "$productName license";
           
            mail("$name <$email>", $subject, $body, $headers);
        }
        else if ($error)
            exitWithError('PayPal', $error, $license);
    }
   
    header("Content-Type: text/text");
    echo("Transaction completed.");
}

And we're done! I hope this is helpful. This all seems to work fine for me, but if you spot any bugs or have any suggestions for improvements, please let me know. If you have any questions, I'd be happy to elaborate more. I'd be keen to hear from people who use this code, too.

Prompt PayPal payment processing, part 2

As discussed in part 1, I recently automated my PayPal-based store, using PayPal's Instant Payment Notification (IPN) service.

For those interested in the technical details, perhaps implementing this for your own store, here's my code. This is written in PHP, but other languages can be used too.

Firstly, a couple of utility functions. For getPayPalShoppingCartValue(), given the PayPal transaction data, a key, and the (zero-based) index, this returns the corresponding value. Tries the key with the index appended, with an underscore and the index appended, or by itself; the documentation is somewhat inconsistent on how it is applied, though I think an underscore is usually used. All this code should still work fine if you aren't using the shopping cart, too.

function getPayPalShoppingCartValue(&$transaction, $key, $index = 0)
{
    $value = $transaction[$key . ($index + 1)];
   
    if (!$value)
        $value = $transaction[$key . '_' . ($index + 1)];
   
    if (!$value)
        $value = $transaction[$key];
   
    return $value;
}

Next, the exitWithError() function emails me the details of an error, for diagnostic purposes, then exits the script. You can optionally pass an array and it will be included in the email. It also outputs the error (normally wouldn't be seen). It calls another existing function of mine (not provided here) that returns the array as an ASCII property list; there are other ways to output it too. Of course, you should replace the mycompany.com email addresses with your own.

function exitWithError($parser, $error = '', $array = null)
{
    $body = "An error occurred with the $parser parser:\n\n$error\n\n";
   
    if ($array)
        $body .= arrayToASCIIPropertyList($array);
   
    $headers = "From: MyCompany <info@mycompany.com>\r\n";
    $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
   
    mail("info@mycompany.com", "Store error: $error", $body, $headers);
   
    header("Content-Type: text/text");
    echo("$parser error: $error");
   
    exit();
}

On to the main code. I actually have this in a function in my code, as it is just one processor function among others, but if you only have one, it can be at the top level of the script.

function handlePayPal()
{
    // Copy to a local variable for convenience, and since the post back to PayPal might wipe it:
    $transaction = $_POST;
   
    // Test mode is activated by passing test=1 to my PayPal Store.  It then uses PayPal's sandbox site instead:
    $testMode = $transaction['test_ipn'] == 1;
   
    if ($testMode)
    {
        mail("MyCompany <sales@mycompany.com>", "PayPal IPN starting", arrayToASCIIPropertyList($transaction), "From: MyCompany <sales@mycompany.com>\r\n");
       
        $paypalDomain = 'www.sandbox.paypal.com';
        $receiverEmail = 'paypal_sandbox_biz@mycompany.com';
    }
    else
    {
        $paypalDomain = 'www.paypal.com';
        $receiverEmail = 'paypal@mycompany.com';
    }

The above sets up things based on whether the purchase was via the PayPal sandbox or your live store. The sandbox is a great way to create fake customer and seller accounts for testing without spending real money. You can initiate this test mode by changing the action on your form from <https://www.paypal.com/cgi-bin/webscr> to <https://www.sandbox.paypal.com/cgi-bin/webscr>. You also need to change the form's "business" field to the sandbox receiver email address.

Next up, we post the received data back to PayPal, so they can confirm that they actually sent it. We construct and post urlencoded form data to their server, then fetch the response. If it's VERIFIED, we're good:

    // Read the post from PayPal system and add 'cmd':
    $req = 'cmd=_notify-validate';
   
    foreach ($_POST as $key => $value)
    {
        $value = urlencode(stripslashes($value));
        $req .= "&$key=$value";
    }
   
    // Post back to PayPal system to validate:
    $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
    $header .= "Host: $paypalDomain:80\r\n";
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
   
    $fp = fsockopen($paypalDomain, 80, $errno, $errstr, 30);
   
    if (!$fp)
        exitWithError('PayPal', 'Unable to connect to the PayPal server.', $transaction);
   
    fputs($fp, $header . $req);
   
    $verified = false;
   
    // Read the response:
    while (!feof($fp))
    {
        $line = fgets($fp, 1024);
       
        if (strcmp($line, "VERIFIED") == 0)
            $verified = true;
    }
   
    fclose($fp);
   
    // Ensure PayPal verified the post:
    if (!$verified)
        exitWithError('PayPal', 'Received a transaction that PayPal did not verify as valid.', $transaction);

We then do some further checks, to ensure the payment went to the correct address, and the transaction has an acceptable status. I wrote this before realizing that pending transactions probably don't reach this point anyway (I think PayPal holds off notifying till they are completed), but it doesn't hurt to leave the pending logic in here:

    // Ensure the payment went to me:
    if ($transaction['receiver_email'] != $receiverEmail)
        exitWithError('PayPal', 'The receiver email was not correct.', $transaction);
   
    $transStatus = $transaction['payment_status'];
    $isPending = ($transStatus == 'Pending');
   
    if (!$isPending && $transStatus != 'Completed')
        exitWithError('PayPal', "The transaction status was $transStatus.", $transaction);

So now we've got a valid transaction, so can begin to process it. Continue to part 3 with the remainder of the code!

Time Out 1.5 released

Time Out version 1.5 is now in general release. It includes an improved icon (as seen on the Dejal site for a few months), a rearranged break layout, and the ability to change the postpone button intervals, or hide either of them and/or the skip break button, if desired. Plus some other minor changes and fixes. See the release notes and the blog entry on the beta release for more information.

Time Out 1.5 is freeware; you are welcome to use it at no cost. However, donations to support development of version 2 are always appreciated... and since I've announced version 2, everyone who donates (any amount!) will be eligible for a Time Out 2 license at no further cost. This offer will expire when Time Out 2 is released (after Leopard).

Download Time Out 1.5 now!

Prompt PayPal payment processing, part 1

I use two payment processors for Dejal: Kagi and PayPal. The Dejal Store powered by Kagi has been fully automated for years, so when a customer buys one of my products, Kagi queries my server, which generates a serial number and passes it back to Kagi's server, and the customer receives it automatically as part of Kagi's "Thanks for your purchase" message. This is very convenient for both me and the customer. (My products also include a Kagi-based store right within the app, which avoids the need to even enter the serial number.)

For the Dejal Store powered by PayPal, on the other hand, it has been a manual process. When someone purchased via PayPal, I received a notification of the payment in my email, which I copied to my home-grown license management app, which parsed it to generate the license, including creating an email message in Mail ready to send. This wasn't much work, but required manual processing on my part, which of course meant the customer had to wait for me before they got their license. I was usually very prompt, but if they bought while I was asleep or otherwise away from my machine, they had to wait. That's just not great service.

So this week I've spent the time to automate the PayPal processing. Now, if you buy from my PayPal store, PayPal will send my server a notification with the shopping cart contents. My server will then automatically add licenses and generate and send out email messages for each product purchased. So now purchasing from either store (or within the app) will give you your license details virtually immediately, with no need for waiting for me. Which of course means less work for me, too, so I can spend more time answering support questions or writing code.

Getting technical

Implementing the PayPal automation wasn't too difficult, though it took some research to find the best solutions. For the standard PayPal business accounts, they offer two automated payment notification services: Payment Data Transfer (PDT) and Instant Payment Notification (IPN). My initial research showed people using PDT, for example that's what the AquaticPrime framework uses. However, further research showed that this might not be the best choice. The way it works is to send the transaction information to your server when the customer is redirected back to your website after the purchase. But if they close their browser window or click away before they return to your site, your server doesn't get the transaction info. Also, you have to deal with pending transactions (e.g. eChecks), form reloads, and other issues.

So then I switched to using IPN. This is a more robust mechanism, but still quite simple to implement. In this case, the payment notification occurs in the background, whether or not the customer actually returns to your site. I believe that pending transactions aren't received until they clear, too. So this is more reliable and efficient.

Both services include fraud protections, in the form of posting the received data back to PayPal and getting a response. If they originated the data, they'll reply saying that it was confirmed, otherwise it's suspicious.

To make things more interesting, my store pages offer multiple products for sale, so I need a shopping cart. Most existing examples assumed a single buy button, but fortunately the PayPal data copes with shopping cart transactions in a fairly simple way, appending digits to the variables.

Continue reading part 2, with a discussion of the PHP code to implement this.

Too unintentionally with continuation sinking

Something I found amusing: I noticed a mention of the Time Out 1.5b1 release on Plateaus.com, a Japanese site (via my site referrers), and auto-translated it to English using Google... admittedly a beta translator. Here's what it came up with:

When work and music are done, (with saying, as for work almost it is Windows but), too unintentionally with continuation sinking, when the air is attached, the eye and the shoulder [gakugaku] is good.

This timeout as at the time interval which is appointed shown under, putting on the thin cover in the picture, (can adjust also transparency), in order to break, you teach. In addition, the script which is executed at the time of sound and start and the end which are let flow when starting and end break (also Automator, AppleScript and the Python script) or the appointment etc of application is possible.

Standard setting is, the public official of the country whether with "micro" break in 10 minutes 10 seconds, with "usually" break in 50 minutes 10 minutes (the [do] [tsu] of is like but), but you are appointment possible by your. It is useful unexpectedly. It is the freeware.

Auto-translation is hard, eh. :)

Time Out 1.5b1 released

It's been a while since the previous version, but Time Out 1.5 is now in beta release.

As mentioned a couple of times recently, version 1.5 is an interim release for 10.3.9 and up, before the big 2.0 upgrade, coming later this year for Leopard.

I've been using the new Time Out icon on the Dejal site since January, but till now the Time Out application itself has still used the "aesthetically challenged" old icon, which consisted of a very badly Photoshopped rendering of my hands in a "T" shape. I've never liked that icon, and I've certainly got lots of feedback over the years that you don't either... so it was a priority when I got Emily Pfeifer to redesign some of my app icons (and the Dejal logo). I'm very happy with the new design, and I hope you are too.

A subtle change is the name of the application. It used to be "Time Out!", with an exclamation point at the end of the name, but I'd grown to dislike that too, what with the hassles and untidiness it caused when referring to the application. So I've dropped the exclamation point from the name.

Feature-wise, 1.5 has a rearranged break layout, with the progress bar and buttons within a box, a more elegant font and color for the "Time Out" text, and the new icon, of course. By popular request, it also includes options to remove any or all of the buttons, and to change the postpone amounts. So if you find the temptation to skip a break too strong, you can get rid of the button to encourage you to take the break. Check out the release notes for more changes.

Here's a feature graphic for Time Out 1.5b1, as seen in rotation (with ones for Simon and Caboodle currently) on the Dejal home page:

Version 1.5 may be the last version of Time Out for Mac OS X 10.3.9 and later. Version 2 and beyond will require a minimum of Mac OS X 10.5, as they will leverage several of the great technologies introduced in Leopard. I'll keep 1.5 around for the foreseeable future, for people who haven't upgraded to Leopard.

And yes, 1.5 is still completely free! While version 2 will be shareware, I am currently planning to also offer a free Lite version, which will have the same features as 1.5, plus some extras.

Product positioning ponderings

As as been mentioned before, I'm working on Time Out version 2 (in between other projects), to be released once Leopard is publicly available.

At present Time Out is freeware. It probably shouldn't be, as it's a great, very popular product, but it started that way and has remained so thus far. That will change with version 2, which will include pretty much all of the most popular features people have been asking for over the last few years, many of which I've been keen to do but couldn't justify in a free version.

So version 2 and beyond will be shareware, and require a minimum of Leopard. However, I plan to keep version 1.5 (to be released soon) around for people who haven't yet upgraded to Leopard. Version 1.5 will remain free, and for 10.3.9 and later. That could also serve as an alternative for people who don't want the improvements in version 2 (or don't want to pay for Time Out)... but I'm also considering other options.

The latest such option to ponder is having a "Lite" edition of version 2. So there would be the standard Time Out 2, a shareware product, plus Time Out Lite 2, a freeware product. The Lite edition would have basically the same feature set as version 1.5, plus a few enhancements. The standard edition would have lots more new features. If the basic features were enough for you, you could use Time Out Lite at no cost, like you can use current versions. If you want the extra features, you install the standard Time Out and buy a license. Like my other products, you could install Time Out and try the full features for a while before deciding to buy.

A previous option that I thought of was to have just one Time Out 2 app, but two or three license levels, like for Simon. Under this approach, there would be a cheap Basic license with limited features, a Standard license with advanced features, and perhaps an Enterprise or Site license with the same features but allowing company-wide installation. This is different than the above approach in that there is no separate free edition; the differentiation is all in license levels. I do like the idea of keeping a free edition, though.

Another idea was similar to that one, having more of a "seat"-based approach. One license, the same features for everyone, but quantity discounts for multiple users. This is more like the Individual/Household/Site license model that I use for Caboodle and other apps. A seat-based approach could perhaps be combined with the latest approach (of standard and Lite editions).

What do you all think? Any preferences, or other ideas? Feedback would be appreciated, via the comments, the Time Out forum, or privately.

Simon 2.3 released

Simon version 2.3 is now in general release!

As previously discussed, this release includes a new Mount plug-in, that works both as a service and notifier, and allows mounting and unmounting local, AFP, and SMB volumes. It also extends the Script plug-in to act as a notifier too, allowing great flexibility in notifications. Plus many other enhancements and fixes. See the release notes for more information, or download now!

Multi-touch on the desktop

Craig Hockenberry wrote thought-provokingly about multi-touch interfaces on the desktop (via Gus Mueller).

This is a favorite topic of mine; as I've written before, I look forward to the day when multi-touch comes to desktop (or portable) computers.

One of his objections was the vertical orientation of traditional displays:

If you’re one of the people who think that a multi-touch monitor is a good idea, try this little experiment: touch the top and bottom of your display repeatedly for five minutes. Unless you’re able to beat the governor of California in an arm wrestling match, you’ll give up well before that time limit. Now can you imagine using an interface like this for an eight hour work day?

But he quickly counters that objection with what I feel is the obvious answer: a touch-based interface needs to be at a comfortable angle. I envision a desktop multi-touch surface at a 30-degree angle, or less, from the desktop: as he says, like a classic drafting table. Perhaps there won't be a distinction between desktop and notebook computers anymore, or perhaps the computer will be in two parts: a tablet-like mobile portion, which docks into and rests on a wedge-like stand on your desk, which adds additional functionality (kinda like the old PowerBook Duo and DuoDock).

The multi-touch screen would be the entire interface (other than perhaps some auxiliary buttons like brightness, volume, etc). It would obviously replace the mouse/trackpad, but would also replace the keyboard, using an onscreen keyboard instead. Yes, tactile feedback is an issue, but as many people have reported with their iPhones, it's possible to get used to typing without it; and there are ways to provide feedback, like the iPhone's magnified view of pressed keys, sounds, vibrations, and other ideas being worked on.

Hockenberry also raises a valid point regarding the precision of a mouse pointer vs a finger:

But even if there was a solution to the ergonomic issues, there would be problems mixing mouse-based applications (with small hit areas) with touch-based inputs (and large hit areas). Touch-based UI is not something you just bolt onto existing applications—it’s something that has to be designed in from the start.

Certainly an important consideration. However I would argue that most applications could be modified to support larger hit areas in sensible ways without too much difficulty - though in some cases major redesigns would be needed. Just have a look around the controls in your favorite apps, and think about how easy it would be to "click" on one with a finger, without activating a nearby control. In most cases, controls are spaced out enough for it to not be a problem, but some, like Photoshop, would require either optional support for a stylus (which Apple probably wouldn't be in favor of), or a finer on-screen control (perhaps like the iPhone's magnifying glass). I'm sure apps designed from the ground up with multi-touch in mind would be better... but migration is certainly possible. And yes, resolution independence should help. If you've got big fingers, you just scale everything up to a comfortable level.

I really believe that multi-touch is the way of the future, and will be coming for Macs in due course. But Apple being Apple, they will do it right, with as smooth a migration path for developers and users as possible.

Time Out featured on Lifehacker

Time Out is a featured download on Lifehacker today. They seem to like it, which is always nice. Lifehacker is a great productivity blog, that I read every day, and recommend to others.

I appreciate the publicity, though I kinda wish it had come in a couple of weeks time, as (by popular request) I am planning to release Time Out version 1.5 with the new icon, and a few other improvements, around that time.

If you've come here from Lifehacker or elsewhere to get Time Out, go ahead; the current version is very good... but the icon is somewhat aesthetically challenged. So come back in a couple of weeks to get 1.5 - Time Out will tell you when it's available.

Version 1.5 will remain freeware, for Mac OS X 10.3.9 and later.

As for Time Out 2, it is still in development, but will require Leopard (Mac OS X 10.5) as a minimum, so version 1.5 will tide people over till Leopard is out (and for people who don't upgrade).

Syndicate content