If you were an admirer of the seminal Penguin Café Orchestra, then you might like Penguin Cafe, a sort of spiritual reconstitution thereof by founder Simon Jeffes’s son Arthur:

Penguin Cafe was founded by Arthur Jeffes in 2009, bringing together a diverse and disparate group of musicians from the likes of Suede, Gorillaz and Razorlight, initially to perform his father Simon Jeffes’ legacy of world renowned Penguin Cafe Orchestra music, ten years after his untimely death in 1997.

Arthur, a composer in his own right, quickly began to create new and unique genre-defying music, with the spellbinding philosophy of the Penguin Cafe always in his mind.

The recently-released The Imperfect Sea is both of and a departure from the fathership. It’s available from the excellent Erased Tapes, which has itself just turned 10 and released a fresh new website.

You can’t do much better than putting the Erased Tapes back catalogue into a Spotify playlist and letting it run all day.

Penguin Cafe album cover for The Imperfect Sea
🗓️

Lost in the shuffle of the Amazon Echo Dot that we’ve been using for the past month is its capacity to receive as well as send via Bluetooth.

I knew you could pipe the audio from the Echo into a Bluetooth speaker; what I only realized today is that you can pipe the audio of other services—like a phone or tablet—to the Echo.

For me this solves the problem of there being no SoundCloud skill for the Echo: I can simply use the Android SoundCloud app and send the audio to the Echo. Because the Echo is hardwired to our hifi, this gives me a handy bridge to blasting SoundCloud audio into the living room.

🗓️

I was either mistakenly issued two double machiattos, or an anonymous suitor was trying to pick me up. Regardless, I’m now exceedingly well-caffeinated.

🗓️

I use Apache Solr, and the related Drupal module, to power the search on this site.

Something that’s always bothered me about the out-of-the-box way this displays search results is that the date display with each search result is the “date the content was last changed.”

So, for example, for this post I wrote in 2015, the date that appears under the search result (when I search the site for pickles) isn’t November 1, 2015, when I wrote the post, but rather July 7, 2016, when it was last updated:

Things I’ve Liked Recently

favourite meal there: toast (from Breadworks bread), smoked salmon, vegetables, pickled onions and cheese. …

Peter Rukavina - 2016-07-03 11:22 - 1 comment

Because Drupal’s very vigilant about keeping the “changed” date current, this date can get updated for a lot of different reasons.

For example, on July 3, 2016 I used the Search and Replace Scanner module do to some automated processing of almost every post here, and Drupal dutifully updated the “changed” date for all of the affected posts to July 3, 2016. That’s fine for auditing purposes, but it just creates confusion for displaying search results, when what I want to know is when was this written.

There are various ways to fix this: altering Solr so that it indexes the created rather than changed date, altering the search results template so that it looks up the created date and displays it, etc.

But the simplest approach, assuming you’ve no need to track revisions, is to simply update the changed dates to match the created dates, via a MySQL query, like this:

UPDATE node SET changed = created;

Once I did that, and then deleted the Solr index and re-indexed everything, the dates in search results became much more helpful:

Things I’ve Liked Recently

favourite meal there: toast (from Breadworks bread), smoked salmon, vegetables, pickled onions and cheese. …

Peter Rukavina - 2015-11-01 14:35 - 1 comment

This is a “nuclear option,” inasmuch as you lose the audit trail for each node. But it was quick and painless for me.

🗓️

Just enjoying Charlottetown Monthly over coffee. Only 33 years out of sync. Great article about Danny Dan MacDonald.

Photo of Charlottetown Monthly magazine cover from 1984
🗓️
Magazines  •  Charlottetown  •  History  •  Coffee
Audio file

I had my first Alexa Skill certified today, one I built over the past couple of weeks for City Cinema here in Charlottetown.

“Alexa Skills” are custom apps built for Amazon’s voice-controlled Echo line of products; think of them as a very early prototype of the computer on Star Trek, but lacking most of the artificial intelligence.

While Echo devices aren’t yet available for sale in Canada, they work in Canada, at least mostly, and it’s clear they’ll be here eventually. So it’s a good time to build up some “voice app” muscle memory, and City Cinema was a good, simple, practical use case.

Simple and practical because there’s really only one thing people want to know about City Cinema: what’s playing. Tonight. On Friday. Next Thursday.

So here’s a high-level overview of what it took to make an Alexa Skill.

First, I needed to select an Invocation Name. This is the “trigger word” or the “app name” that Alexa will glue to my skill. I selected the obvious: City Cinema.

Next, I created an Intent Schema, a JSON description of the things my skill can do, its methods, in other words.

In this case, it can only do a single thing–tell you what’s playing–so there’s only a single intent defined, WhatsPlaying, that has an optional parameter (called a “slot” in Alexa-speak), the date. There are also a few built-in intents added to the schema to allow me to define what happens when a user answers “yes” or “no” to a question, and when they cancel or stop.

{
  "intents": [
    {
      "intent": "WhatsPlaying",
      "slots": [
        {
          "name": "Date",
          "type": "AMAZON.DATE"
        }
      ]
    },
    {
      "intent": "AMAZON.YesIntent"
    },
    {
      "intent": "AMAZON.NoIntent"
    },   
    {
      "intent": "AMAZON.CancelIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    }
  ]
}

Next, I defined the Sample Utterances, a list of the actual things that users can say that will initiate a “what’s playing” lookup:

WhatsPlaying what's playing on {Date}
WhatsPlaying what's playing {Date}
WhatsPlaying what's on {Date}
WhatsPlaying what's showing on {Date}
WhatsPlaying what is playing on {Date}
WhatsPlaying what is playing {Date}
WhatsPlaying what is on {Date}
WhatsPlaying what is showing on {Date}
WhatsPlaying showtimes for {Date}
WhatsPlaying what are the showtimes for {Date}
WhatsPlaying what are showtimes for {Date}
WhatsPlaying showtimes for {Date}
WhatsPlaying the schedule for {Date}
WhatsPlaying schedule for {Date}

Defining these utterances is where you realize that a lot of what we call “artificial intelligence” is still very ELIZA-like: a nest of if-then statements.

Finally, I pointed the skill at an API endpoint on a server that I control. There are no limitations here other than that the endpoint must be served via HTTPS.

From this point, I could code the endpoint in whatever language I liked; all I needed to do is accept inputs from Alexa, and respond with outputs.

I opted to code in PHP, and to use the nascent third-party Amazon Alexa PHP Library as a convenience wrapper.

There are a bunch of things the endpoint must do that using this wrapper makes easier: requests must be validated as having come from Amazon, and there must be application logic in place to respond to LaunchRequest, SessionEndedRequest, and IntentRequest requests.

Other than that, the heavy lifting of the skill is relatively simple, at least in this case.

When a user says, for example, “Alexa, ask City Cinema what’s playing tonight,” Alexa matches the utterance to one of those that I defined, WhatsPlaying what’s playing {Date}, and passes my endpoint the intent (WhatsPlaying) and the date (as YYYY-MM-DD).

So I end up with a PHP object that looks, in part, like this:

[intent] => Array
    (
        [name] => WhatsPlaying
        [slots] => Array
            (
                [Date] => Array
                    (
                        [name] => Date
                        [value] => 2017-03-02
                    )

            )

    )

From there I just use the same business logic that the regular CityCinema.net site uses to query the schedule database; I then munge the answer into SSML (Speech Synthesis Markup Language) to form the response. I pass back to Alexa a JSON response that looks like this:

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "type": "SSML",
      "ssml": "<speak><p>Playing at City Cinema on <say-as interpret-as=\"date\">????0302</say-as>: Jackie<break strength='weak'/> at <say-as interpret-as=\"time\"> 7:00</say-as>.</p><p>Do you want to hear a description of this film?</p></speak>"
    },
    "card": {
      "content": "Jackie at  7:00",
      "title": "Playing Thursday, March  2",
      "type": "Simple"
    },
    "shouldEndSession": false
  },
  "sessionAttributes": {
    "Operation": "FilmDetails",
    "Date": "2017-03-02"
  }
}

While I can return a plain text reply, using SSML allows me to express some additional nuance in how dates and times are interpreted, and to insert breathy pauses when it helps to increase clarity.

Note that I also pass back some sessionAttributes values, Operation and Date. This allows me to respond properly when the user says “yes” or “no” in reaction to the question “Do you want to hear a description of this film?”; they are, in essence, parameters that are passed back to my endpoint with the follow-on intent. Like this, in part:

case 'AMAZON.NoIntent':

  if (array_key_exists('Operation', $alexaRequest->session->attributes)) {
    $operation = $alexaRequest->session->attributes['Operation'];
  }
  switch ($operation) {
    case "FilmDetails":
      $message = "<speak>";
      $message .= "Ok, see you at the movies!";
      $message .= "</speak>";
      $card = '';
      $endSession = TRUE;
      break;
  }

  break;

The Alexa Skills API also provides facility for passing back a “card,” which is a text representation (or variation) of the speech returned.

For example, for a “what’s playing” intent, I return the name of the film and the time; if the user answers “yes” to the “Do you want to hear a description of this film?” question, then I follow up with a card that includes the full film description (I experimented with passing this back for speaking, but it was too long to be useful).

An example of some "cards" returned to the Alexa Skills API.

And that’s it. The application logic is a little more complex than I’ve outlined, mostly to handle the edge cases and the required responses to things like a request without a date, or a request like “Alexa, launch City Cinema.” But the PHP endpoint code only runs 257 lines long. It is not rocket science.

There’s an Apple-like certification process that happens once you’re ready to launch a skill to the public; in my case I submitted the skill for certification at 11:00 a.m. on February 28 and got back a positive response on March 2 at 1:46 a.m., so it was a less-than-48-hour turnaround.

The skill is now live on Amazon.com.

I foolishly selected “Canada” as the sole country where it would be available when I submitted the skill for certification; because the Echo isn’t available in Canada, this renders the skill effectively unusable for the moment because to use an Echo in Canada you have to pretend to be in the U.S.

I’ve opened this up to all countries now, which requires a re-certification. So in a few days the world should have access to the skill. And, eventually, when the Echo gets released in Canada, the skill should be of practical utility to Echo owners in the neighbourhood.

🗓️
Alexa  •  Amazon Echo  •  City Cinema

You’ve been unexpectedly imprisoned in a hellish overseas grotto. Besides your captors, the only person present is another prisoner, one cell over. You cannot see them, but if you whisper, you can communicate without being overheard.

As the days wear on, together you begin to develop a plan for escape.

You are nervous, though: much depends on your ability to trust your fellow prisoner, and your furtive whispered conversations have done little to offer you any evidence this is wise.

You decide to bring things to a head before continuing, and so, using a stray piece of coal and a page ripped from the only book in your cell, you fashion a crude note.

“No, No, No,” you write.

After lights-out you manage to toss the note into your coconspirator’s cell.

The next evening the crumpled note returns.

“Yes, No,” has been added.

Escape is in your grasp.

🗓️

Twenty-two years ago this November I attended the Atlantic Provinces Library Association conference for the first time; I produced a pre-conference workshop on “the Internet,” and took participants through the basics of this novel thing called HTML in a computer lab on the University of PEI campus. By coincidence, at the same time as I was conducting the workshop I was also scheduled to appear on Morningside for the first time. It was a heady day.

The APLA conference is back in Charlottetown again this year, running May 23 to 26, 2017 from the Rodd Charlottetown Hotel. And I’m back on the program again, this time around with a talk titled Why your Library Needs a Hacker in Residence: (and What I’ve Learned by Being One):

Four years ago I was appointed Hacker in Residence at the University of Prince Edward Island’s Robertson Library. The appointment came out of my desire, as a non-librarian, non-academic technologist and libraryophile, to find a way to engage more fully in the life of the library, and to use the lens of librarianship and the academy to inform my work in the community. The position is unpaid and comes with no responsibilities; I’ve variously succeeded and failed at making the best of it. And in this talk I’ll tell my story, leading to some thought about why your library might benefit from following the same path.

Conference registration is open now, and you need not be a librarian to attend: there are a compelling collection of sessions, from bookbinding to data visualization, and if you are interested in libraries, technology, and society I heartily encourage you to attend.

🗓️

If you’re a Mac user, do yourself a favour and change the keyboard shortcut for “Send” in Mail.app to ⌘⏎ (Command + Enter).

This is so much easier to trigger than the default ⌘⇧D (Command + Shift + D).

Screen shot of macOS System Preferences > Keyboard > Shortcuts

🗓️

In (yet another) design pattern to fix the mobile web, Google proposes PRPL, writing, in part:

At the same time, the bulk of our computing has moved from powerful desktop machines with fast, reliable network connections to relatively underpowered mobile devices with connections that are often slow, flaky or both. This is especially true in parts of the world where the next billion users are coming online.

One of the benefits of having been around for Web 0.0 is that I recall the last time this statement was true: “relatively underpowered devices with connections that are often slow, flaky or both” is what the Internet was in 1990.

We know how to build for these conditions because we’ve already done it.

The essential character of this Internet assumes a flaky network; it’s baked right into the technical DNA. Perhaps we need to focus less on figuring out how to cache and optimize the cruft and gloss we’ve introduced in the intervening years, and recapture the value of thrift, elegance and economy.

🗓️
Google  •  Internet  •  Design

About This Blog

Photo of Peter RukavinaI am . I am a writer, letterpress printer, and a curious person.

To learn more about me, read my /now, look at my bio, listen to audio I’ve posted, read presentations and speeches I’ve written, see things I’ve favourited elsewhere, or get in touch (peter@rukavina.net is the quickest way).

I have been writing here since May 1999: you can explore the 25+ years of blog posts in the archive.

You can subscribe to an RSS feed of posts, an RSS feed of comments, an RSS feed of favourites elsewhere, or a podcast RSS feed that just contains audio posts. You can also receive a daily digests of posts by email. I also publish an OPML blogroll.

InstagramYouTubeVimeoORCIDOpenStreetMapInternet ArchivePEI.artDrupalGithub.