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
andpassword
(both strings). Like theAS USER
command-line counterpart, requests includingasUser
will close the connection when they complete (or fail). inRoom
- accepts a dictionary containing
room
(string). withSource
- Accepts a dictionary named
source
containing eitherid
(numeric) or bothtype
andname
(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:
- Replies (i.e., Successes/failures)
- Data
- Notifications
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
}
}