SMAPI sample server

The SMAPI sample server is a Java server that uses SMAPI to create a simple music service. It provides a simple Sonos apps controller interface and serves to Sonos players a static directory of music files. It demonstrates the following features:

  • Browse responses using the getMetadata method.
  • Search responses using a search endpoint.
  • Music playback using a music service endpoint and the getMediaURI method to serve static content.
  • Info view using getExtendedMetadata and getExtendedMetadataText methods, which display additional information about a track.
  • DeviceLink Authentication Mode using getDeviceLinkCode and getDeviceAuthToken methods.

Download, set up, build & test

Download and extract the source code package and see the included README.md for installation instructions. Note that you need Java SE Development Kit 8. The sample server may not work with other versions of Java. Below we’ll briefly go over how the features were implemented.

Download Sonos Content API sample server

Try it out

The sample server demonstrates the core features of SMAPI. To see it in action, add the sample server to one of your Sonos players by following the instructions in Test your service. Once you add it, you can choose the sample server as a music service source.

In the Sonos app, select Services > Add a Service to add the sample server as a music source. You’ll then see the DeviceLink authorization page. Follow the prompts and enter the username “acmeUser” and password “password” to authenticate.

Note: The sample server uses an older version of authentication. See Add authentication to learn how to add authentication for your service.

You should now see the sample server in your list of music sources. Open it up to browse for and play content. Try the search field to search the sample server for an artist, album, or track. You can also learn more details or perform actions on a track, such as view the album or artist information, add the track to Sonos favorites, or add it to a Sonos playlist.

Architecture

The SMAPI sample server uses Spring Boot as a Java framework and is a sample of how to implement a basic SMAPI server. It doesn’t use a content delivery network (CDN) for content, but instead serves a directory of static files. It does not include a database for metatdata nor does it persist settings across instances. If you stop the server and restart, you will need to reauthorize the user again.

For this example, we use the MusicServiceConfig class to configure the service.

The following classes implement required browse and search SMAPI methods:

  • MusicServiceEndpoint
  • MusicServiceGetMetadataEndpoint
  • MusicServiceGetExtendedMetadataEndpoint
  • MusicServiceGetExtendedMetadataTextEndpoint
  • MusicServiceSearchEndpoint

These were broken up into several classes to keep each file small. If you prefer, they could be combined into a single class.

The class DeviceLinkAuthenticationModeEndpoint implements the SMAPI DeviceLink Authentication Mode methods. This works in conjunction with DeviceLinkPageController, which serves the login page.

We did not implement the optional playlist editing and status reporting methods, but added placeholders in their respective classes.

Note: See Add playlists and Add reporting for details. Note that we updated the reporting API after we created this sample.

The MusicServiceAnnotationMethodEndpointMapping class routes requests to endpoints, so that the @PayloadRoot parameters and the @BindObjectId annotation suffice to set up a new request handler.

The sections below describe how the server uses these interfaces to offer the common features. Please see the actual source code for details.

Browsing content

As you browse the sample service, the Sonos app displays content for albums, artists, or tracks. Each time you select an item, the Sonos app sends a getMetadata request for the item’s ID. The server responds with the metadata the item represents. The returned metadata is either a container of other items, like a list of albums, or an individual item such as a track.

The starting ID for any audio service’s hierarchy must be root. Therefore, every service must respond to the getMetadata request for the root id. The contents of this response determines what other IDs are available to browse. The names of all other IDs for your service are up to you. For example, the sample server implements the IDs browse:albums, browse:artists, and browse:tracks. But your service can use anything you want, even foo, bar, and baz, for example. You determine what containers can be browsed and what is in those containers. Ideally, the container hierarchy should match what you already provide listeners when they browse your own application.

The sample server uses the MusicServiceGetMetadataEndpoint to respond to requests. For example, here’s how it generates a response for the artists container:

Handling search requests

Users can search all music services for content. The sample server handles search requests in the MusicServiceSearchEndpoint. When your service provides search, it must respond to the getMetadata request for the search id. Your service’s response must be a collection of the available search category IDs. The Sonos app then uses these to form its search requests. For example, here’s how the sample server handles an album search:

See search and Add search for details.

Playing music

Sonos players get the URIs for your specific content using getMediaUri requests. The sample server handles these requests in the MusicServiceEndpoint:

Since the sample server only serves static files, we’ve implemented a simple StaticContent class. When you develop your implementation, you should be able to update from serving static files to Sonos to serving content from your content delivery network.

Implementing info view

Listeners can view more information about content by doing the following:

  • On the Sonos app for Mac or PC: select a track and choose Info & Options.
  • On the Sonos app for mobile devices, click the three dots next to the track and tap More.

SMAPI supports this view with the getExtendedMetadata and getExtendedMetadataText requests. The sample server generates responses to these requests in the MusicServiceGetExtendedMetadataEndpoint and the MusicServiceGetExtendedMetadataTextEndpoint. For example, here’s how it generates a getExtendedMetadata response for an album:

Note: We updated the info view features after we created this sample. To find out more, see Add actions.

Implementing authentication

Sonos apps use OAuth 2.0 for browser-based authentication of your service. See Add authentication for details.

The sample server demonstrates this by implementing an older version of authentication using getDeviceLinkCode and getDeviceAuthToken in the DeviceLinkAuthenticationModeEndpoint. This code is still useful to understand the basic concept, but we recommend that you use the new APIs described in the link above.

Add reporting

We haven’t implemented status reporting in the sample server. See Add reporting for details.

The StatusReportingEndpoint is a placeholder. But note that we created this before we released the new APIs described above, so it may no longer be useful.