Devious Fish
pianod2 music server
profile for Perette at Stack Overflow, Q&A for professional and enthusiast programmers

pianod2 JSON Support

JSON Requests

JSON request names and keys are case sensitive.

Message quoting should be done in accordance with the JSON specification.

When sent to pianod, the request must be sent on a single line; returns are treated as end-of-message. Requests split over multiple lines will fail with parse errors. Only one request can be sent per line.

Any instruction can be sent as either a command line or as a JSON request. The SCHEMA command (or its equivalent request, getSchema) generates a list of all requests, or details for a particular request. See the commands section of this documentation for a more information on commands.

For example:

SCHEMA getSchema
203 Data
132 Information: All requests take the form:
132 Information:   {"requestname": {request parameters/options...}}
132 Information: getSchema: Dictionary containing:
132 Information:              'request' (optional)
132 Information:                List (0 or more members) of String (no control characters allowed)
204 No data or end of data

If we wanted to use JSON to request the schema for authenticating:

{ "getSchema": {"request": ["authenticate"] } }
203 Data
132 Information: authenticate: Dictionary containing:
132 Information:                 'username' (mandatory)
132 Information:                   Requires also: password
132 Information:                   String (no control characters allowed)
132 Information:                 'password' (mandatory)
132 Information:                   Requires also: username
132 Information:                   String (no control characters allowed)
204 No data or end of data

There are 3 special keys that can be used in the main dictionary of the request:

asUser
Accepts a dictionary containing username and password (both strings). Like the AS USER command-line counterpart, requests including asUser will close the connection when they complete (or fail).
inRoom
accepts a dictionary containing room (string).
withSource
Accepts a dictionary named source containing either id (numeric) or both type and name (both strings).

JSON Responses

JSON response mode is selected at connection time. Initiate Websocket connections with the query parameter protocol=json, or connect on pianod’s HTTP or HTTPS port and greet with HELO pianod json\n for JSON over plain TCP.

All messages sent by the server are dictionaries, which take 3 forms:

Messages are sent as a single, newline-terminated line, or a single Websocket message.

In response to a command or request, you will receive either a reply or data. These both have the fields code, which matches up with the success/command error codes for the line protocol.

Data

If code is 203, the message contains the reply data in a member called data. data is always a list of dictionaries:

USER LIST PERETTE
{
  "code":203,
  "data":[
    {
      "id":"perette",
      "privileges":{
        "rank":"admin",
        "deejay":false,
        "present":true,
        "service":false,
        "influence":true,
        "tuner":false,
        "shadow":false
      }
    }
  ],
  "status":"Data"
}

Note: Response message has been formatted for legibility. The server will return it as a single line of JSON, without newlines or identing. A command-line utility json_format, included in src/parsnip, will beautify JSON provided to it. Use it as a filter, or specify filenames on the command line.

Replies

Other 2xx values for code (200–202, 205–299) indicate a success, and 400–499 indicate a command error. For these, there will be both successes and failures arrays. One or both of these will be non-empty; it is possible to receive multiple successes, failures, or a mix of both.

GRANT SERVICE TO Frank Edward
{
  "code":404,
  "successes":[],
  "status":"Requested item not found",
  "failures":[
    {
      "code":404,
      "status":"Requested item not found",
      "details":null,
      "id":"Frank",
      "name":"Frank"
    }, {
      "code":404,
      "status":"Requested item not found",
      "details":null,
      "id":"Edward",
      "name":"Edward"
    }
  ]
}

Notifications

If there is no code present, the message is a notification. Notifications can also be included with replies.

There are 4 categories of notifications: events, state, currentSong, and errors. Here is a state notification:

{
  "state":{
    "volume":3
  }
}

And another, this one featuring current playback information:

{
  "state":{
    "playbackState":"Paused"
  },
  "currentSong":{
    "duration":309,
    "timeIndex":4,
    "timeRemaining":304
  }
}

An event notification:

{
  "events":[
    {
      "code":4,
      "status":"Track playback complete",
      "details":null
    }
  ]
}

A current song notification:

{
  "currentSong":{
    "playlistName":"jazz",
    "songInfoUrl":null,
    "duration":456,
    "name":"Ritual",
    "playlistId":"2pp1080572466",
    "source":{
      "id":2,
      "type":"filesystem",
      "name":"perette"
    },
    "id":"2ss971186724-9",
    "artistId":"2sa1792080946",
    "artistName":"Chick Corea Elektric Band II",
    "compilation":false,
    "genre":"Jazz",
    "trackId":"2ss971186724-9",
    "albumArtUrl":null,
    "albumId":"2sl971186724",
    "trackName":"Ritual",
    "year":1993
  }
}

Notifications can carry several categories. In the following message, currentSong is null to indicate there is no current song because it was stopping.

{
  "events":[
    {
      "code":4,
      "status":"Track playback complete",
      "details":null
    }
  ],
  "state":{
    "playbackState":"idle"
  },
  "currentSong":null
}

Were instead play was continuing to a new track, the track playback complete event would be accompanied by the new track information:

{
  "events":[
    {
      "code":4,
      "status":"Track playback complete",
      "details":null
    }
  ],
  "currentSong":{
    "playlistName":"Short Stop",
    "songInfoUrl":null,
    "duration":313,
    "name":"One Of Our Submarines",
    "playlistId":"2pp1407280692",
    "source":{
      "id":2,
      "type":"filesystem",
      "name":"perette"
    },
    "id":"2ss1104797890-9",
    "artistId":"2sa988499006",
    "artistName":"Thomas Dolby",
    "compilation":false,
    "genre":"Rock",
    "trackId":"2ss1104797890-9",
    "albumArtUrl":null,
    "albumId":"2sl1104797890",
    "trackName":"One Of Our Submarines",
    "year":null
  }
}