Casting about

A few months ago, I got tired of the constant “media file error” messages Downcast was sending me and began looking for another iOS podcatcher.

Downcast media file error

There are certain features I find essential in a podcatcher:

Other aspects of the user interface will color my opinion of an app, but these trump the rest.

I gave Instacast another shot, and the experience was, if anything, worse than the last time I tried it. Not only is the layout of the app not to my taste, the skip ahead and skip back buttons did absolutely nothing. To be fair, I reinstalled Instacast after it was updated earlier this month, and the skip buttons in the newer version worked just fine. Still, it’s not the app for me.

Pod Wrangler has perhaps the best scrubber in the business, and I have free access to its advanced features because I use Feed Wrangler as my RSS sync service. But it doesn’t give me download or playback order control I want.

Pod Wrangler scrubber

Castro gets points for the pun in its description—high fidelity podcasts—has a scrubber on par with Pod Wranger’s, and has a fun interface overall, with almost all the navigation done by swiping left and right. But the playback order control wasn’t there.

Castro mid-swipe

Pocket Casts was a very strong contender, with all the controls I need. Like Castro, it has a fun user interface. When you turn your phone over in an episode list, for example, the main body of the screen turns in place, but the mini-player strip “falls” from one end of the screen to the other.

Pocket Casts mid-flip

One thing I dislike about Pocket Casts is its sleep timer. Instead of just having a button to set the timer, it forces you tap a button and then move a slider. Not only is this awkward and slow, it’s unnecessarily precise. No one needs to-the-minute resolution on a sleep timer.

Still, because it had most of what I find essential in a podcast app, Pocket Casts had taken Downcast’s spot in my dock. Until I got invited to try the Overcast beta.

By now you’ve probably read several reviews of Overcast, so you don’t need me to tell you about its two killer features: Voice Boost and Smart Speed. I will, however, suggest that you experiment with both of them instead of just turning them on for all podcasts.

If a show tends to be well-recorded, the equalization of Voice Boost is unnecessary and will simply make the overall playback louder. This may not seem like a big deal, but I noticed on a recent car trip that Siri’s turn-by-turn instructions—which are usually at the same volume as whatever I’m listening to—were much quieter than the Voice Boosted podcast she was interrupting and were hard to hear. On the other hand, certain guests on In Our Time are so soft-spoken that even the heroic efforts of BBC’s recording engineers to turn up the gain can’t make them as loud a Melvin Bragg or the other guests. I expect Voice Boost to be a big help with those shows.

And while it’s nice to have dead air reduced, I wouldn’t use Smart Speed on The Bugle, because comedy relies on timing—including pauses. I’ve also found that John Siracusa without pauses is exhausting.

My favorite feature of Overcast is the natural way it allows you to reorder the episodes in any playlist. Just tap the Edit button in the upper right corner and start dragging.

Overcast playback reordering

This is a big advantage over Pocket Casts. In Pocket Casts, smart playlists—which it calls Filters—do not allow arbitrary reordering. Only playlists created by hand allow that. So you have to move episodes into an ad hoc playlist before you can set their order. This is not the greatest burden in the world, but the freedom Overcast gives you to rearrange smart playlists is clearly superior. I haven’t felt the need to make any new playlists in Overcast; I just rearrange episodes in the Unplayed list.

You might be wondering why I’m writing this post a week and a half after Overcast was released. It isn’t because I needed extra time with the app, nor is it because I’m lazy.1 When Overcast came out, I had just shifted back to Pocket Casts as a test. I figured that if I were comfortable with Pocket Casts after using Overcast, then there really wasn’t any reason to switch. But after a week of Pocket Casts, I found myself still missing features in Overcast. That’s when I knew Overcast was going to be my podcast app.

Overcast is by no means perfect. I have, for example, occasionally seen error messages similar to the “media file error” messages that drove me from Downcast. Fortunately, those have been quite rare and they’ve never caused Overcast to crash. So my months-long search for a podcast app I’m happy with is over.

  1. I am lazy, but that has nothing to do with the timing of this post. 

Presentations and expectations

You’ve probably heard by now about the latest bestseller from the MacSparky publishing empire: Presentations. In it, David Sparks does his usual thorough job of walking you through the nuts and bolts of building a presentation in Keynote. But Presentations is more than just a software manual. David also hands out good advice on hardware (including preparing for hardware disasters) and putting together a good performance.

David also fights the good fight for better presentations independent of software and hardware. The first two chapters in particular talk about what makes a compelling presentation, but there are nuggets of wisdom regarding pacing, focus, and effective storytelling sprinkled throughout. This is the stuff that’s most likely to be ignored—often because presentations are expected to be bad.

You may remember this article by Paul Ford from a couple of months ago that made fun of presentation slides used by the military. Theses slides violate all the conventional wisdom by being overpacked with words and graphics.

Example military slide

from Medium

Eric Hess had a very nice followup post a few days later. He didn’t defend the look of these presentations, but he did explain their genesis:

Tragically, the military shares a misconception with the rest of the government and much of the business world that the slides should be able to act as a substitute for the speaker. While you’d think this would drive presentation designers towards clarity, it often does exactly the opposite. Diagrams with bulleted annotations can rarely provide the clarity and fidelity of well-written prose supported by a few well-chosen graphics. Yet busy executives don’t want to take the time to read a multipage essay.

I don’t have any experience with the military, but what Eric says matches perfectly with what I’ve seen from manufacturers. When I start a new consulting project, I usually get sent a bunch of paperwork (sometimes on paper, more commonly on disc) with information on the product at issue. Inevitably, as I flip through the stack of drawings, photos, and test data, I’ll run into a series of pages that have to be turned from portrait to landscape: a PowerPoint deck describing some aspect of the product’s development. It’s not a report written with paragraphs that build on each other; it’s a set of graphs and disconnected sentence fragments arranged as bullet points.

It’s never clear to me whether there actually was a live presentation associated with the deck. But it is clear that the deck was expected to stand on its own—a substitute for the speaker, in Eric’s words—and that it was circulated among the relevant engineers and managers in the company and expected to be read as if it had all the information and clarity of a report.1

This is why all the well-intended advice on making good presentations doesn’t get followed. There is an expectation in many places that the slide deck will not simply be an adjunct to a presentation; it will be the only permanent record of the ideas and information contained in that presentation, and it is judged as such by the presenter’s superiors. When a slide deck takes on that burden, both it and the presentation lose the fluidity that David’s book tries to steer you toward.

The answer, of course, is to have both a written report and a presentation. This is the norm in the academic world, where the published paper is one thing and the talk based on it is another. But this is considered inefficient in most businesses, so the poor slide deck has to pull double duty. And ends up being bad at both jobs.

  1. Reports can be poorly written, of course, but they tend to be more disciplined and more coherent than slide decks. The need to write sentences that form paragraphs and paragraphs that form sections imposes a structure on the writer’s thinking. I can’t remember where I heard or saw this, but Andy Ihnatko once said something like “I don’t write to say what I think; I write to figure out what I think.” A bunch of bullet points won’t do that. 

Better window screenshots

For some time now, I’ve been using a homemade utility, snapflickr, for taking screenshots and automatically uploading them to Flickr. It worked really well for most screenshots, but there were some, like this one from yesterday’s post,

Character Viewer

that just don’t look right because the desktop background border is either too thin or uneven or both. Today I updated snapflickr to fix that.

The problem arose because I was including the drop shadow in window screenshots. There are some, like Dan Benjamin, who think this is an abomination. I agree that the shadows are too big, but don’t like the “open” edges of window screenshots that don’t have the shadow.

Character Viewer bare

On a white background, it looks like contents of the window are going to fall out.

As a compromise, snapflickr took screenshots with the shadow, cropped them down to a more reasonable size, and then composited them on top of a Solid Dark Aqua Blue background color. This worked fine for most windows, which have standard sized shadows, but palette and other utility windows often have smaller shadows. Cropping that looked fine on a normal window looked like shit on a palette window. I tried less cropping for palette windows, but apparently they don’t all use the same size shadow. As you can see from the top screenshot, the lesser cropping didn’t always lead to nice results.

So now snapflickr takes a different approach to window screenshots. It doesn’t include the shadow but adds a 16-pixel border around the outside to provide definition.

Character Viewer with background border

This looks good with any type of window and is what I should have done from the beginning.

Because I sometimes use snapflickr to take screenshots of a rectangular area instead of a window, I needed to add an option not to include the border. That wasn’t too hard.

snapflickr dialog

The border is selected by default, because that’s what I want most often, but it can be turned off if necessary.

The snapflickr source code is in this GitHub repository. It requires the Python Imaging Library to add the border, Carsten Blüm’s Pashua application/library to display the dialog, and Sybren Stüvel’s Flickr API module to do the uploading.

Scripting your scripting

A couple of days ago, Rob Trew tweeted a link to a shell script he wrote that prints out an emoji clock face based on the time it’s given.

Simple bash .sh gets emoji clockface (stdout|clipboard) with specified time (to nearest preceding half hour)…

ComplexPoint (@ComplexPoint) Jul 22 2014 10:31 AM

It sounded like a fun little programming project and possibly even useful.1 Because I wanted to round to the nearest half hour instead of the nearest preceding half hour, and because my shell scripting is abysmal, I decided to rewrite it in Python.

I knew immediately that the key feature of my script would be a dictionary that mapped a time written as text, like “8:30,” to the corresponding emoji, 🕣. The rest of the script would just be input, output, and rounding. Here’s the script:

 1:  #!/usr/bin/python
 2:  # -*- coding: utf-8 -*-
 4:  from sys import argv
 5:  from time import strftime
 7:  clocks = {'12:00': '🕛', '12:30': '🕧',  '1:00': '🕐',  '1:30': '🕜',
 8:             '2:00': '🕑',  '2:30': '🕝',  '3:00': '🕒',  '3:30': '🕞',
 9:             '4:00': '🕓',  '4:30': '🕟',  '5:00': '🕔',  '5:30': '🕠',
10:             '6:00': '🕕',  '6:30': '🕡',  '7:00': '🕖',  '7:30': '🕢',
11:             '8:00': '🕗',  '8:30': '🕣',  '9:00': '🕘',  '9:30': '🕤',
12:            '10:00': '🕙', '10:30': '🕥', '11:00': '🕚', '11:30': '🕦'}
14:  # Get the argument, which should be a time string, like "8:10."
15:  # If there's no argument, use the current time.
16:  try:
17:    oclock = argv[1]
18:  except IndexError:
19:    oclock = strftime('%I:%M')
21:  hour, minute = [ int(x) for x in oclock.split(':') ]
23:  # Round to the nearest half-hour, because there are no
24:  # emoji clockfaces for other times.
25:  rminute = int(round(float(minute)/30)*30)
26:  if rminute == 60:
27:    rminute = 0
28:    hour = 1 if hour == 12 else hour + 1
30:  print clocks['%d:%02d' % (hour, rminute)]

The dictionary is defined in Lines 7–12. By including the encoding line at the top of the script, I was able to include the clock faces directly in the source code instead of messing around with hex character codes.

But the script itself isn’t the point of this post. What I really want to talk about is how I wrote it. I knew what Lines 7–12 were going to look like, and I really didn’t want to type it out. Not only would it be tedious, I’d almost certainly make an error somewhere. So I used a combination of IPython and BBEdit’s search-and-replace tools to build Lines 7–12 step by step.

Step 1 was generating a list of times. I used these commands in an IPython session to print a list of times, one per line:

for h in range(1, 13):
  print "'%d:00'\n'%d:30'" % (h, h)

I copied this into a BBEdit window, moved the last two lines, 12:00 and 12:30, to the top, and did this find-and-replace:

BBEdit replacement dialog

This gave me a single line that looked like this,

12:00', '12:30', '1:00', '1:30', '2:00', '2:30', '3:00', '3:30',
'4:00', '4:30', '5:00', '5:30', '6:00', '6:30', '7:00', '7:30',
'8:00', '8:30', '9:00', '9:30', '10:00', '10:30', '11:00', '11:30', '

which I’ve broken up here for ease of reading. I cleaned up the front and rear to turn it into a Python list assignment,

times = ['12:00', '12:30', '1:00', '1:30', '2:00', '2:30', '3:00',
'3:30', '4:00', '4:30', '5:00', '5:30', '6:00', '6:30', '7:00',
'7:30', '8:00', '8:30', '9:00', '9:30', '10:00', '10:30', '11:00', '11:30']

which I entered into my IPython session.

Step 2 was to do a similar thing for the clock faces. I “typed” them in, one per line, using the Character Viewer,

Character Viewer

and then converted them into a list assignment that I entered into IPython.

faces = ['🕛', '🕧', '🕐', '🕜', '🕑', '🕝', '🕒', '🕞', '🕓',
'🕟', '🕔', '🕠', '🕕', '🕡', '🕖', '🕢', '🕗', '🕣', '🕘', '🕤',
'🕙', '🕥', '🕚', '🕦']

Now comes the fun part. With times and faces defined, it was easy to generate most of the dictionary assignment statement with

print ",  ".join("'%s': '%s'" % (t, f) for t, f in zip(times, faces) )

That gave me this string

'12:00': '🕛',  '12:30': '🕧',  '1:00': '🕐',  '1:30': '🕜',
'2:00': '🕑',  '2:30': '🕝',  '3:00': '🕒',  '3:30': '🕞',
'4:00': '🕓',  '4:30': '🕟',  '5:00': '🕔',  '5:30': '🕠',
'6:00': '🕕',  '6:30': '🕡',  '7:00': '🕖',  '7:30': '🕢',
'8:00': '🕗',  '8:30': '🕣',  '9:00': '🕘',  '9:30': '🕤',
'10:00': '🕙',  '10:30': '🕥',  '11:00': '🕚',  '11:30': '🕦'

where, again, I’ve added line breaks here to make it easier to read.

A few quick edits turned that string into

clocks = {'12:00': '🕛', '12:30': '🕧',  '1:00': '🕐',  '1:30': '🕜',
           '2:00': '🕑',  '2:30': '🕝',  '3:00': '🕒',  '3:30': '🕞',
           '4:00': '🕓',  '4:30': '🕟',  '5:00': '🕔',  '5:30': '🕠',
           '6:00': '🕕',  '6:30': '🕡',  '7:00': '🕖',  '7:30': '🕢',
           '8:00': '🕗',  '8:30': '🕣',  '9:00': '🕘',  '9:30': '🕤',
          '10:00': '🕙', '10:30': '🕥', '11:00': '🕚', '11:30': '🕦'}

which is the nicely formatted dictionary assignment statement you see in Lines 7–12.

Does this seem like more work than just typing it out? It wasn’t. One of the great things about writing scripts frequently is that you become fluent enough to know instinctively how cobble together little bits of code like this. You also learn that some things, like the beginning and end of a list assignment statement, are more efficiently done by typing than by programming, so you don’t waste time trying to script those parts.

Sometimes your first instinct is a little off. I initially wrote the line that built the dictionary string this way:

print ", ".join("'%s': '%s'" % (t, f) for t, f in zip(times, faces) )

Do you see the difference? There’s only one space after the comma in the joining string instead of two. When I saw the output of this statement, I realized that to get the times lined up nicely I’d need a mixture of one and two spaces, depending on whether the hour was a one- or two-digit number. Since there are nine one-digit hours and only three two-digit hours, it would be faster to put two spaces everywhere and delete one in front of the two-digit hours. I reran the line with two spaces after the comma and saved myself twelve edits.

I’m sure there are still better ways to do this, further tricks that would have saved me even more typing. But even though I didn’t save as much time as I might have, I still saved a lot, mainly because I automated all the quotes, colons, and commas that I tend to mistype.

  1. It is useful for Rob. He makes links in FoldingText to his timed Reminders and includes the appropriate clock face in the link text.