Implementing song or album favorites

Listeners can store favorite songs and albums on their Sonos system, your music service, or both. For example, a listener would choose Add Song to My Library to add it as a music service favorite, or Add song to Sonos Favorites to add it as a Sonos favorite:

Listeners can save any playable itemType to their Sonos favorites. Sonos players store Sonos favorites. Listeners can access them from the Sonos Favorites menu on the Sonos app. You do not need to do anything special to enable Sonos favorites. However, you can prevent an item from being added as a favorite by setting isEphemeral to true in the getMetadata response (see the link for details).

You can also enable listeners to save favorite tracks and albums on your music service. This may be useful if you have your own app for listeners of your service. You can enable music service favorites to keep listener favorites in sync on Sonos and your music app. The rest of this document describes how to implement music service favorites.

Listeners use the Info View to add or remove favorite items. See the Customized Info View documentation for details.

Enable music service favorites

To enable listeners to add music service favorites:

You can also customize the way the Sonos app displays service favorites to listeners. For example, you can change the text that listeners select. You can also set up a hierarchy to store different kinds of favorites.

TURN ON THE ALBUM OR TRACK FAVORITES CAPABILITIES

In order for listeners to select favorites in your service, you must enable the appropriate capabilities. You can choose to implement track, album, or both types of favorites. Choose the following capabilities:

  • "Favorites: Adding/Removing Tracks"
  • "Favorites: Adding/Removing Albums"
  • "Extended Metadata (for MOAPI-based InfoView)"

When testing your service, use the customSD.htm page on a player to choose capabilities, as described in Add your service with customSD. When submitting your service to Sonos, use the Version Manager to choose capabilities, as described in B: Technical configuration & test setup.

Specify if a container contains favorites in your getmetadata response

If you will be presenting a user's music service favorites to them, you must configure it at the root level with a SMAPI <itemType> of container. Include the <containsFavorite> element set to true to indicate to the Sonos app this holds favorites. For example, given the following request:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getMetadata xmlns="http://www.sonos.com/Services/1.1">
      <id>root</id>
      <index>0</index>
      <count>100</count>
    </getMetadata>
  </soap:Body>
</soap:Envelope>

Your service might return the favorites container, among others, as shown below:

<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getMetadataResponse
        xmlns="http://www.sonos.com/Services/1.1">
      <getMetadataResult>
        <index>0</index>
        <count>3</count>
        <total>3</total>
        <mediaCollection>
          <itemType>container</itemType>
          <id>favorites</id>
          <title>My Favorites</title>
          <containsFavorite>true</containsFavorite>
          ...
        </mediaCollection>
        ...

Add additional child containers under this favorites container to provide a hierarchical organization to a user's favorites. See below for details.

IMPLEMENT FAVORITES IN GETEXTENDEDMETADATA, CREATEITEM, DELETEITEM, AND GETLASTUPDATE

When the listener selects the Info View for an album or track, the Sonos app sends a getExtendedMetadata request to your service. Your response will determine the options to display for the user. This can include the option to add or remove a music service favorite.

When the listener chooses to add a favorite, Sonos sends a createItem request to your service. When they choose to remove a favorite, Sonos sends a deleteItem request. To keep the Sonos app aware of changes made to listener favorites, Sonos sends getLastUpdate requests immediately following successful createItem and deleteItem responses, as well as at your specified polling interval.

Workflow: ADDING or removing a TRACK OR ALBUM FAVORITE

The following describes the flow when adding or removing a track or album to a listener’s favorites:

  1. When the listener chooses the Info View for a track or album, the Sonos app calls getExtendedMetadata with the track or album ID.
  2. The Sonos app uses your response to getExtendedMetadata to display the Info View, including:​
    • "Save to Your Music" if the isFavorite parameter is false.
    • "Remove from Your Music" if the isFavorite parameter is true.
      You can customize this string in your strings.xml file. See below for details.​
  3. When the listener selects:
    • "Save to Your Music", the Sonos app calls createItem with the track or album ID.
    • "Remove from Your Music", the Sonos app calls deleteItem with the track or album ID.
  4. Depending on the selection, modify your list of favorites for the user:
    • If the listener added the item to favorites, in your createItem implementation, add this item to a list of favorites your service maintains for this listener.
    • If the listener removed the item from their favorites, in your deleteItem implementation, remove this item from any list of favorites your service maintains for this listener.
  5. After the Sonos app receives a response to createItem or deleteItem, it immediately calls getLastUpdate to see if a change has occurred so it can pull the latest changes with a call to getMetadata. Other active Sonos apps in the household may not reflect these changes until they call getLastUpdate. See the note below for details.

Stay in sync! Update favorites before sending getlastupdate response

Be sure to update all music service favorites on your service and update the favorites value for your getLastUpdate response before you respond to the getLastUpdate request. When the Sonos app sees that the favorites value has changed, it will send a new getMetadata request to get the new container content.

Similarly, if a listener updates their favorites using your proprietary music app, update the favorites value for your getLastUpdate response so that when Sonos apps send getLastUpdate requests at the polling interval, they will know to send getMetadata requests to display these changes to the listener.

Strings and error handling

You can change the text for the "Add Song to My Library" and "Delete Song from My Library" Info View options by setting stringId values in your strings.xml file. First, specify the add track, remove track, add album, and remove album from favorites menu items in your presentation map. Include string IDs for the string, as well as for the failure, in progress, and success states. For the remove favorite action, include a prompt string ID if you want to prompt the user to give them an option to reconsider. For example, "Are you sure you want to remove this track from Your Music?"

Here's an example of a presentation map that offers menu items for adding and removing track and album favorites:

<MenuItemOverrides>
  <MenuItem FailureStringId="SAVE_TRACK_FAILURE" InProgressStringId="SAVE_TRACK_DURING" MenuItem="AddTrackToFavorites" StringId="SAVE_TRACK" SuccessStringId="SAVE_TRACK_SUCCESS"/>
  <MenuItem FailureStringId="DELETE_TRACK_FAILURE" InProgressStringId="DELETE_TRACK_DURING" MenuItem="RemoveTrackFromFavorites" PromptStringId="DELETE_TRACK_PROMPT" StringId="DELETE_TRACK" SuccessStringId="DELETE_TRACK_SUCCESS"/>
  <MenuItem FailureStringId="SAVE_ALBUM_FAILURE" InProgressStringId="SAVE_ALBUM_DURING" MenuItem="AddAlbumToFavorites" StringId="SAVE_ALBUM" SuccessStringId="SAVE_ALBUM_SUCCESS"/>
  <MenuItem FailureStringId="DELETE_ALBUM_FAILURE" InProgressStringId="DELETE_ALBUM_DURING" MenuItem="RemoveAlbumFromFavorites" PromptStringId="DELETE_ALBUM_PROMPT" StringId="DELETE_ALBUM" SuccessStringId="DELETE_ALBUM_SUCCESS"/>
</MenuItemOverrides>

Here's an example of some strings:

<String id="SAVE_ALBUM">Add Song to My Library</String>
<String id="DELETE_ALBUM">Delete Song from My Library</String>
<String id="SAVE_TRACK">Add Album to My Library</String>
<String id="DELETE_TRACK">Delete Album from My Library</String>

See Customized Info View for details.

Hierarchical Nodes beneath Favorites

While you could place albums and songs in the same mediaCollection under a root node called “Favorites,” you might not want to mix all user favorites together. For example, you may want to separate favorite songs from favorite albums. To do this, you should create some sort of organization beneath the root-level favorites node. You might have a hierarchy somewhat similar to this:

My Library/ (itemType.favorites)
 Albums/ (itemType.albumList)
 Songs/ (itemType.trackList or itemType.Playlist)

If you implement the hierarchy above, when the Sonos app sends a createItem or deleteItem request with an album ID, it should act on the My Library >> Albums list. When the Sonos app sends a similar request with a track ID, it should act on the My Library >> Songs list. You would still update all favorites before responding to the getLastUpdate request as described earlier as all child nodes are governed by the parent node marked as itemType.favorites.