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

Visiting CERN

A CERN Guide Discusses the Inside of a Collider Section
CERN guided tour
During our week in Morges we encountered snow that eventually postponed our flight from Geneva to London for two days (not so bad – more time with Wild Dingo) but also opened up other possibilities. One of those possibilities was getting on a guided tour of CERN. On the CERN web site it suggests that tours should be booked in advance and when we inquired the day before we actually go, there was no space. We didn’t think about touring CERN before we left on the trip, it only occurred to us while we were in Switzerland. A little disappointed with the availability of the tour, we decided to visit CERN anyway and at least see the Universe of Particles exhibit. But, the weather played in our favor it seems because there was space on a group tour – no shows. Hah, we were in luck.

CERN stands for Conseil European pour le Recherche Nucléaire, or in English, the European Organization for Nuclear Research and it is headquartered just outside of Geneva straddling the Swiss and French borders. At CERN, particles are smashed together in high-energy physics experiments to understand questions like how the universe began. The building blocks of matter and the forces that hold them together are studied with particle accelerators. In accelerators, particles reach speeds near that of light and are smashed together or against a target to see what results. The main accelerator these days is the Large Hadron Collider (LHC) which is housed in a tunnel 27 kilometers (16.8 miles) in circumference and 50-100 meters (164 - 328 feet) underground. The tunnel runs under Switzerland and France.

So we lucked out and caught an English tour that is usually booked out months in advance. On the tour a guide takes us step by step through step through the construction of an accelerator section such as the section that would make up the Large Hadron Collider (LHC). We don’t actually visit the LHC which is operating, but a facility that tested the sections. The tour is great – geek heaven. It lasts from 10:00 to 12:00 and then we spend a few hours at the Universe of Particles. For details of that visit, see this entry.

CERN General Brochure
CERN brochure
CERN brochureCERN brochureCERN brochure

Large Hadron Collider Brochure
LHC brochure
LHC brochureLHC brochureLHC brochure

CERN – Testing Facility
CERN tour

CERN tour

Saturday, November 27, 2010

Mount Blanc Tunnel

Last Chance Pasta
Mont Blanc Tunnel - Pasta
After our two nights in Pontboset, it was time to head out of Italy to Switzerland, specifically, Morges (outside of Geneva). Morges is the European operations of Wild Dingo and it was time to pay tug. When we looked at routes from Pontboset to Morges, the quickest route is through the Great St. Bernard Tunnel, but people advised that us to not go through that route for snow reasons and to take the Mont Blanc Tunnel. The St. Bernard Tunnel is about 1500-1600 feet higher in altitude. So we opted for Mont Blanc since we weren’t pressed for time. The difference between the two routes was 15 minutes and about 25 miles so not a hard decision.

Both tunnels are named for nearby geographical features, the St. Bernard Tunnel for the Great St. Bernard Pass (at 8100 feet) and Mont Blanc Tunnel for Mont Blanc (at 15,782 feet). One of my favorite memories was a large postcard I received from my grandparents from the St. Bernard Pass featuring a St Bernard dog in laying a meadow of alpine flowers. I can remember that card like it was yesterday. The pass is named for Saint Bernard of Menthon who founded a hospice for travellers and used dogs for rescue that came to be known as St. Bernard.

Before entering the Mont Blanc Tunnel we stopped and parked and went into the rest area where we were confronted with a large display of pasta. Last stop for pasta before you go to France where pasta just ain’t pasta! We passed up the deal. We didn’t think Wild Dingo would need that much pasta. Besides, we were carrying a booty of fruit we got from Cascina Bringin (details).

Drilling for the Mont Blanc Tunnel was started in 1946 and opened to traffic in 1965. The tunnel is a single gallery with a single lane going in each direction. The Italian side of the tunnel is in Courmayeur, Aosta Valley and the French side of the tunnel is in Chamonix, Haute-Savoie. As you enter the tunnel you are given a card that can be attached to the rearview mirror and explains what you need to know to drive in the tunnel including distances between you and the vehicle in front of you (150 meters or 492 feet), speed limit, and what to do in case of fire. After the terrible 1999 fire incident in the tunnel it makes sense for drivers to pay attention to the warnings and understand what to do. But honestly, the “red” side of the informational card takes some time to decipher. Is it to be read as a continuous sequence of events or separate triggers for actions? Probably the latter. If smoke is coming out of a car, stop. If you turn off your car, put on the car’s hazard lights. If you see smoke coming out of a vehicle, stop at least 100 meters (328 feet) from it and flee. Flee to the nearest emergency chamber. Look at the card and decide for yourself. Also check out this article on improvements made to the tunnel.

Thankfully, we passed through the 11,611 meter (7,215 mile) tunnel with no incident. We exited into a snowy Chamonix and made our way to Morges, but not before a surreal lunch in Annemasse France where all our French escaped us and we could only mutter in Italian.

Approaching Mont Blanc Tunnel on the Italian Side
Approaching Mont Blanc Tunnel - Italian Side
Mont Blanc Tunnel Entrance – Italian Side - 12:05pm
Mont Blanc Italian Side

View Back over Courmayeur, Italy
Courmayeur View from Mont Blanc Reststop
Inside the Mont Blanc Tunnel – Heading Toward France
Inside Mont Blanc Tunnel
Exiting in Chamonix, France
Chamonix France, Exiting Mont Blanc Tunnel
Mont Blanc Tunnel Information Card
Mont Blanc Information CardMont Blanc Information Card