Saturday, January 15, 2011

Extracting Sonos Playlists - A Simple Sonos JavaScript Application, Take II

Overview

(The code on this page was last checked and verified in June 2014.)

Did you ever want to extract a Sonos playlist so you could share it or keep it for your records outside of Sonos? Well you can. In this post we’ll talk about some simple ways to do it. First, let’s start with a little history. We’ve written about Sonos a couple of other times in the blog. First we showed how to explore your Sonos UPnP topology and then we wrote a simple program using JavaScript to query Sonos (via SOAP requests) to display basic information about what was playing (on GitHub). A reader of the latter blog entry asked the question about generating playlists, and then contributed a Java program which does it (on GitHub). Still later (a year), we developed a WPF application (see WPF Application to Save and Import Sonos Playlists) to extract lists. This post summarizes all the approaches:


  • First Approach - Manual
    The approach requires minimal programming – you work with DeviceSpy (or something equivalent), issue a command, get the returned XML, and transform it. (If you need info on DeviceSpy see the Exploring Sonos via UPnP.) This approach is discussed in detail below.
  • Second Approach - Javascript in the Browser
    The second approach extracts playlists using JavaScript in a browser page. It requires you to configure your browser so that it can communicate to the Sonos devices (disable same origin policy). This approach is discussed below, but only in comparison to the first approach. See A Simple Sonos JavaScript and Java Application for details on how to use this program. (Code is on GitHub.) 
  • Third Approach - Java Program
    The third approach is a simple Java program that takes the IP address of a Sonos device and then spits out what's in its queue. You have to specifically load a playlist in a queue to download it.  (This may be useful for just capturing what's in a queue in general.) This approach requires some knowledge of how to run a basic Java program. See A Simple Sonos JavaScript and Java Application for details on how to do this. (Code is on GitHub.)
  • Fourth Approach - WPF Program
    This is a C# program running on Windows 7/8 which can extract one or many playlists. It can also import into a playlist. This approach is discussed here: WPF Application to Save and Import Sonos Playlists.


First Approach – Manual

Step 1: Open DeviceSpy and go to a zone player that is a master. If all your zones are in one group and you look at a Sonos controller (e.g. the handheld or the iPhone application) the master is the first item in the zone list*. To start with just put all the zone players in the same zone to make it easy.**

*update: Not true. The master is the zone you started the zone group with. You can
**update: Maybe easier is to just create a group of one zone and work with that then you are assured it is the master.

Step 2: In DeviceSpy, go to a zone master expand the Media Server Device, and expand the Content Directory Service.
Browse Action Dialog


Step 3: Open (double click or right Invoke Action) the Browse Action.

Invoke Action Dialog

Step 4: Fill in the parameters in the Browse Action as shown in each query below. The queries end with Query 6 which is what we really want, displaying what’s in a playlist. In each query, you fill in the fields as shown and hit Invoke and the results will be in the Result field as XML. For now you can post the XML in Notepad to get a sense of what it contains. To get the XML from the Result field to the clipboard place your cursor in the field and CTRL + A to select all.

Query 1: Get a Count of What’s in the Queue
- ObjectID = Q
- BrowseFlag = BrowseDirectChildren
- Filter = [leave blank]
- StartingIndex = 0
- RequestedCount = 1
- SortCriteria = [leave blank]
- Result = [look for the childCount attribute in the returned XML]

Query 2: Get What’s in the Queue
- ObjectID = Q:0
- BrowseFlag = BrowseDirectChildren
- Filter = [leave blank]
- StartingIndex = 0
- RequestedCount = 100 (or something high enough to get what you want; if the queue is very big consider doing this in several operations)
- SortCriteria = [leave blank]
- Result = [lots of XML returned about what’s in the queue]

Query 3: See What’s Available to Query In Terms of Searching for Music
- ObjectID = A:
- BrowseFlag = BrowseDirectChildren
- Filter = [leave blank, sure wish I knew the format for using it though…]
- StartingIndex = 0
- RequestedCount = 10
- SortCriteria = [leave blank]
- Result = [XML which shows A:ALBUMARTIST, A:ALBUM, …, A:PLAYLISTS as valid ObjectIDs]

Query 4: See What’s Available to Query System-wide
- ObjectID = 0 [zero]
- BrowseFlag = BrowseDirectChildren
- Filter = [leave blank]
- StartingIndex = 0
- RequestedCount = 10
- SortCriteria = [leave blank]
- Result = [XML which shows A:, S:, Q:, SQ:, R:, AI:, and EN: ]

A: Atribute
S: Music Shares
Q: Queues [we’ve seen an example above]
SQ: Saved Queues
R: Internet Radio
AI: Audio Inputs
EN: Entire Network

Query 5: List Saved Queues (Playlist)
- ObjectID = SQ:
- BrowseFlag = BrowseDirectChildren
- Filter = [leave blank]
- StartingIndex = 0
- RequestedCount = 100
- SortCriteria = [leave blank]
- Result = [XML which shows SQ:1 to however many playlists you have. ]

Query 6: List Songs in a Particular Saved Queue (Playlist)
- ObjectID = SQ:1 [choose a # you know exists using the previous query]
- BrowseFlag = BrowseDirectChildren
- Filter = [leave blank]
- StartingIndex = 0
- RequestedCount = 100
- SortCriteria = [leave blank]
- Result = [XML which shows contents of saved queue or playlist]

The following example below shows some XML from the Results field. The XML shows one track coming from Rhapsody and one from a local server called mediaserver.

<?xml version="1.0" encoding="utf-8"?>
<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">
 <item id="SQ:5/radea%3aTra.16238560.mp3:AFreely,Devendra%20Banhart,Smokey%20Rolls%20Down%20Thunder%20Canyon,298" parentID="SQ:5" restricted="true">
   <res protocolInfo="real.com-rhapsody-direct:*:audio/mp3:*" duration="0:04:58">radea:Tra.16238560.mp3</res>
   <upnp:albumArtURI>/getaa?r=1&amp;u=radea%3aTra.16238560.mp3</upnp:albumArtURI>
   <dc:title>Freely</dc:title>
   <upnp:class>object.item.audioItem.musicTrack</upnp:class>
   <dc:creator>Devendra Banhart</dc:creator>
   <upnp:album>Smokey Rolls Down Thunder Canyon</upnp:album>
 </item>
 <item id="S://mediaserver/music/Master/Supertramp/Even%20in%20the%20Quietest%20Moments/Supertramp%20-%2004%20-%20Downstream.flac" parentID="SQ:5" restricted="true">
   <res protocolInfo="x-file-cifs:*:audio/flac:*">x-file-cifs://mediamarx/music/Master/Supertramp/Even%20in%20the%20Quietest%20Moments/Supertramp%20-%2004%20-%20Downstream.flac</res>
   <upnp:albumArtURI>/getaa?u=x-file-cifs%3a%2f%2fmediamarx%2fmusic%2fMaster%2fSupertramp%2fEven%2520in%2520the%2520Quietest%2520Moments%2fSupertramp%2520-%252004%2520-%2520Downstream.flac&amp;v=167</upnp:albumArtURI>
   <dc:title>Downstream</dc:title>
   <upnp:class>object.item.audioItem.musicTrack</upnp:class>
   <dc:creator>Supertramp</dc:creator>
   <upnp:album>Even in the Quietest Moments...</upnp:album>
   <upnp:originalTrackNumber>4</upnp:originalTrackNumber>
 </item>
</DIDL-Lite>


Step 6: Take the XML from the last request (a particular saved queue) and put in a file called playlist.xml.

Step 7: Create a XSLT file in the same location as the XML file. Call it transform.xslt. You can create a text document and change the extension to .xslt.

Step 8: In the XSLT file put the following:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:didl="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"
    xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/"
>
    <xsl:output method="html" indent="yes"/>
      <xsl:template match="didl:DIDL-Lite">
        <xsl:for-each select="didl:item">
            <xsl:value-of select="dc:creator"/>,
            <b>
            <xsl:value-of select="upnp:album"/>,
            </b>
            "<xsl:value-of select="dc:title"/>"
            <br></br>
        </xsl:for-each>
      </xsl:template>
</xsl:stylesheet>


Step 9: Open the playlist.xml file and put the following line after the version (?xml) line so that it’s the second line in the file:

<?xml-stylesheet type="text/xsl" href="transform.xslt"?>

Step 10: Close and save both files and double-click on the playlist.xml file. It should open in a browser and show the transformed list. For example for the XML shown above the transform produces:

Output of transforming Sonos XML

The XML the query returned is DIDL which stands for Digital Item Declaration Language and is an XML dialect for MPEG-21. In the XLST file you have to be sure and use the namespace declarations carefully. The XML file has xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" so we have to use that in XSLT as well. In the XLST we define it as xmlns:didl="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" using a prefix of “didl”.

In this example we use the browser (verified in Internet Explorer 9 and Chrome) to do the transform.

Second Approach - Javascript in the Browser


The HTML page (using JavaScript and jQuery) that was given in a previous post is approach shown (or really repeated here). Note that the page (HTML and JavaScript) depends on the ability of the browser to “Allow data access across domains” (a setting). See the post for details on doing that at least for IE and Chrome.

1. Populate a drop down list with defined playlists. Uses Query 5 above.
2. Create two buttons next to playlist drop down list. Uses Query 6 above. One button shows the playlist items in the page and the other to copy the playlist to the clipboard. (Since we are stuck with Internet Explorer, we went ahead and used the clipboardData object.
3. Automatically change the zone drop down to the master zone - was a manual process in the previous version.

An example of the page output is shown below. Get the code from GitHub.



Sunday, January 9, 2011

Picasso in Seattle

Picasso Composed of His Muses
Picasso Composed of the Women in His Life
The Picasso in Seattle exhibit (October 8, 2010 – January 17, 2011) at the Seattle Art Museum (SAM) is based on works from the collection of the Musée National Picasso, Paris. That museum is under rennovation and so the works hit the road. The exhibit at SAM includes over 150 paintings, sculptures, drawings, prints, and photographs from the artist’s personal collection. From Wikipedia: “Since Picasso left no will, his death duties (estate tax) to the French state were paid in the form of his works and others from his collection. These works form the core of the immense and representative collection of the Musée Picasso in Paris.” Mon dieu, estate taxes! And, since the work is from his private collection the idea is that it represents what Picasso wanted to use to shape his legacy.

First and foremost, props to SAM for putting on a good show. We thoroughly enjoyed it. It was crowded and could have used more breathing room, but lots of people seeing the show is good for the museum. The selection of works was great, the layout of them (more or less chronologically) made sense, and the supporting material (printed and audio) was appreciated. In regard to latter, the museum did an excellent job of making it all available on the http://www.picassoinseattle.org/ web site with the actual labels on the works, a sampling of the art exhibited, the FULL audio tour, and the script to the audio tour. Wow. This is is important because much of our processing of what we see happens after the visit and having these materials available is great for the digital pack rats that we are. And, if you brought a phone capable of browsing and playing the MP3s or podcasts you could use that instead of the audioplayer they handed out (which was prefectly fine too).

Second, in regard to Picasso, I can say I have a lukewarm relationship with him (or really his legacy and image in popular culture). I like some of his works and cringe at others. Picasso speaks to me in Art like Hemingway speaks to me in Literature. Part of my uncertain thoughts about Picasso center on his relationships with women (his muses) and how his art changed with each new relationship. Reams have been written about the relationships yet the simple thought I could not get out of my mind was if I was missing something choosing a long term relationship. Was I artistically stunting myself? :-)

Friday, December 3, 2010

Lust and Vice: The 7 Deadly Sins from Dürer to Nauman


Lust and Vice: The 7 Deadly Sins from Dürer to Nauman
While we were at the Zentrum Paul Klee to see a Paul Klee exhibit we also got a chance to see another exhibit sponsored jointly with the Kunstmuseum, Bern. The exhibit was called Lust and Vice. The 7 Deadly Sins from Dürer to Nauman (15 October 2010 – 20 February 2011). Part of the exhibit was at the Zentrum and part at the Kunstmuseum. From Albrecht Dürer (1471 – 1528) to Bruce Nauman (1941 - ) artists have been preoccupied with the theme of the sin. Christianity has thought it through and given us a short list of the sins considered deadly, the Seven Deadly Sins, usually given as wrath, greed, sloth, pride, lust, envy, and gluttony. The exhibit catalogs these sins in a variety of media. Some of the exhibit works and some doesn’t. It was exhausting (or maybe we were) to go through it all. Luckily, exhaustion isn’t on the list of seven. 

Seven Deadly Sins On the Kunstmuseum in NeonSeven Deadly Sins On the Kunstmuseum in Neon

Paul Klee – Farbe, Form & Linie

Zentrum Paul Klee - In Bern, Switzerland

The exhibit Paul Klee – Farbe, Form & Linie (11.9.2010 – 16.1.2011) was an exhibit we saw at the Zentrum Paul Klee, Bern. Paul Klee (1879 – 1940) was a German-Swiss painter who produced works in the early twentieth century that crossed several styles including expressionism, cubism, and surrealism. The exhibit’s goal was to “examine the way in which the oeuvre of Paul Klee addresses the elements of picture composition and design. One of its focal points is the interplay and tension that exist between the main elements of pictorial representation, i.e. line, form and color.” It’s hard to appreciate that tension, especially on the first exposure to Klee’s work beyond what you might pick up from popular culture. Klee’s shapes and colors seem simple and innocent and it is easy to dismiss them as something you’ve seen a thousand times before. Yes, you probably have, just imitations and homages and distillations. You have to remind yourself of the time he lived and worked. Not until after the exhibit, in further research, did we appreciate Klee’s struggle to master color (fabre) theory.

The building that houses Klee’s collection (about 40% of Klee’s pictorial work) is the Zentrum Paul Klee in Bern (outside city center), Switzerland. The iconic, undulating building designed by the Italian architect Renzo Piano is a work of art itself. We got to see it under a blanket of snow and it was a welcoming relief to enter and shed our jackets and the cold. There are some great interior views of the building at the architectural-oriented site, arounder.com. Here’s the entrance of the Zentrum.

Exhibit Brochure
Paul Klee - Farbe, Form and Linie Brochure
Paul Klee - Farbe, Form and Linie Brochure

Thursday, December 2, 2010

Museum of Modern and Contemporary Art, Geneva – MAMCO


One of our “snow days” in Morges with Wild Dingo was to visit Geneva’s Museum of Modern and Contemporary Art Museum which goes by the acronym MAMCO. We remember fondly being taken to task by a Seattle gallery owner about the difference between “modern” and “contemporary”… who knew he would be so picky about semantics? The difference between modern and contemporary is that modern refers to Modernism – an art movement or practice, and contemporary refers to a time, now minus 10 to 50 years depending on who you ask, that characterizes when a piece of art was created.

So, at MAMCO, the distinction between modern and contemporary was lost on us and thankfully no one quizzed us. We walked around bewildered. We really didn’t know what to make of what we saw. We laughed, we winced, we explored, we delighted when we decoded a piece or installation, and we even relieved ourselves in an art piece. Well, let us explain. Two of the installations were bathrooms, Toilettes femmes designed by Étienne Bossut, Philippe Parreno, Stéphane Steiner and Toilettes hommes designed by Philippe Ramette, Stéphane Steiner. Well done pieces and functional.

There is work at MAMCO that we never had seen before and quite possibly may never again. For example, an exhibit on Gérald Minkoff, Un portrait and Bujar Marika, Paradox Park. So on the whole, MAMCO was an interesting and thought-provoking stop. What else could you ask of modern, uh, we mean - we think - contemporary art?

We took a train from the Morges train station to Geneva’s and then jumped on a tram to Plainpalais. From Plainpalais go west to find the 10, rue des Vieux-Grenadiers (approximate location).

MAMCO Entrance

Wild Dingo and Travelmarx Shadows

Wild Dingo and Travelmarx Superimposed – Nord 2

Robert Morris – Open Center Sculpture, 1997

INFORMATION FICTION PUBLICITÉ (link)

Our Snowy Starting Point in Morges
We ended up taking the train.

Wednesday, December 1, 2010

CERN – A Universe of Particles

CERN - Universe of Particles
The Universe of Particles is an exhibit a CERN that you can visit for free. The exhibit is housed in the Globe of Science and Innovation across the road from CERN reception (location). How ironic that the size of the globe is about that of Saint Peter’s in Rome and that CERN chooses to use that analogy, at least on their web site. One structure stands as symbol of an organization that asks questions about the universe and puts the answers through rigorous analysis. The other structure stands as quite an impressive architectural feat from an organization that took 359 years (with a 13 year investigation!) to acknowledge that Galileo was right: the earth revolves around the sun. Sorry, that still makes us wince here at Travelmarx. We hold grudges.

Back to the goodies at CERN. Also accessible from the CERN reception area is the exhibition Microcosm that helps give you the background you need to understand what goes on at CERN. It is free to visit as well. A good order would be to visit Microcosm first and then go to the Universe of Particles exhibit. Okay, back to religion. While at the Microcosm exhibit, we wandered around, mostly alone with the exhibits and then suddenly a small group appeared and gathered in a corner to hear a presentation that what is being discovered at CERN was in fact in harmony with religious belief. We listened for a few moments and then left to head over to the Universe of Particles. At the exhibit in the globe, we found our own kind of prophet, a docent who had worked at CERN for many, many years. He didn’t turn any water into wine, but was able to talk about what was going on at CERN very articulately, enough for us.

The Universe of Particles has lots of cool information on very mod looking information stations (globes) with innovative touch interaction methods. The overall experience, changing colors, periodic mini-shows and the occasional docent-prophet is worth a visit. For details on the guided tour at CERN, see this entry.

More Views of the Universe of Particles and the Ever-Changing Show
CERN - Universe of Particles
CERN - Universe of Particles
CERN - Universe of Particles
CERN - Universe of Particles

The Globe of Science and Innovation – Outside

Exploring at the Universe of Particles Exhibit


A Docent Talking Physics