Wednesday, January 11, 2012

How Third-Party Apps Should Use Siri

Apple’s Siri is a “digital assistant” for iPhone 4S and, presumably, various other products to be released in the future. I expect it will come to the Mac at some point too.

I haven’t used Siri, but I have been following the developments because I think she (in the UK, apparently a he) will become a very big deal once there is an easy way for third-party applications (App Store apps) to take advantage of the voice recognition and natural-language processing Apple runs on its servers.

There has been a lot of discussion online about how this could be done without various apps stepping on each other’s toes. If I say “Siri, remind me at six about Tarkan’s birthday party,” which calendar program will it use for the reminder?

In this case, it will obviously use Apple’s. You could make that configurable but I really doubt Apple would.

I think the answer is as easy as it is obvious, and easier than it is awkward. Apple controls (approves) the name of every app in the App Store. It can easily allow developers to choose a “Siri Name” for an app, also subject to central approval. Keeping these unique should not be hard.

Then you simply tell Siri whom to tell (or ask) what. Much like you did in Applescript, if you had a Mac in the 90’s (or are a total masochist today).

For an app named “Candy Store,” it might go like this:

HUMAN TO SIRI: Siri, ask Candy Store if they have blue gumdrops.
SIRI TO CLOUD: <...sends audio...>
CLOUD TO SIRI: Parsed OK for "Candy Store" : "find 'blue gumdrops'"
SIRI TO APP:   find 'blue gumdrops'
APP TO SIRI:   OK, in stock, $6/dozen.  Options: order, view.
SIRI TO HUMAN: Candy Store has blue gumdrops for six dollars per dozen.
               You can view them or order them if you like.
HUMAN TO SIRI: Order six dozen please.

Siri would of course know the context of that last command, because Siri is tracking a conversation and not just individual commands. You could also be very direct:

HUMAN TO SIRI: Siri, tell Candy Store to cancel next week's shipment.
...
SIRI TO HUMAN: Your Candy Store shipment of four hundred mixed jellybeans
               for Monday, January 16 has been canceled.

If I were Apple I would start this with a very, very simple API, supporting only the simplest directives like “find” and “order” and “do,” but also sending the original text to the app in case the app wants to do its own parsing.

But that’s probably way too utopian of me. Apple will no doubt wait until there is a huge NSDigitalAssistantRequest API and statically-typed conversations and 30% of any digitally-assisted sale going to Cupertino, and start with three hand-picked third-party apps for a year-long trial run before mere mortals are allowed in.

Even then, it could of course be huge.

Labels: , ,

Sunday, November 20, 2011

Meta: old comments published, sorry.

I just realized I had not moderated comments in six million years.

So I did, and published the non-spammy ones. In case there is some kind of notification system and you get an e-mail that your comment from 1932 has been published on this blog: my apologies for the tardiness.

Labels:

UITapGestureRecognizer and “unrecognized selector sent to instance” errors.

This is just a very quick note for search engine posterity, in case anybody has the same frustrating problem I had today.

I am implementing some gestures for an iOS art app (as in a work of media art, the "medium" of which is an iPhone/iPad application). I was following the "Event Handling Guide for iOS" from Apple.

After much Googling and some very informative stops at StackOverflow, I had got basically nowhere. Everything seemed right, my code conformed tightly to the tutorial and to everyone else’s, and everybody else who found a solution had obviously solved a very different core problem than I was facing. What could be wrong?!

It turns out the problem was as simple as:

-(void) handleTap
{
    NSLog(@"*** GOT A TAP ***");
}
    

Now, in real life you would almost never use a method as dumb and simple as that, but when setting up your classes for initial hacking and debugging you just might. According to the tutorial, it should work:

The action methods for handling gestures—and the selector for identifying them—are expected to conform to one of two signatures:
- (void)handleGesture
- (void)handleGesture:(UIGestureRecognizer *)sender

Silly programmer, tricks are for kids! The standard-issue selector looks for only the second signature, and if it doesn’t find it you get the error whenever you tap: unrecognized selector sent to instance! boo!

The solution, then, is to declare and implement the method with the argument. That works fine.

-(void) handleTap: (UIGestureRecognizer *)sender
{
    NSLog(@"*** GOT A TAP ***");
}
    

To be fair, Apple has an enormous amount of documentation available online, and it’s not so shocking that a tutorial is out of date. For us iOS newbies it’s frustrating, but I don’t think anybody else is doing a better job of this at the moment.

Labels: , ,

Friday, October 14, 2011

Rough Draft Epitaph

So many important people have died this year, I thought it best to have at least a rough draft of an epitaph on record in case I need one. I feel fine, but you never know. Ergo:

HERE LIES THE FROST
man under ground.
His hair was long,
his belly round.
He lived quite long
for the risks he took,
but never did manage
to write that book.

Labels: ,

Friday, August 05, 2011

Perl ExtUtils::MakeMaker test overrides (for Makefile.PL).

Nerd post follows; non-nerds, move along.

This took me a while to figure out, and in the end I had to dig around in the source code to figure out just what was going on, so here’s a quick note for posterity since I’m sure somebody else will have exactly this problem at some point. Caveat lector: I’m probably making a bunch of mistakes here. And thanks to brian d foy for showing us how to use test_via_harness.

Basically what it boils down to is this: you are going to have either a bunch of test files in a t directory, or a single test.pl file in the main directory. Or possibly both.

The thing you need to override is different in each case. You might just want to do both in case you change your mind later about the test setup.

Let’s say, for instance, that my special little requirement is that I can get at some shared libraries in the /opt/special/lib directory. The examples below should be understood as code inside your Makefile.PL file. And yes, they are almost identical in this case.

For test.pl override test_via_script.

sub MY::test_via_script {

    my ( $self, $perl, $script ) = @_;

    # Here is some special sauce for the environment:
    my $env_setup = 'LD_LIBRARY_PATH=/opt/special/lib';

    # Here are some Makefile variables that are handled by `make`:
    my $harness_args =
      '"$(TEST_VERBOSE)", "$(INST_LIB)", "$(INST_ARCHLIB)"';

    # Here's the command that will create the target:
    my $command =
      sprintf "\t%s %s -MExtUtils::Command::MM -e 'test_harness(%s)' %s",
      $env_setup,
      $perl,
      $harness_args,
      $script;

    return $command;

}

For t/*.t override test_via_harness.

sub MY::test_via_harness {

    my ( $self, $perl, $tests ) = @_;

    # Here is some special sauce for the environment:
    my $env_setup = 'LD_LIBRARY_PATH=/opt/special/lib';

    # Here are some Makefile variables that are handled by `make`:
    my $harness_args =
      '"$(TEST_VERBOSE)", "$(INST_LIB)", "$(INST_ARCHLIB)"';

    # Here's the command that will create the target:
    my $command =
      sprintf "\t%s %s -MExtUtils::Command::MM -e 'test_harness(%s)' %s",
      $env_setup,
      $perl,
      $harness_args,
      $tests;

    return $command;

}

Etc. & So On

I think it’s a much better practice to keep your test files in t/ anyway, and to always run with the test harness. In fact I usually skip the explicit test harness altogether and run everything with the appropriate prove command (the one that belongs to the Perl I’m using).

However, if you’re dealing with legacy code or not interested in doing real Perl stuff or otherwise just need to “get on with it” then you might well need a test.pl – and remember, test_via_script for that guy!

Here are the obvious links you should follow if you want to know more about this:

And finally, for anyone nerdier than I who is reading this: I know about package MY and I agree it’s probably the better solution, but I think it’s (even more) confusing for novices; and I assume at least some people trying to do this aren’t even Perl programmers.

Labels: , , , ,

Monday, May 02, 2011

Seen Today

  1. A 200HUF cappuccino.
  2. Szamoca vs. Eper.
  3. A mini-skirt! 'Tis the season!
  4. Bright sunlight through green glass socialist balconies.
  5. Prolis, pornósmellü, rövidlábú daughter of the café proprietress.
  6. A one-legged man walking a husky.
  7. Public-service street art sampling both Star Wars and Red Robot.
  8. A giant pink Hello Kitty poster at the optometrist's.
  9. Written on the Bortársaság delivery van, the optimistic take on modern Hungary: “MINDEN RENDBEN A BOR FINOM.”

Labels:

Thursday, April 21, 2011

Buying Art (for cheap) is Fun

I recently attended a silent auction, the modest proceeds of which went to the IFRC. The things being auctioned were artworks, mostly on paper. I got three, about which more in a future post after I photograph them. But I will at least give a sort of preview: Two by Ryuta Suzuki and one by Kati Verebics.

It’s a safe bet that I got all three well under market value. I almost got into a little bidding war with someone, but he mysteriously declined to bid on the things I wanted, perhaps intimidated by my hovering around waiting to double down. And I had passer’s remorse about not having bid on something, until I found out the winning bid belonged to a very nice guy.

I don’t often buy art. Very rarely in fact. And not because it’s expensive; while it can be very costly there’s always something you can afford, however minor. The thing is, if you’re collecting art you have to put it somewhere, and you feel sort of bad if that somewhere isn’t a wall.

I suppose you know you’re actually collecting art when you no longer feel bad about not displaying it. I could imagine getting to that point, or if you like falling into that trap, but not soon. I’ve got a sweet little apartment with more windows than walls, and a lot of geographic instability in the mix, and I’m not yet ready to invest in another flat file. Not quite yet.

It’s probably not an easy thing putting together a charity auction. This one had some local artists I’d heard of (including a few I know personally); and some I hadn’t heard of; and some strangers from far afield, whose contributions were sometimes relevant and sometimes not. The quality was very uneven, but in Budapest the quality of a museum show can be just as uneven (I’m lookin’ at you, MüPa!).

Some good things about the auction: admirable transparency about the finances; no hidden reserves; good art on the cheap for a good cause.

Some less-good things: no alcohol (what were they thinking?); a rather, shall we say, distant house staff; no real PR about the artists or works (remember, most people at a charity auction know nothing about art); and, sadly, not enough people wanting to spend money.

As one of the modestly solvent people in the room, I definitely would have spent more on the works I bought if there had been enemy bids. I wouldn’t have gone to the moon, but I definitely would have gone to double what I spent. In one case I almost felt like bidding against myself but part of the adrenalin kick of an auction, even a noncompetitive one, is the tension between wanting what you want, and wanting to get it at the lowest price going.

I know these things are easier said than done, but it seems to me that there are some obvious steps to help raise more money at a charity auction. So I shall play Lucy for a moment and offer...

Cheap Advice for Silent Charity Auctions

  1. Work your connections and get every well-off person you know to attend.
  2. “Well-off” means “able to place the lowest available minimum bid without pain.”
  3. Have plentiful, non-shitty free booze. Get it sponsored of course.
  4. Have a friendly, attractive staff serving the plentiful free booze.
  5. Flatter people unnecessarily.
  6. Make it easy to bid competitively and anonymously.
  7. Have professional promotional materials on hand about your cause, your beneficiary, and every artist.
  8. Include take-home materials, e.g. a high-production-value flyer.
  9. If you don’t know how to do that yourself, get somebody who does know to do it for free for the good cause.
  10. Apply the rule above to every aspect of the auction. You’re already a hero for organizing it in the first place.

In short, it was fun, I totally scored, and I think I’ll try this sort of thing again. But first I have to find a good framer.

A Parting Thought On the Arts and the Web

Why is it that artists and cultural institutions, much like restaurants, generally have not heard the news that Flash-only websites are broken and reflect badly on their owners?

In the case of individual artists, I’m inclined to think of it as similar to the restaurant problem. Creative people get talked into some gimmicky animation and don’t know any better, so up it goes. But when a well-funded Palace of the Arts hires some clueless two-bit company to rain misery on its potential ticket buyers, then I have no choice but to smell a rat.

An example of the first: Mr. Suzuki’s portfolio. Of the second: MuPa.hu, a study in inaccessibility.

Labels: