Intro

Festival daemon.

festivald is a music server that plays on the device it is running on, and is remotely controlled by clients.

It can also serve music resources such as song files, album art, and organized archives of whole artists.

The 3 main APIs festivald exposes:

  • JSON-RPC 2.0 for state retrieval & control
  • REST endpoints for serving large resources (audio, art, etc)
  • Docs - festivald serves the very docs you are reading right now

The transport used is HTTP(s).

A public instance of festivald with Creative Commons licensed music is available at:

https://daemon.festival.pm

For a general quick start, see the next chapter: Quick Start.

Clients

To interact with festivald, you need a client.

The reference JSON-RPC client is festival-cli.

General purpose HTTP clients like curl, wget or a web browser will also do.

The documentation will use festival-cli & curl on the default http://localhost:18425 for examples.

JSON-RPC

For the JSON-RPC API, anything that can transmit JSON over HTTP(s) can be a client, like curl:

# Toggle playback.
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"toggle"}'

The equivalent wget command:

wget -qO- http://localhost:18425 --post-data '{"jsonrpc":"2.0","id":0,"method":"toggle"}'

The equivalent festival-cli command:

festival-cli toggle

For a quick start on the JSON-RPC API, see JSON-RPC/Quick Start.

REST

For the REST API, you can use anything that can handle HTTP(s), like a web browser:

# Download this exact song.
http://localhost:18425/map/Artist Name/Artist Title/Song Title

The equivalent curl command:

curl -JO http://localhost:18425/map/Artist%20Name/Artist%20Title/Song%20Title

The equivalent wget command:

wget --content-disposition "http://localhost:18425/map/Artist Name/Artist Title/Song Title"

For a quick start on the REST API, see REST/Quick Start.

To disable the REST API, set the config option rest to false OR pass --disable-rest via command line on start up.

Documentation

festivald will also serve this documentation.

To access it, start festivald and open the root link in a web browser:

http://localhost:18425

Or you can open the files locally with:

festivald --docs

To disable serving documentation, set the config option docs to false OR pass --disable-docs via command line on start up.

Quick Start

A quick start to using festivald and its JSON-RPC & REST APIs.

More JSON-RPC specific examples here, and more REST specific examples here.

Important things to know:

  1. The main music library/database in festivald is called the Collection
  2. The Collection is created by scanning the filesystem festivald is running on
  3. Everything revolves around the Collection, you should create one before doing anything
  4. In festivald, there are "objects" that appear often, see Common Objects for more info

Launch festivald

Start festivald with no options:

./festivald

festivald will use a default configuration and open up on http://localhost:18425.

To view this documentation locally after starting festivald, you can open it in a web browser:

http://localhost:18425

Or you can open the files locally with:

./festivald --docs

Create a Collection with the JSON-RPC method collection_new

This scans the default Music directory on festivald's filesystem and creates a Collection from it.

festival-cli collection_new

OR

curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_new","params":{"paths":null}}'

Download a random Artist with the REST endpoint /rand/artist

Opening this link in a web browser will cause festivald to collect, organize, and archive all the Album's of a random Artist, and send it over.

http://localhost:18425/rand/artist

View metadata about a specific Album with the JSON-RPC method map_album

This will retrieve the Album "Cigarette & Alcohol" by the Artist "LUCKY TAPES".

festival-cli map_album --artist "LUCKY TAPES" --album "Cigarette & Alcohol"

OR

curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_album","params":{"artist":"LUCKY TAPES","album":"Cigarette & Alcohol"}}'

The response looks like:

{
  "jsonrpc": "2.0",
  "result": {
    "title": "Cigarette & Alcohol",
    "key": 752,
    "artist": 169,
    "release": "2016-07-06",
    "runtime": 2593,
    "song_count": 10,
    "songs": [
      7611,
      7616,
      7618,
      7619,
      7620,
      7621,
      7622,
      7623,
      7624,
      7626
    ],
    "discs": 0,
    "art": 1947006,
    "genre": null
  },
  "id": 0
}

Search for an Artist with the JSON-RPC method search_artist

This will look up all Artist's in the Collection, and return the one that is the most similar (lexicographically) to the input "lUcKee TaPeZ":

festival-cli search_artist --input "lUcKee TaPeZ" --kind top1

OR

curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search_artist","params":{"input":"lUcKee TaPeZ","kind":"top1"}}'

We found "LUCKY TAPES":

{
  "jsonrpc": "2.0",
  "result": {
    "artists": [
      {
        "name": "LUCKY TAPES",
        "key": 169,
        "runtime": 2593,
        "albums": [
          752
        ],
        "songs": [
          7611,
          7616,
          7618,
          7619,
          7620,
          7621,
          7622,
          7623,
          7624,
          7626
        ]
      }
    ]
  },
  "id": 0
}

Audio

Miscellaneous parts of festivald related to audio.

Audio Output Device

festivald automatically connects to the "default" audio output device on the machine it is running on.

If a connection failure occurs during playback, it will continue to play, frequently attempting to reconnect.

If started without any audio output devices available, it will attempt to reconnect every 5 seconds, forever.

Thus, reconnecting hardware/interfaces mid-playback should be fine.

This behavior is πŸ”΄ Unstable and may change in the future.

Ideally, an enumeration and customizable selection of all audio devices would be available.

Audio State

By default, festivald will save audio state upon clean shutdown (or CTRL+C/SIGINT), and recover audio state upon startup.

This means audio will start playing exactly where it left off, and the queue will be intact.

This can be disabled with the recover_audio_state config option or the --disable-restore-audio-state command-line flag.

Media Controls

By default, festivald will hook into the OS's native media controls to display some metadata and allow for playback via the OS's interface or via keyboard play/pause/stop/etc signals.

This can be disabled with the media_controls config option or the --disable-media-controls command-line flag.

Config

festivald reads and loads its configuration file festivald.toml on startup.

It controls various behaviors of festivald.

Exactly where this file is depends on the OS, more details in the Disk section.

Command Line flags will override any overlapping config values.

festivald.toml

This is the default configuration file festivald creates and uses.

If festivald is started with no --flags, e.g:

./festivald

Then it will be equivalent to this config file.

#================#
# festivald.toml #
#================================================================#
# This is `festivald`'s config file.                             #
# It is in the TOML (https://en.wikipedia.org/wiki/TOML) format. #
#                                                                #
# Values will be loaded from this file on startup.               #
# If overlapping `--command-flags` are provided,                 #
# they will be used instead.                                     #
#                                                                #
# For full documentation on config options, see:                 #
# <https://docs.festival.pm/daemon/config.html>                  #
#================================================================#


#----------------------------------------------------------#
#                         NETWORK                          #
#----------------------------------------------------------#
# The IPv4 address `festivald` will bind to.
#
# DEFAULT | "127.0.0.1"
# EXAMPLE | "192.168.2.10", "0.0.0.0"
# TYPE    | IPv4 string
ip = "127.0.0.1"

# The port `festivald` bind to.
#
# Using port 0 will select a random port.
#
# DEFAULT | 18425
# EXAMPLE | 15000, 8080, 9999
# TYPE    | 16-bit unsigned integer (0..65535)
port = 18425

# The max amount of connections `festivald`
# will serve at any given moment.
# `0` means unlimited.
#
# Note that 1 client doesn't necessarily mean
# 1 connection. A single web browser client for
# example can make many multiple connections
# to `festivald`.
#
# DEFAULT | 0
# EXAMPLE | 2, 4, 8, 16, 32, 64, 1000, 99999
# TYPE    | unsigned integer
max_connections = 0

# `festivald` will only serve connections coming
# from these IPs. An empty array `[]` or an array
# containing "0.0.0.0" will serve all IP ranges.
#
# DEFAULT | []
# EXAMPLE | ["127.0.0.1", "192.168.2.10", "13.248.169.48"]
# TYPE    | array of IPv4 addresses
exclusive_ips = []

# Upon a failed, potentially malicious request, instead of
# immediately responding, `festivald` will randomly sleep
# up to this many milliseconds before responding to the connection.
#
# This includes:
#   - Authentication failure
#   - IPs not in the `exclusive_ips` list
#   - IPv6 connections
#
# If 0, `festivald` will immediately respond. This may
# not be wanted due to potential DoS and timing attacks.
#
# If you're hosting locally (127.0.0.1), you can set this
# to 0 (unless you don't trust your local network?).
#
# DEFAULT | 3000
# EXAMPLE | 0, 1000, 3000, 10000, 300000
# TYPE    | unsigned integer
sleep_on_fail = 3000


#----------------------------------------------------------#
#                       COLLECTION                         #
#----------------------------------------------------------#
# Upon a `collection_new` JSON-RPC method call, if the
# `paths` parameter is empty, these PATHs will be scanned
# instead.
#
# If this is also empty, the default OS `Music`
# directory will be scanned.
#
# Windows-style PATHs will only work if `festivald`
# is running on Windows (`C:\\Users\\User\\Music`)
#
# DEFAULT | []
# EXAMPLE | ["/home/user/Music/albums", "/home/user/data/songs"]
# TYPE    | array of PATHs
collection_paths = []


#----------------------------------------------------------#
#                           TLS                            #
#----------------------------------------------------------#
# Enable/disable HTTPS.
#
# You must also provide a PEM-formatted X509 certificate and key
# in the below options for this to work.
#
# DEFAULT | false
# VALUES  | true, false
# TYPE    | boolean
tls = false

# The PEM-formatted X509 certificate used for TLS.
#
# DEFAULT | ""
# EXAMPLE | "/my/path/to/cert.pem"
# TYPE    | PATH string
certificate = ""

# The PEM-formatted key for the above X509 certificate.
#
# DEFAULT | ""
# EXAMPLE | "/my/path/to/key.pem"
# TYPE    | PATH string
key = ""


#----------------------------------------------------------#
#                           API                            #
#----------------------------------------------------------#
# Enable/disable the REST API.
# This is responsible for the `/rest` API that
# serves image, audio, and other heavy resource data.
#
# Setting this to `false` will disable this part
# of the system, and will only leave the JSON-RPC
# API available.
#
# DEFAULT | true
# VALUES  | true, false
# TYPE    | boolean
rest = true

# Enable/disable serving documentation.
#
# By default, `festivald` serves a markdown book
# of it's own documentation, accessible at the
# root `/` endpoint, e.g:
# ```
# http://localhost:18425/
# ```
#
# Setting this to `false` will disable that.
#
# DEFAULT | true
# VALUES  | true, false
# TYPE    | boolean
docs = true

# Enable/disable inlined resources for the REST API.
#
# By default, accessing the REST API via a
# browser will open the resource inlined within
# the browser, if possible.
#
# Setting this to true will make browsers download
# the file directly, instead of opening it.
#
# Currently this only supports art, although in
# the future it will most likely support song files
# opening up as inline mini-players in the browser.
#
# DEFAULT | false
# VALUES  | true, false
# TYPE    | boolean
direct_download = false

# When files are downloaded via the REST API, and the
# file is a nested object referencing multiple things
# (e.g, an _album_ owned by an _artist_), we must include
# that information, but what string should separate them?
#
# The default separator is " - ", e.g:
# ```
# Artist Name - Album Title.zip
# ```
# it can be changed to any string, like "/":
# ```
# Artist Name/Album Title.zip
# ```
# or left empty "" for no separator at all.
#
# This cannot include a slash: `/`
# as that is the legal PATH separator in ZIP files.
#
# DEFAULT | " - "
# EXAMPLE | " --- ", "_", ""
# TYPE    | string
filename_separator = " - "


#----------------------------------------------------------#
#                         LOGGING                          #
#----------------------------------------------------------#
# The logging level `festivald` will use.
#
# "error" will only show critical error messages,
# "warn" will in addition show warnings,
# "info" will in addition show info, etc, etc.
#
# DEFAULT | "error"
# VALUES  | "off", "error", "warn", "info", "debug", "trace"
# TYPE    | string, one of the above
log_level = "error"


#----------------------------------------------------------#
#                       FILESYSTEM                         #
#----------------------------------------------------------#
# Enable/disable watching the filesystem for signals
#
# Other than RPC calls, `festivald` can send signals
# to another local `festivald`, e.g:
# `./festivald --play`
#
# The way this is done is by creating a file
# in Festival's `signal` directory.
#
# `./festivald --FLAG` just creates a file in that directory,
# which an existing Festival will notice and do the appropriate task.
#
# Setting this to `false` will disable that part of the system so that
# filesystem signals won't work, e.g, `./festivald --play` will not work.
#
# DEFAULT | true
# VALUES  | true, false
# TYPE    | boolean
watch = true

# Enable/disable cleaning up cache
#
# When serving `ZIP` files via the REST API, `festivald`
# will first write them to disk, then serve those files
# instead of directly storing everything in memory,
# as to not get OOM-killed on more than a few requests.
#
# Setting this to `false` will make `festivald`
# never clean those files up, ever.
#
# This will make `cache_time` not do anything and will
# also prevent `festivald` from the usual startup/shutdown
# cache cleaning that it does.
#
# DEFAULT | true
# VALUES  | true, false
# TYPE    | boolean
cache_clean = true

# Set the REST API cache time limit
#
# This option sets the time limit on how many seconds
# `festivald` will hold onto this cache for.
#
# Once the time limit is up, `festivald` will remove the
# file. This cache is also reset on startup and shutdown.
#
# This does nothing if `cache_clean` is `false`.
#
# DEFAULT | 3600 (1 hour)
# EXAMPLE | 60 (1 minute), 600 (10 minutes), 1800 (30 minutes), 14400 (4 hours)
# TYPE    | unsigned integer
cache_time = 3600


#----------------------------------------------------------#
#                           AUDIO                          #
#----------------------------------------------------------#
# Enable/disable audio state restoration
#
# Upon startup, `festivald` will recover audio state
# (volume, exact position in song, queue, etc) if this
# setting is `true`.
#
# DEFAULT | true
# VALUES  | true, false
# TYPE    | boolean
restore_audio_state = true

# Reset threshold for the `previous` JSON-RPC method
#
# The `previous` method comes with an optional
# `threshold` parameter that specifies:
#
# ```
# If the current `Song` runtime (seconds) has passed this number,
# this method will reset the current `Song` instead of skipping backwards.
# Setting this to `0` will make this method always go to the previous `Song`.
# ```
#
# But if that parameter is `null`, this option
# will be used instead. The default if not
# specified here is 3 seconds.
#
# For example:
#   - A song is 3+ seconds in
#   - A `previous` method was received
#   - It will reset the current song instead of going back
#
# Setting this to `0` will make `previous`
# always go back if `threshold` is not specified.
#
# DEFAULT | 3
# VALUES  | 0, 3, 5, 100
# TYPE    | unsigned integer
previous_threshold = 3

# Enable/disable OS media controls
#
# `festivald` plugs into the native OS's media controls so that signals
# like `play/pause/stop` and/or keyboard controls can be processed.
#
# Setting this to `false` will disable media controls.
#
# DEFAULT | true
# VALUES  | true, false
# TYPE    | boolean
media_controls = true


#----------------------------------------------------------#
#                      AUTHORIZATION                       #
#----------------------------------------------------------#
# Only process connections to `festivald` that have a
# "authorization" HTTP header with this username and password.
#
# If either the `no_auth_rpc` or `no_auth_rest` options are
# used, then every RPC call/REST endpoint _NOT_ in those lists
# will require this authorization.
#
# TLS must be enabled for this feature to work
# or `festivald` will refuse to start.
#
# To set authorization EVEN IF TLS IS DISABLED,
# See `--confirm-no-tls-auth`.
#
# This value must be:
#   1. The "username"
#   2. Followed by a single colon ":"
#   3. Then the "password", e.g:
# ```
# curl -u my_user:my_pass https://127.0.0.1:18425
# ```
# or the equivalent wget command:
# ```
# wget --user my_user --password my_pass https://localhost:18425
# ```
#
# An empty string disables this feature.
#
# Alternatively, you can input an absolute PATH to a file
# `festivald` can access, containing the string, e.g:
# ```
# authorization = "/path/to/user_and_pass.txt"
# ```
# In this case, `festivald` will read the file and attempt
# to parse it with the same syntax, i.e, the file should contain:
# ```
# my_user:my_pass
# ```
#
# DEFAULT | "" (disabled)
# EXAMPLE | "my_username:my_password", "my_username:aoig2A%^$AWS^%", "/path/to/file"
# TYPE    | string or PATH to file
authorization = ""

# Allow authorization even without TLS
#
# This will let you set the authorization
# setting even if TLS is disabled.
#
# This means your `user:pass` will be sent in clear-text HTTP,
# unless you are wrapping HTTP in something else, like SSH
# port forwarding, or Tor.
#
# DEFAULT | false
# VALUES  | true, false
# TYPE    | boolean
confirm_no_tls_auth = false

# Allow specified JSON-RPC calls without authorization,
# while still requiring authorization for everything else.
#
# If a JSON-RPC method is listed in this array,
# `festivald` will allow any client to use it,
# regardless of authorization.
#
# This allows you to have `authorization` enabled
# across the board, but allow specific JSON-RPC
# calls for public usage.
#
# For example, if only `toggle` is listed, then
# clients WITHOUT authorization will only be
# allowed to use the `toggle` method, for every
# other method, they must authenticate.
#
# The method names listed here must match the
# exact names when using them, or shown in the
# documentation, see here:
#
# <https://docs.festival.pm/daemon/json-rpc/json-rpc.html>
#
# OR WITH
#
# ```
# festivald data --docs
# ```
# DEFAULT | [] (disabled)
# EXAMPLE | ["toggle", "state_audio", "volume"]
# TYPE    | string, must be a method name
no_auth_rpc = []

# Allow specified REST resources without authorization,
# while still requiring authorization for everything else.
#
# REST resources:
#   - `collection`
#   - `playlist`
#   - `artist`
#   - `album`
#   - `song`
#   - `art`
#
# If a REST resource is listed in this array,
# `festivald` will allow any client to use it,
# regardless of authorization.
#
# For example, if only `art` is listed, then
# clients WITHOUT authorization will only be
# allowed to use the `art` related endpoints
# (/rand/art, /current/art, etc). For every
# other endpoint (/rand/song, /collection, etc),
# they must authenticate.
#
# DEFAULT | [] (disabled)
# EXAMPLE | ["art", "song", "album"]
# TYPE    | string, must be a REST resource
no_auth_rest = []

# Allow documentation to be served without authorization,
# while still requiring authorization for everything else.
#
# DEFAULT | false
# VALUES  | true, false
# TYPE    | boolean
no_auth_docs = false

Disk

festivald saves all of its files within various "User OS" directories, owned by the user running it.

You can list all the PATHs on your system with:

./festivald --path

And delete them with with:

./festivald --delete

festivald saves everything into daemon/ because other Festival frontends also use the same festival project directory, e.g:

~/.local/share/festival/
  β”œβ”€ gui/
  β”œβ”€ daemon/
  β”œβ”€ cli/

Cache

Where festivald's cache data is saved (REST ZIP cache, etc).

PlatformValueExample
Windows{FOLDERID_LocalAppData}\Festival\cache\daemonC:\Users\Alice\AppData\Local\Festival\cache\daemon
macOS$HOME/Library/Caches/Festival/daemon/Users/Alice/Library/Caches/Festival/daemon
Linux$HOME/.cache/festival/daemon/home/alice/.cache/festival/daemon

The Cache sub-directories/files, and their purpose:

β”œβ”€ daemon/
   β”‚
   β”œβ”€ zip/ # Cached ZIP files
      β”‚
      β”œβ”€ collection/ # Cached `Collection` ZIPs, created by the `/collection` REST endpoint
      β”‚  β”‚
      β”‚  β”œβ”€ tmp/     # Temporary, un-finished ZIP files
      β”‚
      β”œβ”€ playlist/   # Cached `Playlist` ZIPs, created by the `/playlist/*` REST endpoints
      β”‚  β”‚
      β”‚  β”œβ”€ tmp/
      β”‚
      β”œβ”€ artist/     # Cached `Artist` ZIPs, created by the `*_artist` REST endpoints
      β”‚  β”‚
      β”‚  β”œβ”€ tmp/
      β”‚
      β”œβ”€ album/      # Cached `Artist` ZIPs, created by the `*_album` REST endpoints
      β”‚  β”‚
      β”‚  β”œβ”€ tmp/
      β”‚
      β”œβ”€ art/        # Cached `Artist` ZIPs, created by the `art_*` REST endpoints
      β”‚  β”‚
      β”‚  β”œβ”€ tmp/

Config

Where festivald's configuration files are saved.

PlatformValueExample
Windows{FOLDERID_RoamingAppData}\Festival\config\daemonC:\Users\Alice\AppData\Roaming\Festival\config\daemon
macOS$HOME/Library/Application Support/Festival/daemon/Users/Alice/Library/Application Support/Festival/daemon
Linux$HOME/.config/festival/daemon/home/alice/.config/festival/daemon

The Config sub-directories/files, and their purpose:

β”œβ”€ daemon/
   β”‚
   β”œβ”€ festivald.toml # Config file used by `festivald`

Data

Where festivald's main data is saved (the Collection, audio state, etc).

PlatformValueExample
Windows{FOLDERID_RoamingAppData}\Festival\data\daemonC:\Users\Alice\AppData\Roaming\Festival\data\daemon
macOS$HOME/Library/Application Support/Festival/daemon/Users/Alice/Library/Application Support/Festival/daemon
Linux$HOME/.local/share/festival/daemon/home/alice/.local/share/festival/daemon

The Data sub-directories/files, and their purpose:

β”œβ”€ daemon/
   β”‚
   β”œβ”€ state/
   β”‚  β”œβ”€ audio.bin      # Audio state, e.g: elapsed time, current song.
   β”‚  β”œβ”€ collection.bin # The main music `Collection`, holds metadata and PATHs to audio files.
   β”‚  β”œβ”€ playlists.bin  # The `Playlists` database, holds all playlist data
   β”‚
   β”œβ”€ txt/
   β”‚  β”œβ”€ crash.txt  # Crash/panic data. Useful for bug reports.
   β”‚  β”œβ”€ perf.json  # Collection creation performance timings, in JSON.
   β”‚
   β”œβ”€ docs/ # The static documentations files served by `festivald`
   β”‚
   β”œβ”€ image/ # Full-sized, un-changed `Album` art
   β”‚
   β”œβ”€ signal/ # This is how `festivald` communicates with an existing one
              # (e.g `festivald signal --play`), via filesystem-based signals.
              # `festivald signal --play` quite literally just creates an empty
              # file inside this folder called `play`.

Tor

Like other web services, festivald can be set-up & accessed via Tor.

A public instance of festivald with Creative Commons licensed music is available at:

https://daemon.festival.pm

and its Onion Service is available at:

http://omjo63yjj66ga7jlvhqib4z4qgx6y6oigjcpjcr5ehhfdugfuami3did.onion

Onion Service

festivald doesn't have special integration with Tor, but it can easily be turned into an Onion Service.

After getting festivald setup normally, follow the Onion Service instructions here.

Your torrc should look something like:

HiddenServiceDir /var/lib/tor/festivald
HiddenServicePort 80 127.0.0.1:18425

And in /var/lib/tor/festivald, you should have your onion service hostname, keys, etc.

This onion service will allow you to interact with festivald in all the normal ways, although, you must connect to it via Tor.

JSON-RPC

To use festivald's JSON-RPC API over Tor, your HTTP client must either use a proxy, or be wrapped with torsocks.

ONION="http://omjo63yjj66ga7jlvhqib4z4qgx6y6oigjcpjcr5ehhfdugfuami3did.onion"

festival-cli
	--proxy socks5://127.0.0.1:9050 \ # The Tor SOCKS5 proxy.
	--festivald $ONION \              # The onion address mapped to `festivald`
	daemon_state                      # Method

# or with `torsocks`
torsocks festival-cli -f $ONION daemon_state
ONION="http://omjo63yjj66ga7jlvhqib4z4qgx6y6oigjcpjcr5ehhfdugfuami3did.onion"

curl \
	--socks5-hostname 127.0.0.1:9050 \                    # The Tor SOCKS5 proxy.
	--festivald $ONION \                                  # The onion address mapped to `festivald`
	-d '{"jsonrpc":"2.0","id":0,"method":"daemon_state"}' # Method

REST

For the REST API, it is the same: your HTTP client must connect over Tor.

Although you could just use Tor Browser.

http://omjo63yjj66ga7jlvhqib4z4qgx6y6oigjcpjcr5ehhfdugfuami3did.onion/map/Ludwig van Beethoven/Moonlight Sonata 1/Moonlight Sonata Op. 27, No. 2 In C Sharp Minor: Allegretto

The equivalent curl command:

ONION="http://omjo63yjj66ga7jlvhqib4z4qgx6y6oigjcpjcr5ehhfdugfuami3did.onion"
SOCKS="127.0.0.1:9050"

curl --socks5-hostname $SOCKS -JO $ONION/map/Artist%20Name/Artist%20Title/Song%20Title

Authentication

Since Onion Service's are end-to-end encrypted, HTTPS is not required.

Thus, festivald can freely pass authentication tokens around when used as an Onion Service.

Although, since festivald cannot know if an onion address is being mapped to it, you must pass:

festivald --confirm-no-tls-auth

or set the confirm_no_tls_auth configuration to confirm that you allow authentication without TLS.

If the IP festivald is binding to is localhost/127.0.0.1, this setting will be enabled by default.

For festival-cli, it will automatically detect if you're connecting to an onion address and will allow authentication.

systemd

This is a relatively hardened systemd service file for festivald.

${USER} should be replaced by a user that has access to an audio server (like PulseAudio).

It should be placed at:

/etc/systemd/system/festivald.service

and launched with:

sudo systemctl start festivald

festivald.service

#===================#
# festivald.service #
#=======================================================#
# This is a systemd user service file for `festivald`.  #
# It is relatively hardened for public usage.           #
#                                                       #
# ${USER} should be replaced by a user that has         #
# access to an audio server (like PulseAudio).          #
#=======================================================#

[Unit]
Description=Festival Daemon
After=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
User=${USER} # <- Replace Me
Type=simple
ExecStart=/usr/bin/festivald

## Wait 35 seconds before sending SIGTERM on exit
KillSignal=SIGTERM
TimeoutStopSec=35s
SendSIGKILL=true

## Hardening
CapabilityBoundingSet=~CAP_NET_ADMIN CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_KILL CAP_SYS_PACCT CAP_SYS_BOOT CAP_SYS_CHROOT CAP_LEASE CAP_MKNOD CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_SYS_TIME CAP_IPC_LOCK CAP_LINUX_IMMUTABLE CAP_FOWNER CAP_IPC_OWNER CAP_SYS_RESOURCE
RestrictNamespaces=true
ProtectHostname=true
ProtectClock=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectProc=invisible
ProcSubset=pid
ProtectControlGroups=true
ProtectKernelTunables=true
PrivateUsers=true
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict

[Install]
WantedBy=default.target

Command Line

festivald takes in --flags for many purposes.

Arguments passed to festivald will always take priority over the same configuration options read from disk.

festivald also has a signal sub-command. For example, to send a signal to a festivald running on the same local machine, you can run:

./festivald signal --play

All these "signal"-related --flags live in the signal sub-command.

Examples

Here are some command-line usage examples.

Start festivald on http://localhost:18425 (by default)

./festivald
./festivald --path

Delete all data created/used by festivald

./festivald --delete

Set log level, disable everything except JSON-RPC, start festivald

./festivald --log-level DEBUG --disable-watch --disable-media-controls --disable-rest --disable-docs

Top-level flags

Usage: festivald [OPTIONS] [COMMAND + OPTIONS] [ARGS...]

Arguments passed to `festivald` will always take
priority over configuration options read from disk.

Commands:
  signal  Send a signal to a `festivald` running on the same machine
  help    Print this message or the help of the given subcommand(s)

Options:
      --ip <IP>
          The IPv4 address `festivald` will bind to [default: 127.0.0.1]

      --port <PORT>
          The port `festivald` will bind to [default: 18425]
          
          Using port `0` will select a random port.

      --max-connections <NUMBER>
          Max amount of connections [default: unlimited]
          
          The max amount of connections `festivald`
          will serve at any given moment.
          `0` means unlimited.
          
          Note that 1 client doesn't necessarily mean
          1 connection. A single web browser client for
          example can make many multiple connections
          to `festivald`.

      --exclusive-ip <IP>
          Only accept connections from these IPs
          
          `festivald` will only serve connections coming
          from these IPs. If there's no value given or
          any of the values is "0.0.0.0", `festivald`
          will serve all IP ranges.
          
          To allow multiple IPs, use this flag per IP.
          
          Example: `festivald --exclusive-ip 127.0.0.1 --exclusive-ip 192.168.2.1`

      --tls
          Enable HTTPS
          
          You must also provide a PEM-formatted X509 certificate
          and key in the below options for this to work.
          
          Example: `festivald --tls --certificate /path/to/cert.pem --key /path/to/key.pem`

      --certificate <FILE>
          The PEM-formatted X509 certificate file used for TLS

      --key <FILE>
          The PEM-formatted key file used for TLS

      --authorization <USER:PASS or FILE>
          Enforce a `username` and `password` for connections to `festivald`
          
          Only process connections to `festivald` that have a
          "authorization" HTTP header with this username and password.
          
          If either the `--no-auth-rpc` or `--no-auth-rest` options are
          used, then every RPC call/REST endpoint _NOT_ in those lists
          will require this authorization.
          
          TLS must be enabled or `festivald` must be started
          on `localhost` for this feature to work or `festivald`
          will refuse to start.
          
          To set authorization EVEN IF TLS IS DISABLED,
          See `--confirm-no-tls-auth`.
          
          This value must be:
            1. The "username"
            2. Followed by a single colon ":"
            3. Then the "password", e.g:
          ```
          festivald --authorization my_user:my_pass
          ```
          An empty string disables this feature.
          
          Alternatively, you can input an absolute PATH to a file
          `festivald` can access, containing the string, e.g:
          ```
          festivald --authorization "/path/to/user_and_pass.txt"
          ```
          In this case, `festivald` will read the file and attempt
          to parse it with the same syntax, i.e, the file should contain:
          ```
          my_user:my_pass
          ```

      --confirm-no-tls-auth
          Allow `--authorization` even without TLS
          
          This will let you set the authorization
          setting even if TLS is disabled.
          
          This means your `user:pass` will be sent in clear-text HTTP,
          unless you are wrapping HTTP in something else, like SSH
          port forwarding, or Tor.

      --no-auth-rpc <METHOD>
          Allow specified JSON-RPC calls without authorization
          
          If a JSON-RPC method is listed in this array,
          `festivald` will allow any client to use it,
          regardless of authorization.
          
          This allows you to have `authorization` enabled
          across the board, but allow specific JSON-RPC
          calls for public usage.
          
          For example, if only `toggle` is listed, then
          clients WITHOUT authorization will only be
          allowed to use the `toggle` method, for every
          other method, they must authenticate.
          
          The method names listed here must match the
          exact names when using them, or shown in the
          documentation, see here:
          
          <https://docs.festival.pm/daemon/json-rpc/json-rpc.html>
          
          OR WITH
          
          ```
          festivald data --docs
          ```
          
          To allow multiple methods, use this flag per method.
          
          Example: `festivald --no-auth-rpc toggle --no-auth-rpc volume`

      --no-auth-rest <RESOURCE>
          Allow specified REST resources without authorization
          
          REST resources:
            - `collection`
            - `playlist`
            - `artist`
            - `album`
            - `song`
            - `art`
          
          If a REST resource is listed in this array,
          `festivald` will allow any client to use it,
          regardless of authorization.
          
          For example, if only `art` is listed, then
          clients WITHOUT authorization will only be
          allowed to use the `art` related endpoints
          (/rand/art, /current/art, etc). For every
          other endpoint (/rand/song, /collection, etc),
          they must authenticate.
          
          To allow multiple methods, use this flag per method.
          
          Example: `festivald --no-auth-rest art --no-auth-rest song`

      --no-auth-docs
          Allow documentation to be served without authorization

      --sleep-on-fail <MILLI>
          Sleep before responding to a (potentially malicious) failed connections
          
          Upon a failed, potentially malicious request, instead of
          immediately responding, `festivald` will randomly sleep
          up to this many milliseconds before responding to the connection.
          
          This includes:
            - Authentication failure
            - IPs not in the `exclusive_ips` list
            - IPv6 connections
          
          If 0, `festivald` will immediately respond. This may
          not be wanted to due potential DoS and timing attacks.
          
          If you're hosting locally (127.0.0.1), you can set this
          to 0 (unless you don't trust your local network?).

      --collection-path <PATH>
          Default PATHs to use for the `Collection`
          
          Upon a `collection_new` JSON-RPC method call, if the
          `paths` parameter is empty, these PATHs will be scanned
          instead.
          
          If this is not set, the default OS `Music` directory will be scanned.
          
          If `festivald` is running on Windows, you can use
          Windows-style PATHs: `C:\\Users\\User\\Music`.
          
          To set multiple PATHs, use this flag per PATH.
          
          Example: `festivald --collection-path /my/path/1 --collection-path /my/path/2`

      --direct-download
          Enable direct downloads via the REST API for browsers
          
          By default, accessing the REST API via a browser
          will open the resource in the browser (audio player,
          image viewer, etc)
          
          Using this flag will make browsers download
          the file directly, without opening it.

      --filename-separator <SEPARATOR>
          When files are downloaded via the REST API, and the
          file is a nested object referencing multiple things
          (e.g, an _album_ owned by an _artist_), we must include
          that information, but what string should separate them?
          
          The default separator is " - ", e.g:
          ```
          Artist Name - Album Title.zip
          ```
          it can be changed to any string, like "/":
          ```
          Artist Name/Album Title.zip
          ```
          or left empty "" for no separator at all.
          
          This cannot include a slash: `/`
          as that is the legal PATH separator in ZIP files.

      --disable-cache-clean
          Enable/disable cleaning up cache
          
          When serving `ZIP` files via the REST API, `festivald`
          will first write them to disk, then serve those files
          instead of directly storing everything in memory,
          as to not get OOM-killed on more than a few requests.
          
          Setting this to `false` will make `festivald`
          never clean those files up, ever.
          
          This will make `cache_time` not do anything and will
          also prevent `festivald` from the usual startup/shutdown
          cache cleaning that it does.

      --cache-time <SECONDS>
          Set the REST API cache time limit
          
          This option sets the time limit on how many seconds
          `festivald` will hold onto this cache for.
          
          Once the time limit is up, `festivald` will remove the
          file. This cache is also reset on startup and shutdown.
          
          This does nothing if `--disable-cache-clean` is passed.

      --disable-restore-audio-state
          Disable audio state restoration
          
          Upon startup, `festivald` (by default) will recover
          audio state (volume, exact position in song, queue, etc).
          
          Using this option disables this.

      --disable-watch
          Disable watching the filesystem for signals
          
          The way a newly launched `festivald` communicates to
          an already existing one (e.g, `festivald signal --play`) is
          by creating a file in `festivald`'s `signal` directory.
          
          `festivald signal --FLAG` just creates a file in that directory,
          which an existing `festivald` will notice and do the appropriate task.
          
          Using `--disable-watch` will disable that part of the system so that
          filesystem signals won't work, e.g, `festivald signal --play` will not work.

      --disable-media-controls
          Disable OS media controls
          
          `festivald` plugs into the native OS's media controls so that signals
          like `play/pause/stop` and/or keyboard controls can be processed.
          
          `--disable-media-controls` disables this.

      --disable-rest
          Disable the REST API
          
          This is responsible for the `/rest` API that
          serves image, audio, and other heavy resource data.
          
          `--disable-rest` will disable this part of the system,
          and will only leave the JSON-RPC API available.

      --disable-docs
          Enable/disable serving documentation
          
          By default, `festivald` serves a markdown book
          of it's own documentation, accessible at the
          root `/` endpoint, e.g:
          ```
          http://localhost:18425/
          ```
          
          `--disable-docs` will disable that.

      --log-level <OFF|ERROR|INFO|WARN|DEBUG|TRACE>
          Set filter level for console logs

      --dry-run
          Print the configuration `festivald` would have used, but don't actually startup
          
          This will go through the regular process of:
            - Reading disk for config
            - Reading command-line
            - Merging options together
            - Validating options
          
          and then print them out as JSON, and exit.

      --docs
          Open documentation locally in browser
          
          This opens `festivald'`s documentation in a web
          browser, and does not start `festivald` itself.

      --path
          Print the PATHs used by `festivald`
          
          All data saved by `festivald` is saved in these directories.
          For more information, see: <https://docs.festival.pm/daemon/disk.html>

      --reset-config
          Reset the current `festivald.toml` config file to the default
          
          Exits with `0` if everything went ok, otherwise shows error.

      --reset-cache
          Reset the `festivald` cache folder
          
          This deletes all currently existing `REST` resource cache.

      --delete
          Delete all `festivald` files that are on disk
          
          This deletes all `daemon` Festival folders.
          The PATHs deleted will be printed on success.

      --methods
          Print all the JSON-RPC methods available

  -v, --version
          Print version

  -h, --help
          Print help (see a summary with '-h')

Sub-command: signal

Send a signal to a `festivald` running on the same machine

This will not start a new `festivald`, but send a
signal to an already running one. This only works
if there's a `festivald` already running on the
same machine.

The flag `--disable-watch` disables this feature.

Usage: festivald signal OPTION [ARG]

Options:
      --play
          Start playback

      --pause
          Pause playback

      --toggle
          Toggle playback (play/pause)

      --next
          Skip to next track

      --previous
          Play previous track

      --stop
          Clear queue and stop playback

      --clear
          Clear queue but don't stop playback

      --shuffle
          Shuffle the current queue and reset to the first song

      --repeat-song
          Turn on single `Song` track repeat

      --repeat-queue
          Turn on queue repeat

      --repeat-off
          Turn off repeating

      --volume <VOLUME>
          Set the volume to `VOLUME` (0-100)

      --seek <SECOND>
          Seek to the absolute `SECOND` second in the current song

      --seek-forward <SECOND>
          Seek `SECOND` seconds forwards in the current song

      --seek-backward <SECOND>
          Seek `SECOND` seconds backwards in the current song

      --index <NUMBER>
          Set the current song to the index `NUMBER` in the queue.
          
          NOTE:
          The queue index starts from 1 (first song is `--index 1`).
          
          Providing an index that is out-of-bounds
          will end the queue (even if repeat is turned on).

      --skip <NUMBER>
          Skip `NUMBER` amount of songs
          
          If the last song in the queue is skipped over,
          and queue repeat is turned on, this will reset
          the current song to the 1st in the queue.

      --back <NUMBER>
          Go backwards in the queue by `NUMBER` amount of songs
          
          If `NUMBER` is greater than the amount of songs we can
          skip backwards, this will reset the current song to
          the 1st in the queue.

  -h, --help
          Print help (see a summary with '-h')

Authorization

festivald has a Basic access authentication option in its configuration, with a username + password setup.

An optional bypass is available on specified JSON-RPC methods, REST resources, and documentation.

If authorization is enabled, festivald will only process connections to it that have the "authorization" HTTP header with this username and password (unless specified in the bypass options).

TLS must be enabled for this feature to work or festivald will refuse to start.

However, there are cases where authorization without TLS is okay (reverse proxy, Tor Onion Service, etc). In these cases, the confirm_no_tls_auth option will allow authorization without TLS.

If festivald is started on localhost (127.0.0.1), it will allow authorization without TLS as well.

authorization can either be set in the config file or passed via a command-line flag.

Syntax

The username & password syntax is specified in RFC 7617.

The "authorization" value must be:

  1. The username
  2. Followed by a single colon ":"
  3. Then the password

For example:

my_user:my_pass

A request including this information looks like:

curl -u my_user:my_pass https://127.0.0.1:18425

or the equivalent wget command:

wget --user my_user --password my_pass --auth-no-challenge https://localhost:18425

or the equivalent festival-cli command:

festival-cli -u my_user -p my_pass https://localhost:18425

Alternatively, you can input an absolute PATH to a file festivald can access, containing the string, e.g:

authorization = "/path/to/user_and_pass.txt"

In this case, festivald will read the file and attempt to parse it with the same syntax, i.e, the file should contain:

my_user:my_pass

RFC 7617

Note that curl, wget and festival-cli all follow RFC 7617, as in, they craft their HTTP authorization header to be:

Basic <user:pass in base64>

So these commands:

# Curl
curl -u user:pass https://localhost:18425

# Wget
wget --user=user --password=pass --auth-no-challenge https://localhost:18425

# festival-cli
festival-cli -u user:pass https://localhost:18425

sends this as the HTTP authorization header:

Basic dXNlcjpwYXNz

If you are creating a client for festivald, you must do this for authorization as well.

Web Browser

If connecting to festivald via a web browser, you will receive a visual prompt for authorization:

authorization

JSON-RPC

The no_auth_rpc config option or --no-auth-rpc command-line flag will allow specified JSON-RPC calls without authorization, while still requiring authorization for everything else.

If a JSON-RPC method is listed in these options festivald will allow any client to use it, regardless of authorization.

This allows you to have authorization enabled across the board, but allow specific JSON-RPC calls for public usage.

Usage

The method names in the option must match the exact names of the actual methods.

For example:

If a specified method name is incorrect, festivald will not start.

Example

For example, if toggle is listed, then ALL clients will be allowed to use the toggle method, for every other method, they must authenticate.

festivald.toml:

authorization = "user:pass"
no_auth_rpc   = ["toggle"]

Unauthorized client:

# Even though we didn't specify `-u user:pass`,
# `festivald` will accept this RPC call.
curl https://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"toggle"}'

# But not this one.
curl https://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"stop"}'

Authorized client:

# This _does_ have authentication,
# so it can do whatever it wants.
curl https://localhost:18425 -u user:pass -d '{"jsonrpc":"2.0","id":0,"method":"stop"}'

REST

The no_auth_rest config option or --no-auth-rest command-line flag will allow specified REST resources without authorization, while still requiring authorization for everything else.

If a REST resource is listed in these options festivald will allow any client to access it, regardless of authorization.

This allows you to have authorization enabled across the board, but allow specific REST resources for public usage.

Usage

The specified REST resources must be one of these string's:

REST resourceAllowsExample endpoint
collectionAccess to downloading the whole Collection/collection
playlistAccess to downloading Playlist ZIPs/playlist
artistAccess to downloading Artist ZIPs/current/artist, /map/artist
albumAccess to downloading Album ZIPs/current/album, /map/album
songAccess to downloading Song files/current/song, /map/song
artAccess to downloading Art ZIPs & files/current/art, /art/artist

If a specified REST resource name is incorrect, festivald will not start.

Example

For example, if the value is ["art", "song"], ALL clients will be allowed to use the art and song-related endpoints, for all other endpoints, they must authenticate.

festivald.toml:

authorization = "user:pass"
no_auth_rest  = ["art", "song"]

Unauthorized client:

# Even though we didn't specify `-u user:pass`,
# `festivald` will let us download some art.
curl https://localhost:18425/rand/art

# And some song files.
curl https://localhost:18425/rand/song

# BUT it will not let us download whole albums.
curl https://localhost:18425/rand/album

# Or playlists.
curl https://localhost:18425/playlist/sorted/Playlist 1

Authorized client:

# This _does_ have authentication,
# so it can do whatever it wants.
curl https://localhost:18425/rand/album -u user:pass
curl https://localhost:18425/playlist/sorted/Playlist 1 -u user:pass

Documentation

The no_auth_docs config option or --no-auth-docs command-line flag will allow documentation to be served without authorization, while still requiring authorization for everything else.

Example

festivald.toml:

authorization = "user:pass"
no_auth_docs  = true

Unauthorized client:

# Even though we didn't specify `-u user:pass`,
# `festivald` will let us download/read docs.
curl https://localhost:18425

# BUT if `REST` requires authentication, this will not work.
curl https://localhost:18425/rand/album

Authorized client:

# This _does_ have authentication,
# so it can do whatever it wants.
curl https://localhost:18425/rand/album -u user:pass

API Stability

Some notes on what parts of festivald's API can/cannot be relied upon.

In general - things may be added, but never removed.

If something is unstable, it will be marked as such.

Anything that feels like an API but isn't explicitly marked in festivald's documentation should be assumed to be πŸ”΄ Unstable.

Breaking Changes

Breaking changes to the stable API may occur in 3 situations:

  1. festivald v2.0.0 release
  2. There is a fundamental/security bug that must be fixed in festivald
  3. There is a difference between this documentation and the actual festivald input/output

These will be noted in release notes if they ever occur.

Marker

In the documentation for all Objects, JSON-RPC methods, and REST endpoints there will be a "marker" defining the stability of that API. It will be 1 of the 4 listed markers here.

🟒 Stable

This marks that this API's input/output will never change, and can be relied upon.

🟑 Incomplete

This marks that the output of this API may have additions in the future.

The existing inputs/outputs will not change, however, additional output may appear.

πŸ”΄ Unstable

This marks that this API may in the future:

  • Have additions to input/output
  • Have subtractions to input/output
  • Be renamed
  • Be completely removed

It should not be relied across different festivald versions.

⚫️ Deprecated

This marks that this API has been superseded by a better one.

The old API will continue to exist, but it is recommended to use the newer one.

JSON-RPC

JSON-RPC-specific API stability edge cases.

Naming

All method names, parameter names, and field names are in lower_case_snake_case.

This is 🟒 Stable.

Ordering

The ordering of non-stable output/object fields is πŸ”΄ Unstable.

The ordering of 🟒 Stable output/object fields is 🟒 Stable.

Old v1.0.0 JSON-RPC example:

// 🟑 Incomplete Response
{
  "jsonrpc": "2.0",
  "result": {
    "field1": "Output field 1",
    "field2": "Output field 2"
  },
  "id": 0,
}

// 🟒 Stable Response
{
  "jsonrpc": "2.0",
  "result": {
    "field1": "Output field 1", // Will always be 1, then 2.
    "field2": "Output field 2"
  },
  "id": 0,
}

New v1.1.0 JSON-RPC example:

// 🟑 Incomplete Response
{
  "jsonrpc": "2.0",
  "result": {
    "field3": "Output field 3", // Ordering may
    "field1": "Output field 1", // shift around
    "field4": "Output field 4", // on incomplete
    "field2": "Output field 2"  // methods.
  },
  "id": 0,
}

// 🟒 Stable Response
{
  "jsonrpc": "2.0",
  "result": {
    "field1": "Output field 1", // Still 1, 2.
    "field2": "Output field 2"
  },
  "id": 0,
}

REST

REST-specific API stability edge cases.

ZIP

  1. For REST endpoints that serve large collections of files, the ZIP format will be used
  2. There is no compression applied to the files, they are stored as-is
  3. These ZIPs can be found the in Cache folder with the exact same name as sent to the client

These points are all 🟒 Stable.

ZIP /

ZIP files cannot have internal filenames with /, as that is the legal PATH separator, so all:

  • File names
  • Playlist names
  • Artist names
  • Album titles
  • Song titles

inside ZIPs that contain / will always be replaced with a single dash with no spaces: -

This also applies to the filename_separator, it cannot include /.

Example:

Artist/With/Slash.zip # This is fine, the actual ZIP filename will be quoted.
  β”‚
  β”œβ”€Artist/With/Slash # This will be turned into `Artist-With-Slash`
      β”‚
      β”œβ”€ Album With//Slashes # This will be turned into `Album With--Slashes`
           β”‚
           β”œβ”€ Song With/A Slash # This will be turned into `Song With-A Slash`

This is πŸ”΄ Unstable. The behavior may change in the future.

Duplicate Filenames

When packaging Song's into ZIPs, if there a multiple Song's with the same name in the same Album, it will be suffixed with an incrementing number in parentheses starting from 1.

For example:

My Song.flac
My Song (1).flac
My Song (2).flac
My Song (3).flac

This is πŸ”΄ Unstable. The behavior may change in the future.

File Format & Names

The file format type and names of those files1 in the REST API are both 🟒 Stable.

(1 The filenames depend on the user-specified filename_separator, but the general formatting of them is stable)

The below example uses the default - as the filename_separator.

REST resourceFile Format TypeFilename Formatting
collectionzipCollection - ${CREATION_UNIX_TIMESTAMP}.zip
playlistzipPlaylist - ${PLAYLIST_NAME}.zip
artistzip${ARTIST_NAME}.zip
albumzip${ARTIST_NAME} - ${ALBUM_TITLE}.zip
songOriginal audio format (flac, mp3, etc)${ARTIST_NAME} - ${ALBUM_TITLE} - ${SONG_TITLE}.${AUDIO_FORMAT}
artOriginal image format (png, jpg, etc)${ARTIST_NAME} - ${ALBUM_TITLE}.${IMAGE_FORMAT}

ZIP File Hierarchy

The file hierarchy within ZIPs, and the internal file/folder names are both 🟒 Stable.

This below example will be the same for the rest of festivald v1.x.x:

# Input
https://localhost:18425/collection

# Output
Collection - ${CREATION_UNIX_TIMESTAMP}.zip

# Extracted
Collection - ${CREATION_UNIX_TIMESTAMP}/
    β”‚
    β”œβ”€ ${ARTIST_NAME}/
    β”‚    β”‚
    β”‚    β”œβ”€ ${ALBUM_TITLE}/
    β”‚         β”‚
    β”‚         β”œβ”€ ${ALBUM_TITLE}.${IMAGE_FORMAT}
    β”‚         β”œβ”€ ${SONG_TITLE}.${AUDIO_FORMAT}
    β”‚
    β”‚
    β”œβ”€ ${ARTIST_NAME}/
    β”‚    β”‚
    β”‚    β”œβ”€ ${ALBUM_TITLE}/
    β”‚         β”‚
    β”‚         β”œβ”€ ${ALBUM_TITLE}.${IMAGE_FORMAT}
    β”‚         β”œβ”€ ${SONG_TITLE}.${AUDIO_FORMAT}
    β”‚
    β”‚
	[ ... etc ... ]

Misc

Miscellaneous parts of festivald that can or cannot be relied on.

festival-cli

festivald and festival-cli's versions are tied together to represent their compatibility.

festivald will be able to respond to any 🟒 Stable festival-cli request as long as festivald's:

  • Major version is the same
  • Minor version is the same or greater

For example, festivald v1.2.x is compatible with:

  • festival-cli v1.2.x
  • festival-cli v1.1.x
  • festival-cli v1.0.x

but not necessarily with festival-cli v1.3.x and beyond.

Note that festivald will still be able to communicate with newer/older festival-cli's, however:

  • If a new festival-cli is requesting a method unknown to an old festivald, or
  • If a new festivald has additional output unknown to an old festival-cli (use of non-stable API)

there will be communication issues.

Config

  • config names are 🟒 Stable (max_connections will always be named max_connections)
  • Their expected inputs are 🟒 Stable (max_connections will always want an unsigned integer)
  • Their expected behavior is 🟑 Incomplete (direct_download may include song files someday)
  • Default config values may be changed (default port value may not always be 18425)
  • Additional fields may be added in the future

Referencing any JSON-RPC methods and/or REST resources that are πŸ”΄ Unstable in options like no_auth_rpc & no_auth_rest will also make your configuration πŸ”΄ Unstable.

In general, behavior for existing config options may be extended if it does not break current behavior too much.

For example, direct_download will most likely support showing inline audio files eventually.

Command Line

  • --flags and sub-command names are 🟒 Stable (festivald --path will always be festivald --path)
  • Their expected inputs/outputs are 🟒 Stable
  • Additional flags and/or sub-commands may be added in the future

Disk

All locations and filenames of all files written to disk by festivald are 🟒 Stable.

TypeExample
CacheArtist ZIP cache is always at ~/.cache/festival/daemon/zip/artist
ConfigConfig file is always at ~/.config/festival/daemon/festivald.toml
DataCollection file is always at ~/.local/share/festival/daemon/state/collection.bin

Documentation

πŸ”΄ Unstable.

Do not rely on the exact name or position of something within this documentation.

For example, this section API Stability may be renamed to API Reliability and/or moved to a different chapter.

Documentation may change at any given moment to provide the most accurate information.

Errors

πŸ”΄ Unstable.

Do not rely on the details of the JSON-RPC & REST API errors.

You can rely that an input that leads to OK/ERROR will always be the same.

Logs

πŸ”΄ Unstable.

Do not rely on the log output of festivald.

HTTP Headers

πŸ”΄ Unstable.

Do not rely on the specific HTTP headers festivald returns, or their values.

Protocol

  • Transports other than HTTP(s) may be supported in the future
  • Version 2.0 of JSON-RPC will always be used
  • JSON-RPC will always require HTTP POST requests
  • REST and documentation will always require HTTP GET requests

Common Objects

These objects often appear in the output of many JSON-RPC calls.

The definitions of these objects will be here, instead of everywhere they appear in the documentation.

Collection

The Collection is the main music library/database in festivald.

The 3 Common Objects

The 3 common "objects" that appear almost everywhere are:

Keys

And the number key that acts as the identifier for them:

  • Artist key
  • Album key
  • Song key

Entry

Entry is an "absolute" key, as it holds all integer Key's and all string key's relating to a Song.

Playlist

Playlist's are regular lists of Song's.

The "entries" within a Playlist aren't Song objects themselves, but Entry-like objects called Playlist Entry's.

Generic Response

This is the generic "success" response object, just an empty result:

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0         // the `result` field existing in JSON-RPC means success,
}                 // so the value in this case (null) doesn't matter.

This is the response to many JSON-RPC as well, typically the Playback Control methods.

If an error occurred in this situation, the JSON-RPC defined error would be used:

{
  "jsonrpc": "2.0",
  "error": {          // <--- something went wrong.
    "code": -1,       // <--- the error code.
    "message": "...", // <--- short message of the error.
  },
  "id": 0
}

Collection

🟑 Incomplete

This API's output may have additions in the future.


This is the main music "library" or "database" that festivald creates and uses.

It is the central component, and almost all other methods/endpoints use it in some way.

It does not contain actual audio/image data, but rather metadata and links to where those resources can be found.

The Collection contains many nested objects, including the common 3:

The sort_* fields are a bunch of keys that represent an ordering.

For example, the sort_artist_lexi array contains Artist keys that are in Artist name A-Z ordering, so the first Artist in that array will be something like ArtistStartingWithA and the last will probably be something like ZArtist.

String sorting is done lexicographically as per Rust's string ordering implementation. UTF-8 strings are accepted, so non-English characters and emojis will work, although it is unclear which languages come first/last, or whether πŸ‘Ί is before/after 🀑. Regardless, the implementation linked handles that.

This full Collection object can be received via the collection_full method.

FieldTypeDescription
emptybooleanIf the Collection does NOT have any Artist's, Album's, or Song's
timestampunsigned integerThe UNIX timestamp of when this Collection was created
count_artistunsigned integerHow many unique Artist's there are in this Collection
count_albumunsigned integerHow many unique Album's there are in this Collection
count_songunsigned integerHow many unique Song's there are in this Collection
count_artunsigned integerHow much unique Album art there are in this Collection
artistsarray of Artist objectsAn array of Artist objects
albumsarray of Album objectsAn array of Album objects
songsarray of Song objectsAn array of Song objects
sort_artist_lexiarray of Artist keys (unsigned integers)Artists A-Z
sort_artist_lexi_revarray of Artist keys (unsigned integers)Artists Z-A
sort_artist_album_countarray of Artist keys (unsigned integers)Artists per album count (least to most)
sort_artist_album_count_revarray of Artist keys (unsigned integers)Artists per album count (most to least)
sort_artist_song_countarray of Artist keys (unsigned integers)Artists per song count (least to most)
sort_artist_song_count_revarray of Artist keys (unsigned integers)Artists per song count (most to least)
sort_artist_runtimearray of Artist keys (unsigned integers)Artists runtime shortest-longest
sort_artist_runtime_revarray of Artist keys (unsigned integers)Artists runtime longest-shortest
sort_artist_namearray of Artist keys (unsigned integers)Artist name shortest-longest
sort_artist_name_revarray of Artist keys (unsigned integers)Artist name longest-shortest
sort_album_release_artist_lexiarray of Album keys (unsigned integers)Artists A-Z, albums oldest-latest
sort_album_release_artist_lexi_revarray of Album keys (unsigned integers)Artists Z-A, albums oldest-latest
sort_album_release_rev_artist_lexiarray of Album keys (unsigned integers)Artists A-Z, albums latest-oldest
sort_album_release_rev_artist_lexi_revarray of Album keys (unsigned integers)Artists Z-A, albums latest-oldest
sort_album_lexi_artist_lexiarray of Album keys (unsigned integers)Artists A-Z, albums A-Z
sort_album_lexi_artist_lexi_revarray of Album keys (unsigned integers)Artists Z-A, albums A-Z
sort_album_lexi_rev_artist_lexiarray of Album keys (unsigned integers)Artists A-Z, albums Z-A
sort_album_lexi_rev_artist_lexi_revarray of Album keys (unsigned integers)Artists Z-A, albums Z-A
sort_album_lexiarray of Album keys (unsigned integers)Albums A-Z
sort_album_lexi_revarray of Album keys (unsigned integers)Albums Z-A
sort_album_releasearray of Album keys (unsigned integers)Albums oldest-latest
sort_album_release_revarray of Album keys (unsigned integers)Albums latest-oldest
sort_album_runtimearray of Album keys (unsigned integers)Albums shortest-longest
sort_album_runtime_revarray of Album keys (unsigned integers)Albums longest-shortest
sort_album_titlearray of Album keys (unsigned integers)Album title shortest-longest
sort_album_title_revarray of Album keys (unsigned integers)Album title longest-shortest
sort_song_album_release_artist_lexiarray of Song keys (unsigned integers)Artists A-Z, albums oldest-latest, songs in track order
sort_song_album_release_artist_lexi_revarray of Song keys (unsigned integers)Artists Z-A, albums oldest-latest, songs in track order
sort_song_album_release_rev_artist_lexiarray of Song keys (unsigned integers)Artists A-Z, albums latest-oldest, songs in track order
sort_song_album_release_rev_artist_lexi_revarray of Song keys (unsigned integers)Artists Z-A, albums latest-oldest, songs in track order
sort_song_album_lexi_artist_lexiarray of Song keys (unsigned integers)Artists A-Z, albums A-Z, songs in track order
sort_song_album_lexi_artist_lexi_revarray of Song keys (unsigned integers)Artists Z-A, albums A-Z, songs in track order
sort_song_album_lexi_rev_artist_lexiarray of Song keys (unsigned integers)Artists A-Z, albums Z-A, songs in track order
sort_song_album_lexi_rev_artist_lexi_revarray of Song keys (unsigned integers)Artists Z-A, albums Z-A, songs in track order
sort_song_lexiarray of Song keys (unsigned integers)Songs A-Z
sort_song_lexi_revarray of Song keys (unsigned integers)Songs Z-A
sort_song_releasearray of Song keys (unsigned integers)Songs oldest-latest
sort_song_release_revarray of Song keys (unsigned integers)Songs latest-oldest
sort_song_runtimearray of Song keys (unsigned integers)Songs shortest-longest
sort_song_runtime_revarray of Song keys (unsigned integers)Songs longest-shortest
sort_song_titlearray of Song keys (unsigned integers)Song title shortest-longest
sort_song_title_revarray of Song keys (unsigned integers)Song title longest-shortest

Example

{
  "jsonrpc": "2.0",
  "result": {
    "empty": false,
    "timestamp": 1691018515,
    "count_artist": 3,
    "count_album": 4,
    "count_song": 7,
    "count_art": 4,
    "artists": [
      {
        "name": "artist_1",
        "key": 0,
        "runtime": 4,
        "albums": [
          0,
          1
        ],
        "songs": [
          0,
          1,
          2,
          3
        ]
      },
      {
        "name": "artist_2",
        "key": 1,
        "runtime": 2,
        "albums": [
          2
        ],
        "songs": [
          4,
          5
        ]
      },
      {
        "name": "artist_3",
        "key": 2,
        "runtime": 1,
        "albums": [
          3
        ],
        "songs": [
          6
        ]
      }
    ],
    "albums": [
      {
        "title": "album_1",
        "key": 0,
        "artist": 0,
        "release": "2018-04-25",
        "runtime": 2,
        "song_count": 2,
        "songs": [
          0,
          1
        ],
        "discs": 0,
        "art": 10239,
        "genre": null
      },
      {
        "title": "album_2",
        "key": 1,
        "artist": 0,
        "release": "2018-04-25",
        "runtime": 2,
        "song_count": 2,
        "songs": [
          2,
          3
        ],
        "discs": 0,
        "art": 10239,
        "genre": null
      },
      {
        "title": "album_3",
        "key": 2,
        "artist": 1,
        "release": "2018-04-25",
        "runtime": 2,
        "song_count": 2,
        "songs": [
          4,
          5
        ],
        "discs": 1,
        "art": 10239,
        "genre": null
      },
      {
        "title": "album_4",
        "key": 3,
        "artist": 2,
        "release": "2018-04-25",
        "runtime": 1,
        "song_count": 1,
        "songs": [
          6
        ],
        "discs": 0,
        "art": 10239,
        "genre": null
      }
    ],
    "songs": [
      {
        "title": "mp3",
        "key": 0,
        "album": 0,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "mp3",
        "key": 1,
        "album": 0,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 2,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "mp3",
        "key": 2,
        "album": 1,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "flac",
        "key": 3,
        "album": 1,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 2,
        "disc": 2,
        "mime": "audio/x-flac",
        "extension": "flac"
      },
      {
        "title": "m4a",
        "key": 4,
        "album": 2,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": null,
        "mime": "audio/m4a",
        "extension": "m4a"
      },
      {
        "title": "song_6",
        "key": 5,
        "album": 2,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 2,
        "disc": 2,
        "mime": "audio/ogg",
        "extension": "ogg"
      },
      {
        "title": "mp3",
        "key": 6,
        "album": 3,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ],
    "sort_artist_lexi": [
      0,
      1,
      2
    ],
    "sort_artist_lexi_rev": [
      2,
      1,
      0
    ],
    "sort_artist_album_count": [
      1,
      2,
      0
    ],
    "sort_artist_album_count_rev": [
      0,
      2,
      1
    ],
    "sort_artist_song_count": [
      2,
      1,
      0
    ],
    "sort_artist_song_count_rev": [
      0,
      1,
      2
    ],
    "sort_artist_runtime": [
      2,
      1,
      0
    ],
    "sort_artist_runtime_rev": [
      0,
      1,
      2
    ],
    "sort_artist_name": [
      0,
      1,
      2
    ],
    "sort_artist_name_rev": [
      2,
      1,
      0
    ],
    "sort_album_release_artist_lexi": [
      0,
      1,
      2,
      3
    ],
    "sort_album_release_artist_lexi_rev": [
      3,
      2,
      0,
      1
    ],
    "sort_album_release_rev_artist_lexi": [
      1,
      0,
      2,
      3
    ],
    "sort_album_release_rev_artist_lexi_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_lexi_artist_lexi": [
      0,
      1,
      2,
      3
    ],
    "sort_album_lexi_artist_lexi_rev": [
      3,
      2,
      0,
      1
    ],
    "sort_album_lexi_rev_artist_lexi": [
      1,
      0,
      2,
      3
    ],
    "sort_album_lexi_rev_artist_lexi_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_lexi": [
      0,
      1,
      2,
      3
    ],
    "sort_album_lexi_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_release": [
      0,
      1,
      2,
      3
    ],
    "sort_album_release_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_runtime": [
      3,
      0,
      1,
      2
    ],
    "sort_album_runtime_rev": [
      2,
      1,
      0,
      3
    ],
    "sort_album_title": [
      0,
      1,
      2,
      3
    ],
    "sort_album_title_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_song_album_release_artist_lexi": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_album_release_artist_lexi_rev": [
      6,
      4,
      5,
      0,
      1,
      2,
      3
    ],
    "sort_song_album_release_rev_artist_lexi": [
      2,
      3,
      0,
      1,
      4,
      5,
      6
    ],
    "sort_song_album_release_rev_artist_lexi_rev": [
      6,
      4,
      5,
      2,
      3,
      0,
      1
    ],
    "sort_song_album_lexi_artist_lexi": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_album_lexi_artist_lexi_rev": [
      6,
      4,
      5,
      0,
      1,
      2,
      3
    ],
    "sort_song_album_lexi_rev_artist_lexi": [
      2,
      3,
      0,
      1,
      4,
      5,
      6
    ],
    "sort_song_album_lexi_rev_artist_lexi_rev": [
      6,
      4,
      5,
      2,
      3,
      0,
      1
    ],
    "sort_song_lexi": [
      3,
      4,
      0,
      1,
      2,
      6,
      5
    ],
    "sort_song_lexi_rev": [
      5,
      6,
      2,
      1,
      0,
      4,
      3
    ],
    "sort_song_release": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_release_rev": [
      6,
      5,
      4,
      3,
      2,
      1,
      0
    ],
    "sort_song_runtime": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_runtime_rev": [
      6,
      5,
      4,
      3,
      2,
      1,
      0
    ],
    "sort_song_title": [
      0,
      1,
      2,
      4,
      6,
      3,
      5
    ],
    "sort_song_title_rev": [
      5,
      3,
      6,
      4,
      2,
      1,
      0
    ]
  },
  "id": 0
}

Artist

🟑 Incomplete

This API's output may have additions in the future.


A unique "artist" inside your Collection.

Uniqueness is defined by the Artist's name.

Artist objects hold keys to all of their Album's and Song's, acting as a relation link.

The keys inside albums is sorted by Release date.

The keys inside songs is sorted by Track + Disc order.

FieldTypeDescription
namestringThe Artist's name
keyArtist key (unsigned integer)The Artist key associated with this Artist
runtimeunsigned integerThe total runtime of all songs owned by this Artist in seconds
albumsarray of Album keys (unsigned integers)Keys to all Album's owned by this Artist, in release order
songsarray of Song keys (unsigned integers)Keys to all Songs's owned by this Artist, in Album release order, then Song track order

Example

{
  "name": "Artist Name",
  "key": 65,
  "runtime": 7583,
  "albums": [
    255,
    263
  ],
  "songs": [
    2829,
    2832,
    2835,
    2841
  ]
}

Album

🟑 Incomplete

This API's output may have additions in the future.


A unique Album owned by an Artist.

Uniqueness is defined by the Album's title.

Album objects hold keys to all of its Song's, acting as a relation link.

The keys inside songs is sorted by Track + Disc order.

FieldTypeDescription
titlestringThe title of this Album
keyAlbum key (unsigned integer)The Album key associated with this Album
artistArtist key (unsigned integer)The Artist key of the Artist that owns this Album
releasestringRelease date of this Album in YYYY-MM-DD/YYYY-MM/YYYY format, ????-??-?? if unknown
runtimeunsigned integerThe total runtime of this Album in seconds
song_countunsigned integerHow many Song's are in this Album
songsarray of Song keys (unsigned integers)Keys to all of the Song's in this Album, in track order
discsunsigned integerCount of how many "discs" are in this Album, most will be 0
artoptional (maybe null) unsigned integerSize of this Album's art in bytes, null if not found
genreoptional (maybe null) stringGenre of this Album, null if not found

Example

{
  "title": "Album Title",
  "key": 100,
  "artist": 16,
  "release": "2011-07-13",
  "runtime": 2942,
  "song_count": 3,
  "songs": [
    972,
    1024,
    1051,
  ],
  "discs": 0,
  "art": 306410,
  "genre": null
}

Song

🟑 Incomplete

This API's output may have additions in the future.


A Song inside an Album, owned by an Artist.

Song objects hold keys to the Album it is in, acting as a relation link.

FieldTypeDescription
titlestringThe title of this Song
keySong key (unsigned integer)The Song key associated with this Song
albumAlbum key (unsigned integer)The Album key of the Album this Song is from
runtimeunsigned integerThe total runtime of this Song in seconds
sample_rateunsigned integerThe sample rate of this Song in hertz, e.g: 44100
trackoptional (maybe null) unsigned integerTrack number of this Song, null if not found
discoptional (maybe null) unsigned integerDisc number this Song belongs to, null if not found
mimestringAudio MIME type of this Song
extensionstringFile extension of this Song

Example

{
  "title": "Song Title",
  "key": 401,
  "album": 42,
  "runtime": 132,
  "sample_rate": 44100,
  "track": 5,
  "disc": null,
  "mime": "audio/x-flac",
  "extension": "flac"
}

Key

🟒 Stable

This API is stable since festivald v1.0.0.


Common Objects all have an unsigned integer associated with them:

These keys directly map to a given object, and can be used to retrieve them.

In the case of Album art, the Album key doubles as the key (since art belongs to an album), so to access the art of Album 123 in the REST API, you would use:

http://localhost:18425/key/art/123

Key's start at 0 and are unique per object group, meaning there is an Artist 0 key AND Album 0 key AND Song 0 key.

The actual number value of Key's aren't significant, and should be treated as random.

Thus, the songs field in Album won't necessarily be incrementing by 1, e.g, [0, 1, 2, ...]. It could be [0, 6, 112, 3, ...]. Same with Album keys within Artist's.

Where

Key's can be found in multiple JSON-RPC methods, such as map_artist, search_album, etc.

Each object contains its own key within itself as well, and there are links in-between them:

                 Artist_0                       Artist_1
              ______|______                  ______|_________________
             /             \                /             \          \
          Album_13       Album_5         Album_0         Album_4    Album_8
          __|__           __|__           __|__          __|__         \___        
         /     \         /     \         /     \        /     \            \
[Song_5, Song_0, ...] [Song_3, ...]  [Song_76, ...] [Song_45, ...]   [Song_41, ...]
  1. An Artist contains keys leading to Album's
  2. Album's have a key pointing back to the owning Artist, and keys leading to Song's
  3. Song's have a key pointing back to the owning Album

For convenience, all Artist's also have an array of all their Song's.

Why

Key's are a number that represent direct access to a unique Artist/Album/Song.

Think of it as an index into an array (that's what they really are, implemented).

Reasons why key's exist:

  • Accessing objects via a key is faster than with string inputs
  • Storing/sending/parsing integers is faster & cheaper than string's
  • As long as your Collection is stable, the key's are stable
  • Accessing Song's with the same title in the same Album by the same Artist is impossible with string's, however, each one of those Song's will have a unique Key, which it makes it possible to access them that way

Why NOT

Key's can only be relied upon as long as the Collection has not been reset.

When the Collection is reset, it is not guaranteed that the same key will map to the same object. Using map_* and search_* methods as the main way to retrieve information may be more convenient so that Artist names, Album and Song titles can be used as inputs instead.

Example

Let's search for a song that has a title similar to: "hello"

curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search_song","params":{"input":"hello","kind":"top1"}}'

The output gives us back a Song object, which contains some keys:

{
  "jsonrpc": "2.0",
  "result": {
    "songs": [
      {
        "title": "HELLO",
        "key": 15850,   // <--- This is the `Song`'s key
        "album": 737,   // <--- This is the key of the `Album` this `Song` belongs too
        "runtime": 243,
        "sample_rate": 44100,
        "track": 8,
        "disc": 1,
        "mime": "audio/x-flac",
        "extension": "flac"
      }
    ]
  },
  "id": 0
}

We can now use that Album key to get the Album:

curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_album","params":{"key":"737"}}'

And we get the Album object back:

{
  "jsonrpc": "2.0",
  "result": {
    "title": "Hero",
    "key": 737,    // <--- This is the `Album`'s key
    "artist": 196, // <--- This is the key of the `Artist` this `Album` belongs too
    "release": "2001-12-29",
    "runtime": 4676,
    "song_count": 3,
    "songs": [
      15850, // <--- Hey look, it's the original `Song` key
      9771,
      15853
    ],
    "discs": 0,
    "art": 8348685,
    "genre": null
  },
  "id": 0
}

We can now use that Artist key to get the Artist:

curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_artist","params":{"key":"196"}}'

And we get the Artist object back:

{
  "jsonrpc": "2.0",
  "result": {
    "name": "Tac",
    "key": 196, // <--- This is the `Artist`' key
    "runtime": 15636,
    "albums": [
      737, // <--- Hey look, it's the original `Album` key
    ],
    "songs": [
      15850, // <--- Hey look, it's the original `Song` key
      9771,
      15853
    ]
  },
  "id": 0
}

With these keys, you traverse up and down the relational graph.

Entry

🟒 Stable

This API is stable since festivald v1.0.0.


An "absolute" key to:

This object contains all the relational data of a Song, along with its filesystem PATH.

FieldTypeDescription
pathstring (PATH)The PATH of this Song on the filesystem festivald is running on
key_artistArtist key (unsigned integer)The Artist key
key_albumAlbum key (unsigned integer)The Album key
key_songSong key (unsigned integer)This Song's key
artiststringThe Artist name
albumstringThe Album title
songstringThis Song's title

Example

{
  "path": "/home/hinto/Music/song.mp3",
  "key_artist": 0,
  "key_album": 0,
  "key_song": 0,
  "artist": "Artist Name",
  "album": "Album Title",
  "song": "Song Title"
}

Playlist

🟒 Stable

This API is stable since festivald v1.0.0.


Playlist's are objects where

  • The key is the playlist name (string)
  • The value is an array of Entry-like objects, Playlist Entries
FieldTypeDescription
${PLAYLIST_NAME}array of Playlist Entry'sThe name of the playlist as the key, and the Song entries in an array

Playlist Entry

The Entry object in the context of playlists is similar to Entry, except it does not have the path field.

The Playlist Entry takes 2 forms: valid & invalid:

Playlist Entry formMeaning
validThis is a valid Song; it exists within the current Collection
invalidThis Song does NOT exist in the current Collection, although it did in a previous one (it may have been lost in-between Collection resets)

These objects will appear in playlist-related methods, like playlist_full & playlist_single.

Example:

{
  "hello": [ // <--- the playlist name is "hello"
    // This is an "valid" entry.
    // The underlying Song exists in the current Collection.
    {
      "valid": {
        "key_artist": 46,
        "key_album": 168,
        "key_song": 1756,
        "artist": "Artist Name",
        "album": "Album Title",
        "song": "Song Title"
      }
    },
    // This is an "invalid" entry.
    // The underlying Song doesn't exist in Collection anymore.
    {
      "invalid": {
        "artist": "Artist Name",
        "album": "Album Title",
        "song": "Song Title"
      }
    }
  ]
}

valid

The data definition for valid playlist entry types.

Exact same as Entry but does not have path.

FieldTypeDescription
key_artistArtist key (unsigned integer)This entry's Artist key
key_albumAlbum key (unsigned integer)This entry's Album key
key_songSong key (unsigned integer)This entry's Song key
artiststringThe Artist name
albumstringThe Album title
songstringThe Song title

Example:

{
  "key_artist": 46,
  "key_album": 168,
  "key_song": 1762,
  "artist": "Artist Name",
  "album": "Album Title",
  "song": "Song Title"
}

invalid

The data definition for invalid playlist entry types is the same as valid, but with no keys.

FieldTypeDescription
artiststringThe Artist name
albumstringThe Album title
songstringThe Song title

Example:

{
  "artist": "Artist Name",
  "album": "Album Title",
  "song": "Song Title"
}

Validation

Upon a Collection reset, it is not guaranteed that the same Song's will even exist at all.

This is a problem since existing Playlist's may now be referencing Song's that don't exist anymore.

The way festivald handles this is not to delete them, but "mark" those entries as invalid.

These invalid entries will continue to exist indefinitely.

Upon every future Collection reset, if an invalid entry is able to recover (a matching Song file is found with the correct metadata), it will turn back into a valid entry automatically.

JSON-RPC

festivald exposes a JSON-RPC 2.0 API for general state retrieval & signal control.

It can be accessed by sending a HTTP POST request containing a JSON-RPC 2.0 request in the body, to the root endpoint, /.

All method documentation will include:

  • What inputs it needs
  • What output to expect
  • Examples

The title of the section itself is the method name, for example, collection_new is the method name.

All method names, parameter names, and field names are in lower_case_snake_case.

For a quick start on using the JSON-RPC API, see the next section: Quick Start.

Missing resource

If a JSON-RPC method is interacting with an underlying resource and that resource is missing from the filesystem, festivald will not respond to the client with an error, however, it will log an error message on the machine it is running on.

For example, if a queue_add_key_song method is sent, and that Song's underlying PATH is missing/moved/renamed from when the Collection was created:

mv "Song Title" "Song_Title"

festivald will now have a reference to a non-existent PATH and will not be able to find the file, so it will log an error that looks something like:

Audio - PATH error: No such file or directory (os error 2) ... /path/to/unknown/song.mp3

You can re-create the Collection with collection_new to re-link these PATHs.

Example JSON-RPC 2.0 request:

{
  "jsonrpc": "2.0",   // JSON-RPC version. MUST be exactly "2.0"
  "method": "method", // A string of the method name
  "param": null,      // Optional parameters needed by the method
  "id": 0,            // An ID, MUST be a String, Number, or NULL value if included
}

Example Shell script for sending a request:

IP=localhost             # ip of festivald
PORT=18425               # port of festivald
METHOD='previous'        # the method to call
PARAMS='{"threshold":3}' # the parameters of the method
ID=0                     # the ID of this request

# Send JSON-RPC request to goto the previous song
# (or reset the current, if more than 3 seconds has passed).
curl \
    http://$IP:$PORT \
    -d '{"jsonrpc":"2.0","id":$ID,"method":"'$METHOD'","params":'$PARAMS'}'

Example JSON-RPC 2.0 SUCCESSFUL response:

{
  "jsonrpc": "2.0", // JSON-RPC version. Will always be exactly "2.0"
  "result": {       // The field containing the result of the SUCCESSFUL response
    // This can contain fields that
    // are nested arbitrarily deep.
    // Although, most times they
    // will be simple "key": value
    // pairs.
  },
  "id": 0, // The ID associated with the client
}

Example JSON-RPC 2.0 FAILED response:

{
  "jsonrpc": "2.0", // JSON-RPC version. Will always be exactly "2.0"
  "error": {        // The field containing the result of the FAILED response
    "code": -32601, // A number that indicates the error type that occurred
    "message": "",  // A string providing a short description of the error
    "data": null,   // An OPTIONAL field containing extra data about the error
  },
  "id": 0, // The ID associated with the client
}

Parameters

For methods with optional parameters, the field(s) can be omitted:

festival-cli queue_add_key_artist --key 0 --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_artist","params":{"key":0,"append":"back","clear":false}}'

The exception is collection_new, since it has a single optional field. You must specify it (even if null).

curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_new","params":{"paths":null}}'

JSON-RPC Quick Start

A quick start to using festivald's JSON-RPC 2.0 API.

Create the Collection and start playing an Artist

  1. First, scan the default Music directory on festivald's filesystem, and create a Collection with collection_new:
festival-cli collection_new
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_new","params":{"paths":null}}'
  1. Add the Artist "LUCKY TAPES" to the queue with queue_add_map_artist:
festival-cli queue_add_map_artist --artist "LUCKY TAPES"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_artist","params":{"artist":"LUCKY TAPES"}}'
  1. Start playing with play:
festival-cli play
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"play"}'

View state of current audio playback with state_audio

festival-cli state_audio
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_audio"}'

Set the volume to 10% with volume

festival-cli volume --volume 10
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"volume","params":{"volume":10}}'

View the current Album with current_album

festival-cli current_album
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_album"}'

Clear the queue and stop playback with stop

festival-cli stop
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"stop"}'

Create and add an Artist to a playlist with playlist_add_map_artist

festival-cli playlist_add_map_artist --playlist "Playlist Name" --artist "Artist Name" --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_map_artist","params":{"playlist":"Playlist Name","artist":"Artist Name","append":"back","clear":false}}'

Collection

Methods related for creating and viewing various info about the Collection.

collection_new

🟑 Incomplete

This API's output may have additions in the future.


Create a new Collection (and replace the current one).

While this method is in progress, other JSON-RPC/REST requests will be rejected.

festivald will respond with some stats when the Collection reset has finished.

Inputs

FieldTypeDescription
pathsoptional (maybe-null) array of PATHsAn array of filesystem PATHs to scan for the new Collection. These must be absolute PATHs on the system festivald is running on, not PATHs on the client. If null is provided, the default Music directory will be used.

Outputs

FieldTypeDescription
timefloatHow many seconds it took festivald to reset AND respond
emptybooleanIf the Collection does NOT have any Artist's, Album's, or Song's
timestampunsigned integerThe UNIX timestamp of when this Collection was created
count_artistunsigned integerHow many unique Artist's there are in this Collection
count_albumunsigned integerHow many unique Album's there are in this Collection
count_songunsigned integerHow many unique Song's there are in this Collection
count_artunsigned integerHow much unique Album art there are in this Collection

Example Request 1

Use default Music PATH.

festival-cli collection_new
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_new","params":{"paths":null}}'

Example Request 2

Use the PATH /home/user/Music/collection on festivald's filesystem.

festival-cli collection_new --paths "/home/user/Music/collection"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_new","params":{"paths":["/home/user/Music/collection"]}}'

Example Request 3

Windows PATH works too if \ is escaped (and if festivald is running on Windows).

festival-cli collection_new --paths "C:\\Users\\User\\Music\\collection"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_new","params":{"paths":["C:\\Users\\User\\Music\\collection"]}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "time": 0.462621988,
    "empty": false,
    "timestamp": 1690579397,
    "count_artist": 195,
    "count_album": 825,
    "count_song": 8543,
    "count_art": 824
  },
  "id": 0
}

collection_brief

🟑 Incomplete

This API's output may have additions in the future.


Retrieve some brief metadata about the current Collection.

This method is a subset of the collection_full method.

Inputs

None

Outputs

FieldTypeDescription
emptybooleanIf the Collection does NOT have any Artist's, Album's, or Song's
timestampunsigned integerThe UNIX timestamp of when this Collection was created
count_artistunsigned integerHow many unique Artist's there are in this Collection
count_albumunsigned integerHow many unique Album's there are in this Collection
count_songunsigned integerHow many unique Song's there are in this Collection
count_artunsigned integerHow much unique Album art there are in this Collection

Example Request

festival-cli collection_brief
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_brief"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "empty": false,
    "timestamp": 1690410052,
    "count_artist": 195,
    "count_album": 825,
    "count_song": 8543,
    "count_art": 824
  },
  "id": 0
}

collection_full

🟑 Incomplete

This API's output may have additions in the future.


Retrieve full metadata about the current Collection.

Inputs

None

Outputs

The output of this method will be a full Collection object.

Example Request

festival-cli collection_full
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_full"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "empty": false,
    "timestamp": 1691018515,
    "count_artist": 3,
    "count_album": 4,
    "count_song": 7,
    "count_art": 4,
    "artists": [
      {
        "name": "artist_1",
        "key": 0,
        "runtime": 4,
        "albums": [
          0,
          1
        ],
        "songs": [
          0,
          1,
          2,
          3
        ]
      },
      {
        "name": "artist_2",
        "key": 1,
        "runtime": 2,
        "albums": [
          2
        ],
        "songs": [
          4,
          5
        ]
      },
      {
        "name": "artist_3",
        "key": 2,
        "runtime": 1,
        "albums": [
          3
        ],
        "songs": [
          6
        ]
      }
    ],
    "albums": [
      {
        "title": "album_1",
        "key": 0,
        "artist": 0,
        "release": "2018-04-25",
        "runtime": 2,
        "song_count": 2,
        "songs": [
          0,
          1
        ],
        "discs": 0,
        "art": 10239,
        "genre": null
      },
      {
        "title": "album_2",
        "key": 1,
        "artist": 0,
        "release": "2018-04-25",
        "runtime": 2,
        "song_count": 2,
        "songs": [
          2,
          3
        ],
        "discs": 0,
        "art": 10239,
        "genre": null
      },
      {
        "title": "album_3",
        "key": 2,
        "artist": 1,
        "release": "2018-04-25",
        "runtime": 2,
        "song_count": 2,
        "songs": [
          4,
          5
        ],
        "discs": 1,
        "art": 10239,
        "genre": null
      },
      {
        "title": "album_4",
        "key": 3,
        "artist": 2,
        "release": "2018-04-25",
        "runtime": 1,
        "song_count": 1,
        "songs": [
          6
        ],
        "discs": 0,
        "art": 10239,
        "genre": null
      }
    ],
    "songs": [
      {
        "title": "mp3",
        "key": 0,
        "album": 0,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "mp3",
        "key": 1,
        "album": 0,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 2,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "mp3",
        "key": 2,
        "album": 1,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "flac",
        "key": 3,
        "album": 1,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 2,
        "disc": 2,
        "mime": "audio/x-flac",
        "extension": "flac"
      },
      {
        "title": "m4a",
        "key": 4,
        "album": 2,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": null,
        "mime": "audio/m4a",
        "extension": "m4a"
      },
      {
        "title": "song_6",
        "key": 5,
        "album": 2,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 2,
        "disc": 2,
        "mime": "audio/ogg",
        "extension": "ogg"
      },
      {
        "title": "mp3",
        "key": 6,
        "album": 3,
        "runtime": 1,
        "sample_rate": 48000,
        "track": 1,
        "disc": 2,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ],
    "sort_artist_lexi": [
      0,
      1,
      2
    ],
    "sort_artist_lexi_rev": [
      2,
      1,
      0
    ],
    "sort_artist_album_count": [
      1,
      2,
      0
    ],
    "sort_artist_album_count_rev": [
      0,
      2,
      1
    ],
    "sort_artist_song_count": [
      2,
      1,
      0
    ],
    "sort_artist_song_count_rev": [
      0,
      1,
      2
    ],
    "sort_artist_runtime": [
      2,
      1,
      0
    ],
    "sort_artist_runtime_rev": [
      0,
      1,
      2
    ],
    "sort_artist_name": [
      0,
      1,
      2
    ],
    "sort_artist_name_rev": [
      2,
      1,
      0
    ],
    "sort_album_release_artist_lexi": [
      0,
      1,
      2,
      3
    ],
    "sort_album_release_artist_lexi_rev": [
      3,
      2,
      0,
      1
    ],
    "sort_album_release_rev_artist_lexi": [
      1,
      0,
      2,
      3
    ],
    "sort_album_release_rev_artist_lexi_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_lexi_artist_lexi": [
      0,
      1,
      2,
      3
    ],
    "sort_album_lexi_artist_lexi_rev": [
      3,
      2,
      0,
      1
    ],
    "sort_album_lexi_rev_artist_lexi": [
      1,
      0,
      2,
      3
    ],
    "sort_album_lexi_rev_artist_lexi_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_lexi": [
      0,
      1,
      2,
      3
    ],
    "sort_album_lexi_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_release": [
      0,
      1,
      2,
      3
    ],
    "sort_album_release_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_album_runtime": [
      3,
      0,
      1,
      2
    ],
    "sort_album_runtime_rev": [
      2,
      1,
      0,
      3
    ],
    "sort_album_title": [
      0,
      1,
      2,
      3
    ],
    "sort_album_title_rev": [
      3,
      2,
      1,
      0
    ],
    "sort_song_album_release_artist_lexi": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_album_release_artist_lexi_rev": [
      6,
      4,
      5,
      0,
      1,
      2,
      3
    ],
    "sort_song_album_release_rev_artist_lexi": [
      2,
      3,
      0,
      1,
      4,
      5,
      6
    ],
    "sort_song_album_release_rev_artist_lexi_rev": [
      6,
      4,
      5,
      2,
      3,
      0,
      1
    ],
    "sort_song_album_lexi_artist_lexi": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_album_lexi_artist_lexi_rev": [
      6,
      4,
      5,
      0,
      1,
      2,
      3
    ],
    "sort_song_album_lexi_rev_artist_lexi": [
      2,
      3,
      0,
      1,
      4,
      5,
      6
    ],
    "sort_song_album_lexi_rev_artist_lexi_rev": [
      6,
      4,
      5,
      2,
      3,
      0,
      1
    ],
    "sort_song_lexi": [
      3,
      4,
      0,
      1,
      2,
      6,
      5
    ],
    "sort_song_lexi_rev": [
      5,
      6,
      2,
      1,
      0,
      4,
      3
    ],
    "sort_song_release": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_release_rev": [
      6,
      5,
      4,
      3,
      2,
      1,
      0
    ],
    "sort_song_runtime": [
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ],
    "sort_song_runtime_rev": [
      6,
      5,
      4,
      3,
      2,
      1,
      0
    ],
    "sort_song_title": [
      0,
      1,
      2,
      4,
      6,
      3,
      5
    ],
    "sort_song_title_rev": [
      5,
      3,
      6,
      4,
      2,
      1,
      0
    ]
  },
  "id": 0
}

collection_brief_artists

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve an array of every Artist name in the current Collection.

The returned array of string's is in lexicographical order.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Artist's there are
artistsarray of string'sThe title of every Artist in the Collection

Example Request

festival-cli collection_brief_artists
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_brief_artists"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "artists": [
      "aaa",
      "bbb",
      "ccc"
    ]
  },
  "id": 0
}

collection_brief_albums

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve an array of every Album title in the current Collection.

The returned array of string's is in lexicographical order.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Album's there are
albumsarray of string'sThe title of every Album in the Collection

Example Request

festival-cli collection_brief_albums
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_brief_albums"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "albums": [
      "aaa",
      "bbb",
      "ccc"
    ]
  },
  "id": 0
}

collection_brief_songs

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve an array of every Song title in the current Collection.

The returned array of string's is in lexicographical order.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Song's there are
songsarray of string'sThe title of every Song in the Collection

Example Request

festival-cli collection_brief_songs
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_brief_songs"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "songs": [
      "aaa",
      "bbb",
      "ccc"
    ]
  },
  "id": 0
}

collection_full_artists

🟑 Incomplete

This API's output may have additions in the future.


Retrieve an array of every Artist object in the current Collection.

The returned array is in incrementing key order, as in:

Artist 0,
Artist 1,
Artist 2,

[... etc ...]

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Artist's there are
artistsarray of Artist objectsEvery Artist in the Collection

Example Request

festival-cli collection_full_artists
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_full_artists"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 1,
    "artists": [
      {
        "name": "Artist Name",
        "key": 0,
        "runtime": 3561,
        "albums": [
          0,
          1
        ],
        "songs": [
          0,
          1,
          5,
          20,
          22,
          23
        ]
      }
    ]
  },
  "id": 0
}

collection_full_albums

🟑 Incomplete

This API's output may have additions in the future.


Retrieve an array of every Album object in the current Collection.

The returned array is in incrementing key order, as in:

Album 0,
Album 1,
Album 2,

[... etc ...]

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Album's there are
albumsarray of Album objectsEvery Album in the Collection

Example Request

festival-cli collection_full_albums
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_full_albums"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "albums": [
      {
        "title": "Album Title",
        "key": 0,
        "artist": 0,
        "release": "2019",
        "runtime": 1385,
        "song_count": 4,
        "songs": [
          0,
          1,
          7,
          11
        ],
        "discs": 0,
        "art": 525016,
        "genre": null
      },
      {
        "title": "Album Title 2",
        "key": 1,
        "artist": 0,
        "release": "2019",
        "runtime": 3605,
        "song_count": 4,
        "songs": [
          12,
          16,
          22,
          23
        ],
        "discs": 0,
        "art": 628931,
        "genre": null
      }
    ]
  },
  "id": 0
}

collection_full_songs

🟑 Incomplete

This API's output may have additions in the future.


Retrieve an array of every Song object in the current Collection.

The returned array is in incrementing key order, as in:

Song 0,
Song 1,
Song 2,

[... etc ...]

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Song's there are
songsarray of Song objectsEvery Song in the Collection

Example Request

festival-cli collection_full_songs
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_full_songs"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "songs": [
      {
        "title": "Song Title 1",
        "key": 0,
        "album": 0,
        "runtime": 371,
        "sample_rate": 96000,
        "track": 1,
        "disc": 1,
        "mime": "audio/x-flac",
        "extension": "flac"
      },
      {
        "title": "Song Title 2",
        "key": 1,
        "album": 0,
        "runtime": 348,
        "sample_rate": 96000,
        "track": 2,
        "disc": 1,
        "mime": "audio/x-flac",
        "extension": "flac"
      }
    ]
  },
  "id": 0
}

collection_entries

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve an array of Entry's of every Song in the current Collection.

The returned array is in incrementing key order, as in:

Entry 0 (Song key 0),
Entry 1 (Song key 1),
Entry 2 (Song key 2),

[... etc ...]

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Entry's (Song's) there are
entriesarray of Entry objectsEvery Song in the Collection (in Entry form)

Example Request

festival-cli collection_entries
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_entries"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": [
    {
      "path": "/home/hinto/festival/assets/audio/song_1.mp3",
      "key_artist": 0,
      "key_album": 0,
      "key_song": 0,
      "artist": "artist_1",
      "album": "album_1",
      "song": "mp3"
    },
    {
      "path": "/home/hinto/festival/assets/audio/song_2.mp3",
      "key_artist": 0,
      "key_album": 0,
      "key_song": 1,
      "artist": "artist_1",
      "album": "album_1",
      "song": "mp3"
    },
    {
      "path": "/home/hinto/festival/assets/audio/song_3.mp3",
      "key_artist": 0,
      "key_album": 1,
      "key_song": 2,
      "artist": "artist_1",
      "album": "album_2",
      "song": "mp3"
    },
    {
      "path": "/home/hinto/festival/assets/audio/song_4.flac",
      "key_artist": 0,
      "key_album": 1,
      "key_song": 3,
      "artist": "artist_1",
      "album": "album_2",
      "song": "flac"
    },
    {
      "path": "/home/hinto/festival/assets/audio/song_5.m4a",
      "key_artist": 1,
      "key_album": 2,
      "key_song": 4,
      "artist": "artist_2",
      "album": "album_3",
      "song": "m4a"
    },
    {
      "path": "/home/hinto/festival/assets/audio/song_6.ogg",
      "key_artist": 1,
      "key_album": 2,
      "key_song": 5,
      "artist": "artist_2",
      "album": "album_3",
      "song": "song_6"
    },
    {
      "path": "/home/hinto/festival/assets/audio/song_7.mp3",
      "key_artist": 2,
      "key_album": 3,
      "key_song": 6,
      "artist": "artist_3",
      "album": "album_4",
      "song": "mp3"
    }
  ],
  "id": 0
}

collection_health

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve the health of the current Collection.

This method tells you how many Song's referenced by the current Collection have a missing underlying file, i.e, there is no file at the PATH the Collection points to for a particular Song.

Missing Song's will be returned in Entry form.

The returned array of missing Entry's is in incrementing Song key order, as in:

Entry 10 (Song key 10),
Entry 13 (Song key 13),
Entry 75 (Song key 75),
Entry 76 (Song key 76),

[... etc ...]

Inputs

None

Outputs

FieldTypeDescription
all_okbooleanIf the underlying file for every single Song exists, this is true, else if even 1 is missing, it is false
song_lenunsigned integerThe total count of Song's in the Collection
missing_lenunsigned integerThe total count of Song's with missing underlying files
missingarray of Entry objectsAn array of each Song that is missing, in Entry object form

Example Request

festival-cli collection_health
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_health"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "all_ok": false,
    "song_len": 24,
    "missing_len": 2,
    "missing": [
      {
        "path": "/home/hinto/Music/song.flac",
        "key_artist": 0,
        "key_album": 0,
        "key_song": 0,
        "artist": "Artist Name",
        "album": "Album Title",
        "song": "Song Title"
      },
      {
        "path": "/home/hinto/Music/song2.flac",
        "key_artist": 1,
        "key_album": 1,
        "key_song": 1,
        "artist": "Artist Name 2",
        "album": "Album Title 2",
        "song": "Song Title 2"
      }
    ]
  },
  "id": 0
}

collection_perf

🟒 Stable

This API is stable since festivald v1.0.0.


View some performance stats about the latest Collection reset.

Inputs

None

Outputs

FieldTypeDescription
bytesunsigned integerTotal size of the Collection (collection.bin only, not audio/art) in bytes
userfloatCollection creation time in seconds, for the user
sysfloatCollection creation time in seconds, for the system festivald is running on

Example Request

festival-cli collection_perf
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_perf"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "bytes": 2554823,
    "user": 0.45682073,
    "sys": 0.48661286
  },
  "id": 0
}

collection_resource_size

🟒 Stable

This API is stable since festivald v1.0.0.


View the size of the current Collection's underlying resources (audio files and art).

The output of this method reflects the live audio file size, not the one at the time of the Collection creation. For example, if an underlying audio file is changed:

my_song_file.flac (5MB) -> my_song_file.flac (33MB)

Then this method will reflect that change.

However, Art is cached by festivald and only updated upon a Collection reset.

Inputs

None

Outputs

FieldTypeDescription
audiounsigned integerTotal size of the Collection's underlying audio files in bytes
artunsigned integerTotal size of the Collection's underlying Album art in bytes

Example Request

festival-cli collection_resource_size
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"collection_resource_size"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "audio": 315060491209,
    "art": 877030803
  },
  "id": 0
}

Daemon

These methods are for retrieving/modifying festivald in "system"-related ways.

daemon_config

πŸ”΄ Unstable

This API's output may be changed in the future.


Retrieve the active configuration of festivald.

The output is almost a mirror of the configuration file.

See the Config chapter to see the full description of these fields.

The reason why this method is πŸ”΄ Unstable is because it will output all JSON-RPC methods & REST resources, even πŸ”΄ Unstable ones, which may not exist in the future.

Inputs

None

Outputs

FieldType
ipstring (IPv4 address)
portunsigned integer
max_connectionsoptional (maybe-null) unsigned integer
exclusive_ipsoptional (maybe-null) array of strings (IPv4 addresses)
sleep_on_failoptional (maybe-null) unsigned integer
collection_pathsarray of strings (PATHs)
tlsboolean
certificateoptional (maybe-null) string (PATH)
keyoptional (maybe-null) string (PATH)
restboolean
docsboolean
direct_downloadboolean
filename_separatorstring
log_levelstring, one of OFF, ERROR, WARN, INFO, DEBUG, ERROR
watchboolean
cache_cleanboolean
cache_timeunsigned integer
restore_audio_stateboolean
media_controlsboolean
authorizationboolean
confirm_no_tls_authboolean
no_auth_rpcoptional (maybe-null) array of JSON-RPC Method names
no_auth_restoptional (maybe-null) array of REST Resource names
no_auth_docsboolean

Example Request

festival-cli daemon_config
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_config"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "ip": "127.0.0.1",
    "port": 18425,
    "max_connections": null,
    "exclusive_ips": null,
    "sleep_on_fail": 3000,
    "collection_paths": [
      "/home/hinto/Music"
    ],
    "tls": true,
    "certificate": "/home/hinto/festival/assets/tls/cert.pem",
    "key": "/home/hinto/festival/assets/tls/key.pem",
    "rest": true,
    "docs": true,
    "direct_download": false,
    "filename_separator": " - ",
    "log_level": "TRACE",
    "watch": true,
    "cache_clean": true,
    "cache_time": 3600,
    "restore_audio_state": true,
    "media_controls": true,
    "authorization": true,
    "confirm_no_tls_auth": false,
    "no_auth_rpc": [
      "toggle"
    ],
    "no_auth_rest": [
      "song"
    ],
    "no_auth_docs": true
  },
  "id": 0
}

daemon_methods

πŸ”΄ Unstable

This API's output may be changed in the future.


Retrieve all JSON-RPC methods this festivald knows about.

The reason why this method is πŸ”΄ Unstable is because it will output all methods, even πŸ”΄ Unstable ones, which may not exist in the future.

Ordering of the method names should not be relied upon.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerTotal amount of methods
methodsarray of string'sThe names of all the methods this festivald knows about

Example Request

festival-cli daemon_methods
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_methods"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 109,
    "methods": [
      "collection_new",
      "collection_brief",
      "collection_full",
      "collection_brief_artists",
      "collection_brief_albums",
      "collection_brief_songs",
      "collection_full_artists",
      "collection_full_albums",
      "collection_full_songs",
      "collection_entries",
      "collection_perf",
      "collection_health",
      "collection_resource_size",
      "daemon_config",
      "daemon_methods",
      "daemon_no_auth_rpc",
      "daemon_no_auth_rest",
      "daemon_remove_cache",
      "daemon_save",
      "daemon_seen_ips",
      "daemon_shutdown",
      "daemon_state",
      "state_audio",
      "state_queue_key",
      "state_queue_song",
      "state_queue_entry",
      "state_playing",
      "state_repeat",
      "state_runtime",
      "state_volume",
      "key_artist",
      "key_album",
      "key_song",
      "key_entry",
      "key_artist_albums",
      "key_artist_songs",
      "key_artist_entries",
      "key_album_artist",
      "key_album_songs",
      "key_album_entries",
      "key_song_artist",
      "key_song_album",
      "key_other_albums",
      "key_other_songs",
      "key_other_entries",
      "map_artist",
      "map_album",
      "map_song",
      "map_entry",
      "map_artist_albums",
      "map_artist_songs",
      "map_artist_entries",
      "map_album_songs",
      "map_album_entries",
      "current_artist",
      "current_album",
      "current_song",
      "current_entry",
      "rand_artist",
      "rand_album",
      "rand_song",
      "rand_entry",
      "search",
      "search_artist",
      "search_album",
      "search_song",
      "search_entry",
      "toggle",
      "play",
      "pause",
      "next",
      "stop",
      "previous",
      "clear",
      "seek",
      "skip",
      "back",
      "shuffle",
      "repeat",
      "volume",
      "volume_up",
      "volume_down",
      "queue_add_key_artist",
      "queue_add_key_album",
      "queue_add_key_song",
      "queue_add_map_artist",
      "queue_add_map_album",
      "queue_add_map_song",
      "queue_add_rand_artist",
      "queue_add_rand_album",
      "queue_add_rand_song",
      "queue_add_rand_entry",
      "queue_add_playlist",
      "queue_set_index",
      "queue_remove_range",
      "playlist_new",
      "playlist_remove",
      "playlist_clone",
      "playlist_get_index",
      "playlist_remove_index",
      "playlist_add_key_artist",
      "playlist_add_key_album",
      "playlist_add_key_song",
      "playlist_add_map_artist",
      "playlist_add_map_album",
      "playlist_add_map_song",
      "playlist_single",
      "playlist_brief",
      "playlist_full"
    ]
  },
  "id": 0
}

daemon_no_auth_rpc

πŸ”΄ Unstable

This API's output may be changed in the future.


Retrieve all JSON-RPC methods this festivald allows without authorization, set in the no_auth_rpc option

The reason why this method is πŸ”΄ Unstable is because it will output all methods, even πŸ”΄ Unstable ones, which may not exist in the future.

Ordering of the method names should not be relied upon.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerTotal amount of methods
rpcarray of string'sThe names of all the methods this festivald allows without authorization

Example Request

festival-cli daemon_no_auth_rpc
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_no_auth_rpc"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "rpc": [
      "collection_brief_artists",
      "key_artist_entries",
      "search_album"
    ]
  },
  "id": 0
}

daemon_no_auth_rest

πŸ”΄ Unstable

This API's output may be changed in the future.


Retrieve all REST resources this festivald allows without authorization, set in the no_auth_rest option

The reason why this method is πŸ”΄ Unstable is because it will output all REST resources, even πŸ”΄ Unstable ones, which may not exist in the future.

Ordering of the resource names should not be relied upon.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerTotal amount of methods
restarray of string'sThe names of all the REST resources this festivald allows without authorization

Example Request

festival-cli daemon_no_auth_rest
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_no_auth_rest"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "rest": [
      "song",
      "art"
    ]
  },
  "id": 0
}

daemon_remove_cache

🟒 Stable

This API is stable since festivald v1.0.0.


Remove all the cached REST resource files on disk.

Warning: If there is a connection currently using this cache, it will error.

Inputs

None

Outputs

The output is an un-named array containing:

FieldTypeDescription
pathstring (PATH)A file that was removed
bytesunsigned integerHow many bytes that file was

Example Request

festival-cli daemon_remove_cache
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_remove_cache"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": [
    {
      "path": "/home/hinto/.cache/festival/daemon/zip/artist/Artist Name.zip"
      "bytes": 345673
    },
    {
      "path": "/home/hinto/.cache/festival/daemon/zip/album/Album Title.zip"
      "bytes": 345673
    }
  ],
  "id": 0
}

daemon_save

🟑 Incomplete

This API's output may have additions in the future.


Save festivald data to disk.

Currently this saves:

The Collection is always saved automatically after creation.

Inputs

None

Outputs

null if everything went ok.

Example Request

festival-cli daemon_save
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_save"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

daemon_seen_ips

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve an array of the IP addresses festivald has seen.

Inputs

None

Outputs

The output is an un-named array containing:

FieldTypeDescription
ipstring (IPv4 address)IP address festivald has seen
countunsigned integerHow many connections this IP has made to festivald

Example Request

festival-cli daemon_seen_ips
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_seen_ips"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": [
    {
      "ip": "127.0.0.1",
      "count": 14
    },
    {
      "ip": "192.168.2.1",
      "count": 2
    }
  ],
  "id": 0
}

daemon_shutdown

🟑 Incomplete

This API's output may have additions in the future.


Send a shutdown signal to festivald.

festivald will:

Then shutdown.

Inputs

None

Outputs

FieldTypeDescription
uptimeunsigned integerUptime of festivald in seconds
uptime_readablestringUptime of festivald in human-readable time (60 is 1 minute)
total_requestsunsigned integerTotal amount of requests festivald has received since starting
total_connectionsunsigned integerTotal amount of connections festivald has received since starting

Example Request

festival-cli daemon_shutdown
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_shutdown"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "uptime": 4,
    "uptime_readable": "4 seconds",
    "total_requests": 1,
    "total_connections": 1
  },
  "id": "festival-cli"
}

daemon_state

🟑 Incomplete

This API's output may have additions in the future.


Retrieve state about the status of festivald itself.

Inputs

None

Outputs

FieldTypeDescription
uptimeunsigned integerUptime of festivald in seconds
uptime_readablestringUptime of festivald in human-readable time (60 is 1 minute)
savingbooleanIf festivald is currently saving a recently created Collection to disk
total_requestsunsigned integerTotal amount of requests festivald has received since starting
total_connectionsunsigned integerTotal amount of connections festivald has received since starting
current_connectionsunsigned integerAmount of open connections festivald currently has
restbooleanIf this festivald's REST API is enabled
docsbooleanIf this festivald's documentation serving is enabled
direct_downloadbooleanIf this festivald's REST API has direct_download enabled
authorizationbooleanIf this festivald has authorization enabled
versionstringSemantic version of this festivald
commitstringGit commit of this festivald
osstringThe OS this festivald was built for

Example Request

festival-cli search_daemon
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"daemon_state"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "uptime": 43,
    "uptime_readable": "43 seconds",
    "saving": false,
    "total_requests": 1447,
    "total_connections": 297,
    "current_connections": 3,
    "rest": true,
    "docs": true,
    "direct_download": false,
    "authorization": false,
    "version": "v1.0.0",
    "commit": "ae086becca9a603b53ded80de870794858c272d0",
    "os": "Linux x64"
  },
  "id": 0
}

State Retrieval

These methods are for retrieving state (mostly audio state), and do not mutate any part of the system.

state_audio

🟑 Incomplete

This API's output may have additions in the future.


Retrieve the current audio state.

Inputs

None

Outputs

FieldTypeDescription
queuearray of Song keys (unsigned integers)Array of Song keys that are in the queue, in order of what will be played next
queue_idxoptional (maybe-null) unsigned integerThe queue index festivald is currently on, null if no Song is set
playingbooleanIf festivald is currently playing
song_keyoptional (maybe-null) Song key (unsigned integer)The key of current Song, null if no Song is set
elapsedunsigned integerElapsed runtime of current Song in seconds
runtimeunsigned integerTotal runtime of current Song in seconds
repeatstring, one of song, queue, or offAudio repeat behavior. song means the Song will repeat after ending, queue means the whole queue will repeat after ending, off means the queue will be cleared and playback will stop when ending
volumeunsigned integer in between 0..100The current volume level
songoptional (maybe-null) Song objectThe current Song as an object, null if no Song is set

Example Request

festival-cli state_audio
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_audio"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "queue": [
      14
    ],
    "queue_len": 1,
    "queue_idx": 0,
    "playing": false,
    "song_key": 14,
    "elapsed": 0,
    "runtime": 349,
    "repeat": "off",
    "volume": 25,
    "song": {
      "title": "い぀か",
      "key": 14,
      "album": 9,
      "runtime": 349,
      "sample_rate": 44100,
      "track": 1,
      "disc": 1,
      "mime": "audio/x-flac",
      "extension": "flac"
    }
  },
  "id": 0
}

state_queue_key

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve state about the queue.

This returns the queue as Song key's.

Returned key's are in order of what will be played next.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerLength of the queue
keysarray of Song keys (unsigned integers)Array of the queue's Song's as keys

Example Request

festival-cli state_queue_key
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_queue_key"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 5,
    "keys": [
      2896,
      2899,
      2904,
      2906,
      2911
    ]
  },
  "id": 0
}

state_queue_song

🟑 Incomplete

This API's output may have additions in the future.


Retrieve state about the queue.

This returns the queue as full Song objects.

Returned Song's are in order of what will be played next.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerLength of the queue
songsarray of Song objectsArray of the queue's Song's

Example Request

festival-cli state_queue_song
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_queue_song"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "songs": [
      {
        "title": "SUNFLOWER",
        "key": 2539,
        "album": 237,
        "runtime": 252,
        "sample_rate": 44100,
        "track": 1,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "BEST FRIEND",
        "key": 2517,
        "album": 237,
        "runtime": 262,
        "sample_rate": 44100,
        "track": 2,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ]
  },
  "id": 0
}

state_queue_entry

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve state about the queue.

This is the same as state_queue except it returns Entry's instead of Song's.

Returned Entry's are in order of what will be played next.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerLength of the queue
entriesarray of Entry objectsArray of the queue's Song's, in Entry form

Example Request

festival-cli state_queue_entry
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_queue_entry"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "entries": [
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
        "key_artist": 65,
        "key_album": 237,
        "key_song": 2539,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      },
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/BEST FRIEND.mp3",
        "key_artist": 65,
        "key_album": 237,
        "key_song": 2517,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "BEST FRIEND"
      }
    ]
  },
  "id": 0
}

state_playing

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve playback status.

Inputs

None

Outputs

FieldTypeDescription
playingbooleanAre we currently playing?

Example Request

festival-cli state_playing
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_playing"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "playing": true
  },
  "id": 0
}

state_repeat

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve the currently set repeat mode.

Inputs

None

Outputs

FieldTypeDescription
modestring, one of off, song, queueThe currently set repeat mode. off mean repeat is off, song means Song repeating, queue means queue repeating.

Example Request

festival-cli state_repeat
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_repeat"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "mode": "off"
  },
  "id": 0
}

state_runtime

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve the elapsed runtime & total runtime of the currently set Song.

This will return 0 values (0:00) if there is no Song set.

Inputs

None

Outputs

FieldTypeDescription
elapsedunsigned integerElapsed runtime of current Song in seconds
runtimeunsigned integerTotal runtime of current Song in seconds
elapsed_readablestringHuman-readable version of elapsed (5 would be 0:05)
runtime_readablestringHuman-readable version of runtime (60 would be 1:00)

Example Request

festival-cli state_runtime
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_runtime"}'

Example Response 1

Song is set:

{
  "jsonrpc": "2.0",
  "result": {
    "elapsed": 12,
    "runtime": 125,
    "elapsed_readable": "0:12",
    "runtime_readable": "2:05"
  },
  "id": 0
}

Example Response 2

Song is not set:

{
  "jsonrpc": "2.0",
  "result": {
    "elapsed": 0,
    "runtime": 0,
    "elapsed_readable": "0:00",
    "runtime_readable": "0:00"
  },
  "id": 0
}

state_volume

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve the current volume level.

Inputs

None

Outputs

FieldTypeDescription
volumeunsigned integer in between 0..100The current volume level

Example Request

festival-cli state_volume
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"state_volume"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "volume": 25
  },
  "id": 0
}

Key

Use key's to retrieve various Common Objects.

If the key is invalid, a JSON-RPC error will be returned.

To use regular string's as input instead (Artist name, Album title, Song title, etc), see Map.

key_artist

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist key, retrieve an Artist.

Inputs

FieldTypeDescription
keyArtist key (unsigned integer)See Key

Outputs

FieldTypeDescription
artistArtist objectSee Artist

Example Request

festival-cli key_artist --key 65
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_artist","params":{"key":65}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artist": {
      "name": "Rex Orange County",
      "key": 65,
      "runtime": 7583,
      "albums": [
        237
      ],
      "songs": [
        2800,
        2803,
        2809
      ]
    }
  },
  "id": 0
}

key_album

🟑 Incomplete

This API's output may have additions in the future.


Input an Album key, retrieve an Album.

Inputs

FieldTypeDescription
keyAlbum key (unsigned integer)See Key

Outputs

FieldTypeDescription
albumAlbum objectSee Album

Example Request

festival-cli key_album --key 237
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_album","params":{"key":237}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "album": {
      "title": "RAINBOW",
      "key": 237,
      "artist": 65,
      "release": "????-??-??",
      "runtime": 1090,
      "song_count": 6,
      "songs": [
        2594,
        2540,
        2600,
        2496,
        2557,
        2500
      ],
      "discs": 0,
      "art": 7753,
      "genre": null
    }
  },
  "id": 0
}

key_song

🟑 Incomplete

This API's output may have additions in the future.


Input a Song key, retrieve a Song.

Inputs

FieldTypeDescription
keySong key (unsigned integer)See Key

Outputs

FieldTypeDescription
songSong objectSee Song

Example Request

festival-cli key_song --key 2594
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_song","params":{"key":2594}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "song": {
      "title": "SUNFLOWER",
      "key": 2594,
      "album": 237,
      "runtime": 252,
      "sample_rate": 44100,
      "track": 1,
      "disc": null,
      "mime": "audio/mpeg",
      "extension": "mp3"
    }
  },
  "id": 0
}

key_entry

🟒 Stable

This API is stable since festivald v1.0.0.


Input a Song key, retrieve an Entry.

Inputs

FieldTypeDescription
keySong key (unsigned integer)See Key

Outputs

FieldTypeDescription
entryEntry objectSee Entry

Example Request

festival-cli key_entry --key 5151
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_entry","params":{"key":5151}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entry": {
      "path": "/home/hinto/Music/song.flac",
      "key_artist": 108,
      "key_album": 488,
      "key_song": 5151,
      "artist": "Artist Name",
      "album": "Album Title",
      "song": "Song Title"
    }
  },
  "id": 0
}

key_artist_albums

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist key, retrieve all their Album's.

The Album's are sorted by Release date.

Inputs

FieldTypeDescription
keyArtist key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Album's there are
albumsarray of Album objectsSee Album

Example Request

festival-cli key_artist_albums --key 62
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_artist_albums","params":{"key":62}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "albums": [
      {
        "title": "Apricot Princess",
        "key": 234,
        "artist": 62,
        "release": "2017",
        "runtime": 2370,
        "song_count": 10,
        "songs": [
          2463,
          2471,
          2483,
          2492,
          2498,
          2504,
          2514,
          2522,
          2530,
          2536
        ],
        "discs": 0,
        "art": 307745,
        "genre": "Pop"
      },
      {
        "title": "Pony",
        "key": 241,
        "artist": 62,
        "release": "2019-09-19",
        "runtime": 2032,
        "song_count": 10,
        "songs": [
          2540,
          2545,
          2548,
          2553,
          2558,
          2567,
          2573,
          2578,
          2581,
          2587
        ],
        "discs": 0,
        "art": 190830,
        "genre": "Alternative & Indie"
      },
      {
        "title": "WHO CARES?",
        "key": 247,
        "artist": 62,
        "release": "2022",
        "runtime": 2091,
        "song_count": 11,
        "songs": [
          2590,
          2592,
          2596,
          2598,
          2602,
          2606,
          2607,
          2610,
          2614,
          2618,
          2622
        ],
        "discs": 0,
        "art": 80994,
        "genre": "Alternative & Indie"
      }
    ]
  },
  "id": 0
}

key_artist_songs

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist key, retrieve all their Song's.

The Song's are sorted by Album release date, then Track + Disc order.

Inputs

FieldTypeDescription
keyArtist key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Song's there are
songsarray of Song objectsSee Song

Example Request

festival-cli key_artist_songs --key 62
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_artist_songs","params":{"key":62}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "songs": [
      {
        "title": "SUNFLOWER",
        "key": 2444,
        "album": 222,
        "runtime": 252,
        "sample_rate": 44100,
        "track": 1,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "BEST FRIEND",
        "key": 2398,
        "album": 222,
        "runtime": 262,
        "sample_rate": 44100,
        "track": 2,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ]
  },
  "id": 0
}

key_artist_entries

🟒 Stable

This API is stable since festivald v1.0.0.


Input an Artist key, retrieve all their Song's in Entry form.

The Entry's are sorted by Album release date, then Track + Disc order.

Inputs

FieldTypeDescription
keyArtist key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Entry's there are
entriesarray of Entry objectsSee Entry

Example Request

festival-cli key_artist_entries --key 62
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_artist_entries","params":{"key":62}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "entries": [
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2444,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      },
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/BEST FRIEND.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2398,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "BEST FRIEND"
      }
    ]
  },
  "id": 0
}

key_album_artist

🟑 Incomplete

This API's output may have additions in the future.


Input an Album key, retrieve its Artist.

Inputs

FieldTypeDescription
keyAlbum key (unsigned integer)See Key

Outputs

FieldTypeDescription
artistArtist objectSee Artist

Example Request

festival-cli key_album_artist --key 237
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_album_artist","params":{"key":237}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artist": {
      "name": "Rex Orange County",
      "key": 65,
      "runtime": 7583,
      "albums": [
        237
      ],
      "songs": [
        2800,
        2803,
        2809
      ]
    }
  },
  "id": 0
}

key_album_songs

🟑 Incomplete

This API's output may have additions in the future.


Input an Album key, retrieve all of its Song's.

The Song's are sorted by Track + Disc order.

Inputs

FieldTypeDescription
keyArtist key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Song's there are
songsarray of Song objectsSee Song

Example Request

festival-cli key_album_songs --key 222
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_album_songs","params":{"key":222}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "songs": [
      {
        "title": "SUNFLOWER",
        "key": 2444,
        "album": 222,
        "runtime": 252,
        "sample_rate": 44100,
        "track": 1,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "BEST FRIEND",
        "key": 2398,
        "album": 222,
        "runtime": 262,
        "sample_rate": 44100,
        "track": 2,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ]
  },
  "id": 0
}

key_album_entries

🟒 Stable

This API is stable since festivald v1.0.0.


Input an Album key, retrieve all of its Song's in Entry form.

The Entry's are sorted by Track + Disc order.

Inputs

FieldTypeDescription
keyAlbum key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Entry's there are
entriesarray of Entry objectsSee Entry

Example Request

festival-cli key_album_entries --key 222
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_album_entries","params":{"key":222}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "entries": [
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2444,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      },
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/BEST FRIEND.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2398,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "BEST FRIEND"
      }
    ]
  },
  "id": 0
}

key_song_artist

🟑 Incomplete

This API's output may have additions in the future.


Input a Song key, retrieve its Artist.

Inputs

FieldTypeDescription
keySong key (unsigned integer)See Key

Outputs

FieldTypeDescription
artistArtist objectSee Artist

Example Request

festival-cli key_song_artist --key 2800
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_song_artist","params":{"key":2800}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artist": {
      "name": "Rex Orange County",
      "key": 65,
      "runtime": 7583,
      "albums": [
        237
      ],
      "songs": [
        2800,
        2803,
        2809
      ]
    }
  },
  "id": 0
}

key_song_album

🟑 Incomplete

This API's output may have additions in the future.


Input a Song key, retrieve its Album.

Inputs

FieldTypeDescription
keySong key (unsigned integer)See Key

Outputs

FieldTypeDescription
albumAlbum objectSee Album

Example Request

festival-cli key_song_album --key 2540
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_song_album","params":{"key":2540}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "album": {
      "title": "Pony",
      "key": 241,
      "artist": 62,
      "release": "2019-09-19",
      "runtime": 2032,
      "song_count": 10,
      "songs": [
        2540,
        2545,
        2548,
        2553,
        2558,
        2567,
        2573,
        2578,
        2581,
        2587
      ],
      "discs": 0,
      "art": 190830,
      "genre": "Alternative & Indie"
    }
  },
  "id": 0
}

key_other_albums

🟑 Incomplete

This API's output may have additions in the future.


Input an Album key, retrieve all Album's by the same Artist.

The Album's are sorted by Release date.

Inputs

FieldTypeDescription
keyAlbum key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Album's there are
albumsarray of Album objectsSee Album

Example Request

festival-cli key_other_albums --key 234
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_other_albums","params":{"key":234}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "albums": [
      {
        "title": "Apricot Princess",
        "key": 234,
        "artist": 62,
        "release": "2017",
        "runtime": 2370,
        "song_count": 10,
        "songs": [
          2463,
          2471,
          2483,
          2492,
          2498,
          2504,
          2514,
          2522,
          2530,
          2536
        ],
        "discs": 0,
        "art": 307745,
        "genre": "Pop"
      },
      {
        "title": "Pony",
        "key": 241,
        "artist": 62,
        "release": "2019-09-19",
        "runtime": 2032,
        "song_count": 10,
        "songs": [
          2540,
          2545,
          2548,
          2553,
          2558,
          2567,
          2573,
          2578,
          2581,
          2587
        ],
        "discs": 0,
        "art": 190830,
        "genre": "Alternative & Indie"
      },
      {
        "title": "WHO CARES?",
        "key": 247,
        "artist": 62,
        "release": "2022",
        "runtime": 2091,
        "song_count": 11,
        "songs": [
          2590,
          2592,
          2596,
          2598,
          2602,
          2606,
          2607,
          2610,
          2614,
          2618,
          2622
        ],
        "discs": 0,
        "art": 80994,
        "genre": "Alternative & Indie"
      }
    ]
  },
  "id": 0
}

key_other_songs

🟑 Incomplete

This API's output may have additions in the future.


Input a Song key, retrieve all Song's in the same Album.

The Song's are sorted by Track + Disc order.

Inputs

FieldTypeDescription
keySong key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Song's there are
songsarray of Song objectsSee Song

Example Request

festival-cli key_other_songs --key 2444
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_other_songs","params":{"key":2444}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "songs": [
      {
        "title": "SUNFLOWER",
        "key": 2444,
        "album": 222,
        "runtime": 252,
        "sample_rate": 44100,
        "track": 1,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "BEST FRIEND",
        "key": 2398,
        "album": 222,
        "runtime": 262,
        "sample_rate": 44100,
        "track": 2,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ]
  },
  "id": 0
}

key_other_entries

🟒 Stable

This API is stable since festivald v1.0.0.


Input a Song key, retrieve all Song's in the same Album in Entry form.

The Entry's are sorted by Track + Disc order.

Inputs

FieldTypeDescription
keySong key (unsigned integer)See Key

Outputs

FieldTypeDescription
lenunsigned integerHow many Entry's there are
entriesarray of Entry objectsSee Entry

Example Request

festival-cli key_other_entries --key 2444
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"key_other_entries","params":{"key":2444}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "entries": [
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2444,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      },
      {
        "path": "/home/hinto/Music/Rex Orange County/RAINBOW/BEST FRIEND.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2398,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "BEST FRIEND"
      }
    ]
  },
  "id": 0
}

Map

These methods are the same as the key_* methods, but instead of key's, you can directly use:

strings to lookup Common Objects.

So instead of:

festival-cli key_artist --key 100

you can use:

festival-cli map_artist --artist 'γ‚«γƒγ‚³γ‚’γƒ€γƒŽ'

If the input is invalid, a JSON-RPC error will be returned.

Warning

Inputs are case-sensitive and must be exactly correct.

If you have an Album called Hello World, none of these inputs will work:

  • Hello world
  • hello World
  • HELlo World
  • HelloWorld
  • H3ll0 W0rld

The input must be exactly Hello World.

Collisions

When using map_album you must specify:

  • Artist name
  • Album title

and when using map_song you must specify:

  • Artist name
  • Album title
  • Song title

The reason these have to be specified is to prevent collisions.

If there's 2 Song's in your Collection called: Hello World, festivald cannot know which one you want.

Since Artist names are unique, and Album titles within Artist's are unique, they serve as an identifier.

Duplicate Song Names

An uncommon "bug" you may encounter when using:

  • Artist names
  • Album titles
  • Song titles

as the key for searching objects is that:

  1. if multiple Song's with the same name exist
  2. in the same Album
  3. by the same Artist

it is impossible to specify which one you want.

This may occur in Album's that have "interlude" tracks, which may be different, but have the same name, e.g:

Artist Name/
  β”‚
  β”œβ”€ Album Name/
      β”‚
      β”œβ”€ Song 1
      β”œβ”€ Interlude # <------------- same name
      β”œβ”€ Song 3.flac
      β”œβ”€ Interlude # <------------- same name
      β”œβ”€ Song 5.flac

The workaround is by using Song key's to retrieve these instead, as they are unique per file, regardless of metadata.

map_artist

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist name, retrieve an Artist object.

Inputs

FieldTypeDescription
artiststringArtist name

Outputs

FieldTypeDescription
artistArtist objectSee Artist

Example Request

festival-cli map_artist --artist "Rex Orange County"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_artist","params":{"artist":"Rex Orange County"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artist": {
      "name": "Rex Orange County",
      "key": 65,
      "runtime": 7583,
      "albums": [
        237
      ],
      "songs": [
        2800,
        2803,
        2809
      ]
    }
  },
  "id": 0
}

map_album

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist name and Album title, retrieve an Album object.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title

Outputs

FieldTypeDescription
albumAlbum objectSee Album

Example Request

festival-cli map_album --artist "Rex Orange County" --album RAINBOW
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_album","params":{"artist":"Rex Orange County","album":"RAINBOW"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "album": {
      "title": "RAINBOW",
      "key": 237,
      "artist": 65,
      "release": "????-??-??",
      "runtime": 1090,
      "song_count": 6,
      "songs": [
        2594,
        2540,
        2600,
        2496,
        2557,
        2500
      ],
      "discs": 0,
      "art": 7753,
      "genre": null
    }
  },
  "id": 0
}

map_song

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist name, Album title, and Song title, retrieve a Song object.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title
songstringSong title

Outputs

FieldTypeDescription
songSong objectSee Song

Example Request

festival-cli map_song --artist "Rex Orange County" --album RAINBOW --song SUNFLOWER
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_song","params":{"artist":"Rex Orange County","album":"RAINBOW","song":"SUNFLOWER"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "song": {
      "title": "SUNFLOWER",
      "key": 2539,
      "album": 237,
      "runtime": 252,
      "sample_rate": 44100,
      "track": 1,
      "disc": null,
      "mime": "audio/mpeg",
      "extension": "mp3"
    }
  },
  "id": 0
}

map_entry

🟒 Stable

This API is stable since festivald v1.0.0.


Input an Artist name, Album title, and Song title, retrieve an Entry object.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title
songstringSong title

Outputs

FieldTypeDescription
entryEntry objectSee Entry

Example Request

festival-cli map_entry --artist "Rex Orange County" --album RAINBOW --song SUNFLOWER
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_entry","params":{"artist":"Rex Orange County","album":"RAINBOW","song":"SUNFLOWER"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entry": {
      "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
      "key_artist": 65,
      "key_album": 237,
      "key_song": 2539,
      "artist": "Rex Orange County",
      "album": "RAINBOW",
      "song": "SUNFLOWER"
    }
  },
  "id": 0
}

map_artist_albums

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist name, retrieve all of their Album's.

The Album's are sorted by Release date.

Inputs

FieldTypeDescription
artiststringArtist name

Outputs

FieldTypeDescription
lenunsigned integerHow many Album's there are
albumsarray of Album objectsSee Album

Example Request

festival-cli map_artist_albums --artist "Rex Orange County"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_artist_albums","params":{"artist":"Rex Orange County"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "albums": [
      {
        "title": "Apricot Princess",
        "map": 234,
        "artist": 62,
        "release": "2017",
        "runtime": 2370,
        "song_count": 10,
        "songs": [
          2463,
          2471,
          2483,
          2492,
          2498,
          2504,
          2514,
          2522,
          2530,
          2536
        ],
        "discs": 0,
        "art": 307745,
        "genre": "Pop"
      },
      {
        "title": "Pony",
        "map": 241,
        "artist": 62,
        "release": "2019-09-19",
        "runtime": 2032,
        "song_count": 10,
        "songs": [
          2540,
          2545,
          2548,
          2553,
          2558,
          2567,
          2573,
          2578,
          2581,
          2587
        ],
        "discs": 0,
        "art": 190830,
        "genre": "Alternative & Indie"
      },
      {
        "title": "WHO CARES?",
        "map": 247,
        "artist": 62,
        "release": "2022",
        "runtime": 2091,
        "song_count": 11,
        "songs": [
          2590,
          2592,
          2596,
          2598,
          2602,
          2606,
          2607,
          2610,
          2614,
          2618,
          2622
        ],
        "discs": 0,
        "art": 80994,
        "genre": "Alternative & Indie"
      }
    ]
  },
  "id": 0
}

map_artist_songs

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist name, retrieve all their Song's.

The Song's are sorted by Album release date, then Track + Disc order.

Inputs

FieldTypeDescription
artiststringArtist name

Outputs

FieldTypeDescription
lenunsigned integerHow many Song's there are
songsarray of Song objectsSee Song

Example Request

festival-cli map_artist_songs --artist "Rex Orange County"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_artist_songs","params":{"artist":"Rex Orange County"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "songs": [
      {
        "title": "SUNFLOWER",
        "map": 2444,
        "album": 222,
        "runtime": 252,
        "sample_rate": 44100,
        "track": 1,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "BEST FRIEND",
        "map": 2398,
        "album": 222,
        "runtime": 262,
        "sample_rate": 44100,
        "track": 2,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ]
  },
  "id": 0
}

map_artist_entries

🟒 Stable

This API is stable since festivald v1.0.0.


Input an Artist name, retrieve all their Song's in Entry form.

The Entry's are sorted by Album release date, then Track + Disc order.

Inputs

FieldTypeDescription
artiststringArtist name

Outputs

FieldTypeDescription
lenunsigned integerHow many Entry's there are
entriesarray of Entry objectsSee Entry

Example Request

festival-cli map_artist_entries --artist "Rex Orange County"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_artist_entries","params":{"artist":"Rex Orange County"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "entries": [
      {
        "path": "/home/hinto/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2444,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      },
      {
        "path": "/home/hinto/Rex Orange County/RAINBOW/BEST FRIEND.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2398,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "BEST FRIEND"
      }
    ]
  },
  "id": 0
}

map_album_songs

🟑 Incomplete

This API's output may have additions in the future.


Input an Artist name and Album title, retrieve all the Song's in that Album.

The Song's are sorted by Track + Disc order.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title

Outputs

FieldTypeDescription
lenunsigned integerHow many Song's there are
songsarray of Song objectsSee Song

Example Request

festival-cli map_album_songs --artist "Rex Orange County" --album RAINBOW
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_album_songs","params":{"artist":"Rex Orange County","album":"RAINBOW"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "songs": [
      {
        "title": "SUNFLOWER",
        "map": 2444,
        "album": 222,
        "runtime": 252,
        "sample_rate": 44100,
        "track": 1,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      },
      {
        "title": "BEST FRIEND",
        "map": 2398,
        "album": 222,
        "runtime": 262,
        "sample_rate": 44100,
        "track": 2,
        "disc": null,
        "mime": "audio/mpeg",
        "extension": "mp3"
      }
    ]
  },
  "id": 0
}

map_album_entries

🟒 Stable

This API is stable since festivald v1.0.0.


Input an Artist name and Album title, retrieve all the Song's in that Album in Entry form.

The Entry's are sorted by Track + Disc order.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title

Outputs

FieldTypeDescription
lenunsigned integerHow many Entry's there are
entriesarray of Entry objectsSee Entry

Example Request

festival-cli map_album_entries --artist "Rex Orange County" --album RAINBOW
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"map_album_entries","params":{"artist":"Rex Orange County","album":"RAINBOW"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 2,
    "entries": [
      {
        "path": "/home/hinto/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2444,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      },
      {
        "path": "/home/hinto/Rex Orange County/RAINBOW/BEST FRIEND.mp3",
        "key_artist": 62,
        "key_album": 222,
        "key_song": 2398,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "BEST FRIEND"
      }
    ]
  },
  "id": 0
}

Current

Access the currently set Song, its Album, or its Artist, or in Entry form.

If no Song is set, a JSON-RPC error will be returned.

current_artist

🟑 Incomplete

This API's output may have additions in the future.


Access the Artist of the currently set Song.

Inputs

None

Outputs

FieldTypeDescription
artistArtist objectSee Artist

Example Request

festival-cli current_artist
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_artist"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artist": {
      "name": "Rex Orange County",
      "key": 65,
      "runtime": 7583,
      "albums": [
        237
      ],
      "songs": [
        2800,
        2803,
        2809
      ]
    }
  },
  "id": 0
}

current_album

🟑 Incomplete

This API's output may have additions in the future.


Access the Album of the currently set Song.

Inputs

None

Outputs

FieldTypeDescription
albumAlbum objectSee Album

Example Request

festival-cli current_album
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_album"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "album": {
      "title": "RAINBOW",
      "key": 237,
      "artist": 65,
      "release": "????-??-??",
      "runtime": 1090,
      "song_count": 6,
      "songs": [
        2594,
        2540,
        2600,
        2496,
        2557,
        2500
      ],
      "discs": 0,
      "art": 7753,
      "genre": null
    }
  },
  "id": 0
}

current_song

🟑 Incomplete

This API's output may have additions in the future.


Access the currently set Song.

Inputs

None

Outputs

FieldTypeDescription
songSong objectSee Song

Example Request

festival-cli current_song
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_song"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "song": {
      "title": "SUNFLOWER",
      "key": 2594,
      "album": 237,
      "runtime": 252,
      "sample_rate": 44100,
      "track": 1,
      "disc": null,
      "mime": "audio/mpeg",
      "extension": "mp3"
    }
  },
  "id": 0
}

current_entry

🟒 Stable

This API is stable since festivald v1.0.0.


Access the currently set Song, in Entry form.

Inputs

None

Outputs

FieldTypeDescription
entryEntry objectSee Entry

Example Request

festival-cli current_entry
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"current_entry"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entry": {
      "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
      "key_artist": 65,
      "key_album": 237,
      "key_song": 2539,
      "artist": "Rex Orange County",
      "album": "RAINBOW",
      "song": "SUNFLOWER"
    }
  },
  "id": 0
}

Rand

Access a random Song, Album, or Artist, or in Entry form.

If the Collection is empty, a JSON-RPC error will be returned.

Repeating is not prevented, so there is nothing preventing you from retrieving the same object multiple times in a row.

rand_artist

🟑 Incomplete

This API's output may have additions in the future.


Access a random Artist in your Collection.

Inputs

None

Outputs

FieldTypeDescription
artistArtist objectSee Artist

Example Request

festival-cli rand_artist
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_artist"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artist": {
      "name": "γ‚«γƒγ‚³γ‚’γƒ€γƒŽ",
      "key": 65,
      "runtime": 4709,
      "albums": [
        276,
        256
      ],
      "songs": [
        2883,
        2504,
        2859,
        2863,
        2866,
        2869,
        2873,
        2874,
        2693,
        2694
      ]
    }
  },
  "id": 0
}

rand_album

🟑 Incomplete

This API's output may have additions in the future.


Access a random Album in your Collection.

Inputs

None

Outputs

FieldTypeDescription
albumAlbum objectSee Album

Example Request

festival-cli rand_album
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_album"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "album": {
      "title": "hug",
      "key": 243,
      "artist": 65,
      "release": "2016",
      "runtime": 1276,
      "song_count": 5,
      "songs": [
        2541,
        2546,
        2550,
        2554,
        2556
      ],
      "discs": 0,
      "art": 220954,
      "genre": null
    }
  },
  "id": 0
}

rand_song

🟑 Incomplete

This API's output may have additions in the future.


Access a random Song in your Collection.

Inputs

None

Outputs

FieldTypeDescription
songSong objectSee Song

Example Request

festival-cli rand_song
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_song"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "song": {
      "title": "Home Alone",
      "key": 2825,
      "album": 269,
      "runtime": 182,
      "sample_rate": 48000,
      "track": 1,
      "disc": 1,
      "mime": "audio/x-flac",
      "extension": "flac"
    }
  },
  "id": 0
}

rand_entry

🟒 Stable

This API is stable since festivald v1.0.0.


Access a random Entry in your Collection.

Inputs

None

Outputs

FieldTypeDescription
entryEntry objectSee Entry

Example Request

festival-cli rand_entry
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"rand_entry"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entry": {
      "path": "/home/hinto/Music/γ‚«γƒγ‚³γ‚’γƒ€γƒŽ/η₯η₯­/Home Alone.flac",
      "key_artist": 65,
      "key_album": 269,
      "key_song": 2825,
      "artist": "γ‚«γƒγ‚³γ‚’γƒ€γƒŽ",
      "album": "η₯η₯­",
      "song": "Home Alone"
    }
  },
  "id": 0
}

Search

Fuzzy similarity searches for Song's, Album's, Artist's, and Entry's.

In general: input a string, receive some objects that are similar to the input.

If you know the exact string for a Song, Album, or Artist, consider using the Map methods instead for a direct lookup.

If you know the exact key, use the Key methods instead.

Kind

These are different "kinds" of searches you can do, affecting the result output.

Each search method requires one of these as input.

All of these return objects sorted from most-to-least similar.

KindDescription
allALL objects will be returned
sim60Only objects 60% similar
sim70Only objects 70% similar
sim80Only objects 80% similar
top25Only the top 25 results
top5Only the top 5 results
top1Only the top result

Warning

The output array may return empty given no matches or an empty Collection:

{
  "jsonrpc": "2.0",
  "result": {
    "songs": []
  },
  "id": 0
}

search

🟑 Incomplete

This API's output may have additions in the future.


Input a string, retrieve arrays of Artist's, Album's, and Song's, sorted by how similar their names/titles are to the input.

Inputs

FieldTypeDescription
inputstringThe string to match against, to use as input
kindstring, one of all, sim60, sim70, sim80, top25, top5, top1See Search/Kind

Outputs

FieldTypeDescription
artistsarray of Artist objectsAn array of Artist objects, sorted by most similar name first
albumsarray of Album objectsAn array of Album objects, sorted by most similar title first
songsarray of Song objectsAn array of Song objects, sorted by most similar title first

Example Request

festival-cli search --input twice --kind sim70
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search","params":{"input":"twice","kind":"sim70"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artists": [
      {
        "name": "TWICE",
        "key": 106,
        "runtime": 343,
        "albums": [
          598
        ],
        "songs": [
          5411
        ]
      },
    ],
    "albums": [
      {
        "title": "TIME",
        "key": 271,
        "artist": 42,
        "release": "2014-01-21",
        "runtime": 2904,
        "song_count": 3,
        "songs": [
          3058,
          3095,
          3121
        ],
        "discs": 0,
        "art": 1264656,
        "genre": null
      }
    ],
    "songs": [
      {
        "title": "TIME",
        "key": 5560,
        "album": 538,
        "runtime": 249,
        "sample_rate": 44100,
        "track": 5,
        "disc": 1,
        "mime": "audio/x-flac",
        "extension": "flac"
      }
    ]
  },
  "id": 0
}

search_artist

🟑 Incomplete

This API's output may have additions in the future.


Input a string, retrieve an array of Artist's, sorted by how similar their names are to the input.

Inputs

FieldTypeDescription
inputstringThe string to match against, to use as input
kindstring, one of all, sim60, sim70, sim80, top25, top5, top1See Search/Kind

Outputs

FieldTypeDescription
artistsarray of Artist objectsAn array of Artist objects, sorted by most similar name first

Example Request

festival-cli search_artist --input twice --kind sim70
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search_artist","params":{"input":"twice","kind":"sim70"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artists": [
      {
        "name": "TWICE",
        "key": 106,
        "runtime": 343,
        "albums": [
          598
        ],
        "songs": [
          5411
        ]
      }
    ]
  },
  "id": 0
}

search_album

🟑 Incomplete

This API's output may have additions in the future.


Input a string, retrieve an array of Album's, sorted by how similar their titles are to the input.

Inputs

FieldTypeDescription
inputstringThe string to match against, to use as input
kindstring, one of all, sim60, sim70, sim80, top25, top5, top1See Search/Kind

Outputs

FieldTypeDescription
albumsarray of Album objectsAn array of Album objects, sorted by most similar title first

Example Request

festival-cli search_album --input time --kind sim70
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search_album","params":{"input":"time","kind":"sim70"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "albums": [
      {
        "title": "TIME",
        "key": 271,
        "artist": 42,
        "release": "2014-01-21",
        "runtime": 2904,
        "song_count": 3,
        "songs": [
          3058,
          3095,
          3121
        ],
        "discs": 0,
        "art": 1264656,
        "genre": null
      }
    ]
  },
  "id": 0
}

search_song

🟑 Incomplete

This API's output may have additions in the future.


Input a string, retrieve an array of Song's, sorted by how similar their titles are to the input.

Inputs

FieldTypeDescription
inputstringThe string to match against, to use as input
kindstring, one of all, sim60, sim70, sim80, top25, top5, top1See Search/Kind

Outputs

FieldTypeDescription
songsarray of Song objectsAn array of Song objects, sorted by most similar title first

Example Request

festival-cli search_song --input time --kind sim70
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search_song","params":{"input":"time","kind":"sim70"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "songs": [
      {
        "title": "TIME",
        "key": 5412,
        "album": 528,
        "runtime": 249,
        "sample_rate": 44100,
        "track": 5,
        "disc": 1,
        "mime": "audio/x-flac",
        "extension": "flac"
      }
    ]
  },
  "id": 0
}

search_entry

🟒 Stable

This API is stable since festivald v1.0.0.


Input a string, retrieve an array of Song's (in Entry form), sorted by how similar their titles are to the input.

Inputs

FieldTypeDescription
inputstringThe string to match against, to use as input
kindstring, one of all, sim60, sim70, sim80, top25, top5, top1See Search/Kind

Outputs

FieldTypeDescription
entriesEntry objectSee Entry

Example Request

festival-cli search_entry --input time --kind top1
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"search_entry","params":{"input":"time","kind":"top1"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entries": [
      {
        "path": "/home/hinto/Music/Kero Kero Bonito/Time 'n' Place/Time Today.flac",
        "key_artist": 148,
        "key_album": 665,
        "key_song": 6768,
        "artist": "Kero Kero Bonito",
        "album": "Time 'n' Place",
        "song": "Time Today"
      }
    ]
  },
  "id": 0
}

Playback Control

Methods for controlling festivald audio playback, shuffling, seeking, etc.

Most of the responses of these methods will be the generic null response, indicating success.

See Queue for adding/removing Song's from the queue.

toggle

🟑 Incomplete

This API's output may have additions in the future.


Toggle playback.

Inputs

None

Outputs

null if everything went ok.

Example Request

festival-cli toggle
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"toggle"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

play

🟑 Incomplete

This API's output may have additions in the future.


Start playback.

Inputs

None

Outputs

null if everything went ok.

Example Request

festival-cli play
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"play"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

pause

🟑 Incomplete

This API's output may have additions in the future.


Pause playback.

Inputs

None

Outputs

null if everything went ok.

Example Request

festival-cli pause
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"pause"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

clear

🟑 Incomplete

This API's output may have additions in the future.


Clear the queue.

Inputs

FieldTypeDescription
playbackbooleanIf there is a Song currently set and playing, should we continue playback?

Outputs

FieldTypeDescription
lenunsigned integerAmount of Song's cleared from the queue

Example Request

festival-cli clear
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"clear","params":{"playback":false}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 207
  },
  "id": 0
}

stop

🟑 Incomplete

This API's output may have additions in the future.


Clear the queue and stop playback.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerAmount of Song's cleared from the queue

Example Request

festival-cli stop
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"stop"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 207
  },
  "id": 0
}

next

🟑 Incomplete

This API's output may have additions in the future.


Skip to the next song in the queue.

Ends the queue (or repeats if a repeat mode is on) if at the last song.

Does nothing if the queue is empty.

Inputs

None

Outputs

null if everything went ok.

Example Request

festival-cli next
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"next"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

previous

🟑 Incomplete

This API's output may have additions in the future.


Set the current Song to the previous in the queue.

If threshold is not specified, the previous_threshold config option will be used.

Inputs

FieldTypeDescription
thresholdoptional (maybe-null) unsigned integerIf the current Song runtime (seconds) has passed this number, this method will reset the current Song instead of skipping backwards. Setting this to 0 will make this method always go to the previous Song.

Outputs

null if everything went ok.

Example Request

festival-cli previous --threshold 0
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"previous","params":{"threshold":0}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

skip

🟑 Incomplete

This API's output may have additions in the future.


Skip forward a variable amount of Song's in the queue.

Inputs

FieldTypeDescription
skipunsigned integerHow many Song's to skip. If greater than the rest of the Song's in the queue, the queue will end (unless a repeat mode is on).

Outputs

null if everything went ok.

Example Request

festival-cli skip --skip 3
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"skip","params":{"skip":3}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

back

🟑 Incomplete

This API's output may have additions in the future.


Go backwards a variable amount of Song's in the queue.

This method ignores the previous_threshold config option, it will always go back.

Inputs

FieldTypeDescription
backunsigned integerHow many Song's to go backwards. This will not wrap around if we hit the 1st Song in the queue.

Outputs

null if everything went ok.

Example Request

festival-cli back --back 10
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"back","params":{"back":10}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

seek

🟑 Incomplete

This API's output may have additions in the future.


Seek forwards/backwards or to an absolute second in the current Song.

Seeking forwards pass the remaining Song length will finish the Song.

Seeking to an absolute position longer than the Song length will also finish the Song.

Seeking backwards more than already-played Song length will reset the Song.

Inputs

FieldTypeDescription
kindstring, one of forward, backward, absoluteThe "type" of seeking we should do. forward means advance the current Song by the provided second. backward means go back in the current Song by the provided second. absolute means skip to the exact second in the Song, e.g, to skip to the 1 minute mark in the current Song, you would use absolute + 60.
secondunsigned integerThe second to seek forward/backwards/to.

Outputs

null if everything went ok.

Example Request

festival-cli seek --kind absolute --second 60
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"seek","params":{"kind":"absolute","second":60}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

shuffle

🟑 Incomplete

This API's output may have additions in the future.


Shuffle the current queue, then set the current Song to the 1st Song in the queue.

Inputs

None

Outputs

null if everything went ok.

Example Request

festival-cli shuffle
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"shuffle"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

repeat

🟒 Stable

This API is stable since festivald v1.0.0.


Set the playback repeat mode.

Inputs

FieldTypeDescription
modestring, one of off, song, queueThe repeat mode to set. off turns off repeating, song turns on Song repeating, queue turns on queue repeating.

Outputs

FieldTypeDescription
previousstring, one of off, song, queueWhat the repeat mode was set to previously
currentstring, one of off, song, queueWhat the repeat mode is now set at

Example Request

festival-cli repeat --mode off
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"repeat","params":{"mode":"off"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "previous": "off",
    "current": "song"
  },
  "id": 0
}

volume

🟒 Stable

This API is stable since festivald v1.0.0.


Set the playback volume.

Inputs

FieldTypeDescription
volumeunsigned integerThe volume % to set. Must be in-between 0..100. If greater than 100, it will set the volume to 100.

Outputs

FieldTypeDescription
previousunsigned integerWhat the volume was set to previously
currentunsigned integerWhat the volume is now set at

Example Request

festival-cli volume --volume 15
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"volume","params":{"volume":15}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "previous": 0,
    "current": 15
  },
  "id": "festival-cli"
}

volume_up

🟒 Stable

This API is stable since festivald v1.0.0.


Raise the playback volume.

Inputs

FieldTypeDescription
upunsigned integerThe number to raise the volume by. Must be in-between 0..100. If greater than 100, it will set the volume to 100. Volume cannot go higher than 100.

Outputs

FieldTypeDescription
previousunsigned integerWhat the volume was set to previously
currentunsigned integerWhat the volume is now set at

Example Request

festival-cli volume_up --up 15
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"volume_up","params":{"up":15}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "previous": 0,
    "current": 15
  },
  "id": "festival-cli"
}

volume_down

🟒 Stable

This API is stable since festivald v1.0.0.


Lower the playback volume.

Inputs

FieldTypeDescription
downunsigned integerThe number to lower the volume by. Must be in-between 0..100. Volume cannot go lower than 0.

Outputs

FieldTypeDescription
previousunsigned integerWhat the volume was set to previously
currentunsigned integerWhat the volume is now set at

Example Request

festival-cli volume_down --down 15
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"volume_down","params":{"down":15}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "previous": 15,
    "current": 0
  },
  "id": "festival-cli"
}

Queue

Methods for adding/removing Songs to/from the queue.

Append

These are different way you can append to the queue.

All queue methods involving appending requires one of these as input.

KindDescription
frontAppend Song(s) to the front of the queue
backAppend Song(s) to the back of the queue
indexAppend Song(s) at a specific index in the queue. Queue index starts at 0, so to mimic front, you would provide 0.

If the index append is used, the separate index field must be non-null and provide an index.

The way this works is that the provided Song(s)'s will be inserted into the queue, starting from that index, for example:

#![allow(unused)]
fn main() {
// Our queue.
[0] Song A // <- Currently Playing.
[1] Song A
[2] Song A

// The songs we'd like to add at `index 2`
Song B
Song B
Song B

// The queue after appending.
[0] Song A // <- Currently Playing.
[1] Song A
[2] Song B // <- our songs were inserted
[3] Song B //    into the queue, starting
[4] Song B //    from index 2.
[5] Song A
}

offset

All queue methods involving appending multiple Song's has an optional input: offset.

If the method happens to set the current Song (added to empty queue, added to front, etc), this field lets you start at a particular Song offset in the Artist/Album/Playlist.

The Song's before the offset will still be added, but the current Song set will be the one at the offset.

The exact ordering of the Artist's songs and what the offsets are relative to is the same as the object's internal ordering: Album in release order, then Song track order.

Ordering for an Album's songs is by Track + Disc order.

Ordering for Playlist is just their regular array order.

For example, given "offset": 3:

#![allow(unused)]
fn main() {
// Artist's songs.
[0] song_1 // <----/ These are still added to the queue, but..
[1] song_2 // <---/
[2] song_3 // <--/
[3] song_4 // <-/ We will start playing from this `Song`.
[4] song_5
[5] song_6
}

queue_add_key_artist

🟑 Incomplete

This API's output may have additions in the future.


Add an Artist to the queue with an Artist key.

Inputs

FieldTypeDescription
keyArtist key (unsigned integer)See Key
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used
offsetoptional (maybe-null) unsigned integerSee Queue/offset

Outputs

result: null if everything went ok.

error: ... if there was an index/offset error.

Example Request 1

Add to back of the queue.

festival-cli queue_add_key_artist --key 123 --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_artist","params":{"key":123,"append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_key_artist --key 123 --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_artist","params":{"key":123,"append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add all the Song's by this Artist, but start at the 5th Song (offset 4).

festival-cli queue_add_key_artist --key 123 --append front --clear --play --offset 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_artist","params":{"key":123,"append":"front","clear":true,"play":true,"offset":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

queue_add_key_album

🟑 Incomplete

This API's output may have additions in the future.


Add an Album to the queue with an Album key.

Inputs

FieldTypeDescription
keyAlbum key (unsigned integer)See Key
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used
offsetoptional (maybe-null) unsigned integerSee Queue/offset

Outputs

result: null if everything went ok.

error: ... if there was an index/offset error.

Example Request 1

Add to back of the queue.

festival-cli queue_add_key_album --key 123 --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_album","params":{"key":123,"append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_key_album --key 123 --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_album","params":{"key":123,"append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add all the Song's in this Album, but start at the 5th Song (offset 4).

festival-cli queue_add_key_album --key 123 --append front --clear --play --offset 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_album","params":{"key":123,"append":"front","clear":true,"play":true,"offset":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

queue_add_key_song

🟑 Incomplete

This API's output may have additions in the future.


Add a Song to the queue with a Song key.

Inputs

FieldTypeDescription
keySong key (unsigned integer)See Key
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

result: null if everything went ok.

error: ... if there was an index/offset error.

Example Request 1

Add to back of the queue.

festival-cli queue_add_key_song --key 123 --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_song","params":{"key":123,"append":"back","clear":false,"play":false}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_key_song --key 123 --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_song","params":{"key":123,"append":"index","clear":false,"play":false,"index":4}'

Example Request 3

Clear the queue, add Song 123.

festival-cli queue_add_key_song --key 123 --append front --clear --play
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_key_song","params":{"key":123,"append":"front","clear":true,"play":true}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

queue_add_map_artist

🟑 Incomplete

This API's output may have additions in the future.


Add an Artist to the queue with an Artist name.

Inputs

FieldTypeDescription
artiststringArtist name
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used
offsetoptional (maybe-null) unsigned integerSee Queue/offset

Outputs

result: null if everything went ok.

error: ... if there was an index/offset error.

Example Request 1

Add to back of the queue.

festival-cli queue_add_map_artist --artist TWICE --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_artist","params":{"artist":"TWICE","append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_map_artist --artist TWICE --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_artist","params":{"artist":"TWICE","append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add all the Song's by this Artist, but start at the 5th Song (offset 4).

festival-cli queue_add_map_artist --artist TWICE --append front --clear --play --offset 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_artist","params":{"artist":"TWICE","append":"front","clear":true,"play":true,"offset":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

queue_add_map_album

🟑 Incomplete

This API's output may have additions in the future.


Add an Album to the queue with an Artist name and Album title.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used
offsetoptional (maybe-null) unsigned integerSee Queue/offset

Outputs

result: null if everything went ok.

error: ... if there was an index/offset error.

Example Request 1

Add to back of the queue.

festival-cli queue_add_map_album --artist TWICE --album "PAGE TWO" --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_album","params":{"artist":"TWICE","album":"PAGE TWO","append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_map_album --artist TWICE --album "PAGE TWO" --append index --index 4 
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_album","params":{"artist":"TWICE","album":"PAGE TWO","append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add all the Song's in this Album, but start at the 5th Song (offset 4).

festival-cli queue_add_map_album --artist TWICE --album "PAGE TWO" --append front --clear --play --offset 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_album","params":{"artist":"TWICE","album":"PAGE TWO","append":"front","clear":true,"play":true,"offset":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

queue_add_map_song

🟑 Incomplete

This API's output may have additions in the future.


Add a Song to the queue with an Artist name Album title, and Song title.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title
songstringSong title
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

result: null if everything went ok.

error: ... if there was an index/offset error.

Example Request 1

Add to back of the queue.

festival-cli queue_add_map_song --artist TWICE --album "PAGE TWO" --song "CHEER UP" --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_song","params":{"artist":"TWICE","album":"PAGE TWO","song":"CHEER UP","append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4, start from Song 3 (offset 2).

festival-cli queue_add_map_song --artist TWICE --album "PAGE TWO"  --song "CHEER UP" --append index --index 4 
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_song","params":{"artist":"TWICE","album":"PAGE TWO","song":"CHEER UP","append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add the Song "CHEER UP".

festival-cli queue_add_map_song --artist TWICE --album "PAGE TWO" --song "CHEER UP" --append front --clear --play
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_map_song","params":{"artist":"TWICE","album":"PAGE TWO","song":"CHEER UP","append":"front","clear":true,"play":true}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

queue_add_rand_artist

🟑 Incomplete

This API's output may have additions in the future.


Add a random Artist to the queue.

Inputs

FieldTypeDescription
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used
offsetoptional (maybe-null) unsigned integerSee Queue/offset

Outputs

FieldTypeDescription
artistArtist objectThe Artist that was added to the queue

Example Request 1

Add to back of the queue.

festival-cli queue_add_rand_artist --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_artist","params":{"append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_rand_artist --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_artist","params":{"append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add all the Song's by this Artist, but start at the 5th Song (offset 4).

festival-cli queue_add_rand_artist --append front --clear --play --offset 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_artist","params":{"append":"front","clear":true,"play":true,"offset":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "artist": {
      "name": "Rex Orange County",
      "key": 65,
      "runtime": 7583,
      "albums": [
        237
      ],
      "songs": [
        2800,
        2803,
        2809
      ]
    }
  },
  "id": 0
}

queue_add_rand_album

🟑 Incomplete

This API's output may have additions in the future.


Add a random Album to the queue.

Inputs

FieldTypeDescription
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used
offsetoptional (maybe-null) unsigned integerSee Queue/offset

Outputs

FieldTypeDescription
albumAlbum objectThe Album that was added to the queue

Example Request 1

Add to back of the queue.

festival-cli queue_add_rand_album --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_album","params":{"append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_rand_album --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_album","params":{"append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add all the Song's in this Album, but start at the 5th Song (offset 4).

festival-cli queue_add_rand_album --append front --clear --play --offset 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_album","params":{"append":"front","clear":true,"play":true,"offset":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "album": {
      "title": "RAINBOW",
      "key": 237,
      "artist": 65,
      "release": "????-??-??",
      "runtime": 1090,
      "song_count": 6,
      "songs": [
        2594,
        2540,
        2600,
        2496,
        2557,
        2500
      ],
      "discs": 0,
      "art": 7753,
      "genre": null
    }
  },
  "id": 0
}

queue_add_rand_song

🟑 Incomplete

This API's output may have additions in the future.


Add a random Song to the queue.

Inputs

FieldTypeDescription
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
songSong objectThe Song that was added to the queue

Example Request 1

Add to back of the queue.

festival-cli queue_add_rand_song --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_song","params":{"append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_rand_song --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_song","params":{"append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add to front of queue.

festival-cli queue_add_rand_song --append front --clear --play
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_song","params":{"append":"front","clear":true,"play":true}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "song": {
      "title": "SUNFLOWER",
      "key": 2594,
      "album": 237,
      "runtime": 252,
      "sample_rate": 44100,
      "track": 1,
      "disc": null,
      "mime": "audio/mpeg",
      "extension": "mp3"
    }
  },
  "id": 0
}

queue_add_rand_entry

🟑 Incomplete

This API's output may have additions in the future.


Add a random Song to the queue, receive it back in Entry form.

This is the same as queue_add_rand_song but returns an Entry.

Inputs

FieldTypeDescription
appendstring, one of front, back or indexSee Queue/Append
clearbooleanShould the queue be cleared before adding?
playbooleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
entryEntry objectThe Song that was added to the queue, in Entry form

Example Request 1

Add to back of the queue.

festival-cli queue_add_rand_entry --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_entry","params":{"append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4.

festival-cli queue_add_rand_entry --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_entry","params":{"append":"index","clear":false,"play":false,"index":4}}'

Example Request 3

Clear the queue, add to front of queue.

festival-cli queue_add_rand_entry --append front --clear --play
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_rand_entry","params":{"append":"front","clear":true,"play":true}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entry": {
      "path": "/home/hinto/Music/Rex Orange County/RAINBOW/SUNFLOWER.mp3",
      "key_artist": 69,
      "key_album": 254,
      "key_song": 2738,
      "artist": "Rex Orange County",
      "album": "RAINBOW",
      "song": "SUNFLOWER"
    }
  },
  "id": 0
}

queue_add_playlist

🟑 Incomplete

This API's output may have additions in the future.


Add a Playlist to the queue.

Inputs

FieldTypeDescription
playliststringThe Playlist's name
appendstring, one of front, back or indexSee Queue/Append
clearoptional (maybe-null) booleanShould the queue be cleared before adding?
playoptional (maybe-null) booleanShould we start playing?
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used
offsetoptional (maybe-null) unsigned integerSee Queue/offset

Outputs

result: null if everything went ok.

error: ... if there was an index/offset error or if the playlist didn't exist.

Example Request 1

Add to back of the queue.

festival-cli queue_add_playlist --playlist my_playlist --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_playlist","params":{"playlist":"my_playlist","append":"back","clear":false,"play":false}}'

Example Request 2

Insert at queue index 4, start from Song 3 (offset 2).

festival-cli queue_add_playlist --playlist my_playlist --append index --index 4 --offset 2
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_playlist","params":{"playlist":"my_playlist","append":"index","clear":false,"play":false,"index":4,"offset":2}}'

Example Request 3

Clear the queue, add starting from Song 5 (offset 4).

festival-cli queue_add_playlist --playlist my_playlist --append front --clear --play --offset 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_add_playlist","params":{"playlist":"my_playlist","append":"front","clear":true,"play":false,"offset":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": null, // <--- everything went ok.
  "id": 0
}

queue_set_index

🟑 Incomplete

This API's output may have additions in the future.


Set the current Song to a queue index.

If the index is out-of-bounds (queue has 10 songs, index is 10 or greater), this method will do nothing.

Inputs

FieldTypeDescription
indexunsigned integerAn index in the queue (1st Song is index 0, 2nd Song is index 1, etc). The current state of the "queue" can be viewed with state_audio.

Outputs

FieldTypeDescription
out_of_boundsbooleanIf the provided index was equal to or greater than the queue length.
indexunsigned integerThe provided index
queue_lenunsigned integerThe queue length

Example Request

Set the current Song to index 4.

festival-cli queue_set_index --index 123
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_set_index","params":{"index":123}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "out_of_bounds": true,
    "index": 123,
    "queue_len": 0
  },
  "id": 0
}

queue_remove_range

🟑 Incomplete

This API's output may have additions in the future.


Remove a range of queue indices.

If either start or end is out-of-bounds, this method will do nothing.

Inputs

FieldTypeDescription
startunsigned integerThe beginning index to start removing from
endunsigned integerThe index to stop at
skipbooleanShould we skip to the next song if the range includes the current one? false will leave playback as is, even if the current song is wiped from the queue.

start and end

This method will start removing from the start index up UNTIL the end index.

It is a NON-inclusive range, i.e: it is 0..4, not 0..=4.

For example, given "start": 0 and "end": 4:

# The queue.
index 0 | song_1 <--- We start removing from here.
index 1 | song_2    |
index 2 | song_3    |
index 3 | song_4 <--- To here.
index 4 | song_5 <--- This song is not removed.
index 5 | song_6

Outputs

FieldTypeDescription
out_of_boundsbooleanIf either start or end was out-of-bounds
startunsigned integerThe provided start
endunsigned integerThe provided end
queue_lenunsigned integerThe queue length before removing

Example Request 1

Remove the 1st Song in the queue.

festival-cli queue_remove_range --start 0 --end 1 --skip
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_remove_range","params":{"start":0,"end":1,"skip":true}}'

Example Request 2

Remove 2, 3, 4 from the queue.

festival-cli queue_remove_range --start 2 --end 5 --skip
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"queue_remove_range","params":{"start":2,"end":5,"skip":true}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "out_of_bounds": false,
    "start": 2,
    "end": 5,
    "queue_len": 5
  },
  "id": 0
}

Playlist

Methods related for creating/modifying/viewing various info about Playlist's.

Append

Playlist methods are similar to the Queue methods, all Playlist methods involving appending requires an append type as input.

These append types are the exact same as the Queue, see Queue/Append for more info.

playlist_new

🟒 Stable

This API is stable since festivald v1.0.0.


Create a new empty Playlist, overwriting an existing one.

Inputs

FieldTypeDescription
playliststringThe name of the new Playlist

Outputs

FieldTypeDescription
lenoptional (maybe-null) unsigned integerIf the Playlist existed (and thus, overwritten), the amount of Playlist Entry's it had is returned, else if it didn't exist, null
entriesoptional (maybe-null) array of Playlist Entry objectsIf the Playlist existed (and thus, overwritten), its Playlist Entry's are returned, else if it didn't exist, null

Example Request

festival-cli playlist_new --playlist "Playlist 1"
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_new","params":{"playlist":"Playlist 1"}}'

Example Response 1

The playlist did not previously exist:

{
  "jsonrpc": "2.0",
  "result": {
    "len": null
    "entries": null
  },
  "id": 0
}

Example Response 2

The playlist previously existed, it was empty, and was overwritten:

{
  "jsonrpc": "2.0",
  "result": {
    "len": 0,
    "entries": []
  },
  "id": 0
}

Example Response 3

The playlist previously existed, it contained this 1 Playlist Entry, and was overwritten:

{
  "jsonrpc": "2.0",
  "result": {
    "len": 1,
    "entries": [
      {
        "valid": {
          "key_artist": 67,
          "key_album": 238,
          "key_song": 2588,
          "artist": "Rex Orange County",
          "album": "Apricot Princess",
          "song": "Waiting Room"
        }
      }
    ]
  },
  "id": 0
}

playlist_remove

🟒 Stable

This API is stable since festivald v1.0.0.


Remove a Playlist.

This method errors if playlist does not exist.

Inputs

FieldTypeDescription
playliststringThe name of the Playlist to remove

Outputs

FieldTypeDescription
lenunsigned integerThe amount of Playlist Entry's this removed Playlist had
entriesarray of Playlist Entry objectsThe Playlist Entry's of the remove Playlist

Example Request

festival-cli playlist_remove --playlist Playlist 1
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_remove","params":{"playlist":"Playlist 1"}}'

Example Response 1

The playlist existed, it was empty, and was removed:

{
  "jsonrpc": "2.0",
  "result": {
    "len": 0,
    "entries": []
  },
  "id": 0
}

Example Response 2

The playlist existed, it contained this 1 Playlist Entry, and was removed:

{
  "jsonrpc": "2.0",
  "result": {
    "len": 1,
    "entries": [
      {
        "valid": {
          "key_artist": 67,
          "key_album": 238,
          "key_song": 2588,
          "artist": "Rex Orange County",
          "album": "Apricot Princess",
          "song": "Waiting Room"
        }
      }
    ]
  },
  "id": 0
}

playlist_clone

🟒 Stable

This API is stable since festivald v1.0.0.


Clone an existing Playlist and all it's Entry's into a new one.

This method errors if from does not exist.

If to already exists, it will be overwritten.

Inputs

FieldTypeDescription
fromstringThe name of the Playlist to clone FROM
tostringThe name of the new Playlist to clone TO

Outputs

FieldTypeDescription
lenoptional (maybe-null) unsigned integerIf to already existed (and thus, overwritten), the amount of Playlist Entry's it had is returned, else if it didn't exist, null
entriesoptional (maybe-null) array of Playlist Entry objectsIf to already existed, its Playlist Entry's are returned, else if it didn't exist, null

Example Request

festival-cli playlist_clone --from original --to clone
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_remove","params":{"from":"original","to":"clone"}}'

Example Response 1

The playlist did not previously exist:

{
  "jsonrpc": "2.0",
  "result": {
    "len": null
    "entries": null
  },
  "id": 0
}

Example Response 2

The playlist previously existed, it was empty, and was overwritten:

{
  "jsonrpc": "2.0",
  "result": {
    "len": 0,
    "entries": []
  },
  "id": 0
}

Example Response 3

The playlist previously existed, it contained this 1 Playlist Entry, and was overwritten:

{
  "jsonrpc": "2.0",
  "result": {
    "len": 1,
    "entries": [
      {
        "valid": {
          "key_artist": 67,
          "key_album": 238,
          "key_song": 2588,
          "artist": "Rex Orange County",
          "album": "Apricot Princess",
          "song": "Waiting Room"
        }
      }
    ]
  },
  "id": 0
}

playlist_get_index

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve a single Playlist Entry from a Playlist, using its index number.

This method errors if the playlist does not exist or if index is out-of-bounds.

Inputs

FieldTypeDescription
playliststringThe name of the Playlist
indexunsigned integerThe index of the entry in the playlist

Outputs

FieldTypeDescription
entryPlaylist Entry objectThe Playlist Entry that was at index

Example Request

Retrieve the 1st entry in playlist "Hello"

festival-cli playlist_get_index --playlist Hello --index 0 
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_get_index","params":{"playlist":"Hello","index":0}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entry": {
      "valid": {
        "key_artist": 65,
        "key_album": 237,
        "key_song": 2539,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      }
    }
  },
  "id": 0
}

playlist_remove_index

🟒 Stable

This API is stable since festivald v1.0.0.


Remove a single Playlist Entry from a Playlist, using its index number.

This method errors if the playlist does not exist or if index is out-of-bounds.

Inputs

FieldTypeDescription
playliststringThe name of the Playlist
indexunsigned integerThe index of the entry in the playlist

Outputs

FieldTypeDescription
entryPlaylist Entry objectThe Playlist Entry that was removed

Example Request

Remove the 1st entry in playlist "Hello"

festival-cli playlist_remove_index --playlist Hello --index 0 
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_remove_index","params":{"playlist":"Hello","index":0}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "entry": {
      "valid": {
        "key_artist": 65,
        "key_album": 237,
        "key_song": 2539,
        "artist": "Rex Orange County",
        "album": "RAINBOW",
        "song": "SUNFLOWER"
      }
    }
  },
  "id": 0
}

playlist_add_key_artist

🟒 Stable

This API is stable since festivald v1.0.0.


Add an Artist to a Playlist with a Key.

If the specified playlist does not already exist, it will be created.

This method errors if there was an index error.

Inputs

FieldTypeDescription
keyArtist key (unsigned integer)Artist key of the Artist to add
playliststringThe name of the Playlist
appendstring, one of front, back or indexSee Playlist/Append
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
existedbooleanIf playlist already existed or not
old_lenunsigned integerThe old length of playlist
new_lenunsigned integerThe new length of playlist

Example Request 1

Add to back of the playlist "Hello".

festival-cli playlist_add_key_artist --playlist Hello --key 0 --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_key_artist","params":{"playlist":"Hello","key":0,"append":"back"}}'

Example Request 2

Append at playlist index 4.

festival-cli playlist_add_key_artist --playlist Hello --key 0 --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_key_artist","params":{"playlist":"Hello","key":0,"append":"index","index":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "existed": false,
    "old_len": 0,
    "new_len": 15
  },
  "id": 0
}

playlist_add_key_album

🟒 Stable

This API is stable since festivald v1.0.0.


Add an Album to a Playlist with a Key.

If the specified playlist does not already exist, it will be created.

This method errors if there was an index error.

Inputs

FieldTypeDescription
keyAlbum key (unsigned integer)Album key of the Album to add
playliststringThe name of the Playlist
appendstring, one of front, back or indexSee Playlist/Append
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
existedbooleanIf playlist already existed or not
old_lenunsigned integerThe old length of playlist
new_lenunsigned integerThe new length of playlist

Example Request 1

Add to back of the playlist "Hello".

festival-cli playlist_add_key_album --playlist Hello --key 0 --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_key_album","params":{"playlist":"Hello","key":0,"append":"back"}}'

Example Request 2

Append at playlist index 4.

festival-cli playlist_add_key_album --playlist Hello --key 0 --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_key_album","params":{"playlist":"Hello","key":0,"append":"index","index":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "existed": true,
    "old_len": 115,
    "new_len": 125
  },
  "id": 0
}

playlist_add_key_song

🟒 Stable

This API is stable since festivald v1.0.0.


Add a Song to a Playlist with a Key.

If the specified playlist does not already exist, it will be created.

This method errors if there was an index error.

Inputs

FieldTypeDescription
keySong key (unsigned integer)Song key of the Song to add
playliststringThe name of the Playlist
appendstring, one of front, back or indexSee Playlist/Append
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
existedbooleanIf playlist already existed or not
old_lenunsigned integerThe old length of playlist
new_lenunsigned integerThe new length of playlist

Example Request 1

Add to back of the playlist "Hello".

festival-cli playlist_add_key_song --playlist Hello --key 0 --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_key_song","params":{"playlist":"Hello","key":0,"append":"back"}}'

Example Request 2

Append at playlist index 4.

festival-cli playlist_add_key_song --playlist Hello --key 0 --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_key_song","params":{"playlist":"Hello","key":0,"append":"index","index":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "existed": false,
    "old_len": 0,
    "new_len": 187
  },
  "id": 0
}

playlist_add_map_artist

🟒 Stable

This API is stable since festivald v1.0.0.


Add an Artist to a Playlist.

If the specified playlist does not already exist, it will be created.

This method errors if there was an index error.

Inputs

FieldTypeDescription
artiststringArtist name
playliststringThe name of the Playlist
appendstring, one of front, back or indexSee Playlist/Append
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
existedbooleanIf playlist already existed or not
old_lenunsigned integerThe old length of playlist
new_lenunsigned integerThe new length of playlist

Example Request 1

Add to back of the playlist "Hello".

festival-cli playlist_add_map_artist --playlist Hello --artist TWICE --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_map_artist","params":{"playlist":"Hello","artist":"TWICE","append":"back"}}'

Example Request 2

Append at playlist index 4.

festival-cli playlist_add_map_artist --playlist Hello --artist TWICE --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_map_artist","params":{"playlist":"Hello","artist":"TWICE","append":"index","index":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "existed": true,
    "old_len": 10,
    "new_len": 187
  },
  "id": 0
}

playlist_add_map_album

🟒 Stable

This API is stable since festivald v1.0.0.


Add an Album to a Playlist.

If the specified playlist does not already exist, it will be created.

This method errors if there was an index error.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title
playliststringThe name of the Playlist
appendstring, one of front, back or indexSee Playlist/Append
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
existedbooleanIf playlist already existed or not
old_lenunsigned integerThe old length of playlist
new_lenunsigned integerThe new length of playlist

Example Request 1

Add to back of the playlist "Hello".

festival-cli playlist_add_map_album --playlist "Hello" --artist TWICE --album "PAGE TWO" --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_map_album","params":{"playlist":"Hello","artist":"TWICE","album":"PAGE TWO","append":"back"}}'

Example Request 2

Append at playlist index 4.

festival-cli playlist_add_map_album --playlist Hello --artist TWICE --album "PAGE TWO" --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_map_album","params":{"playlist":"Hello","artist":"TWICE","album":"PAGE TWO","append":"index","index":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "existed": true,
    "old_len": 0,
    "new_len": 187
  },
  "id": 0
}

playlist_add_map_song

🟒 Stable

This API is stable since festivald v1.0.0.


Add a Song to a Playlist.

If the specified playlist does not already exist, it will be created.

This method errors if there was an index error.

Inputs

FieldTypeDescription
artiststringArtist name
albumstringAlbum title
songstringSong title
playliststringThe name of the Playlist
appendstring, one of front, back or indexSee Playlist/Append
indexoptional (maybe-null) unsigned integerIf the index append is chosen, this will be the index used

Outputs

FieldTypeDescription
existedbooleanIf playlist already existed or not
old_lenunsigned integerThe old length of playlist
new_lenunsigned integerThe new length of playlist

Example Request 1

Add to back of the playlist "Hello".

festival-cli playlist_add_map_song --playlist Hello --artist TWICE --album "PAGE TWO" --song "CHEER UP" --append back
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_map_song","params":{"playlist":"Hello","artist":"TWICE","album":"PAGE TWO","song":"CHEER UP","append":"back"}}'

Example Request 2

Append at playlist index 4.

festival-cli playlist_add_map_song --playlist Hello --artist TWICE --album "PAGE TWO" --song "CHEER UP" --append index --index 4
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_add_map_song","params":{"playlist":"Hello","artist":"TWICE","album":"PAGE TWO","song":"CHEER UP","append":"index","index":4}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "existed": false,
    "old_len": 0,
    "new_len": 17
  },
  "id": 0
}

playlist_single

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve a single Playlist.

This method errors if playlist does not exist.

Inputs

FieldTypeDescription
playliststringThe name of the Playlist

Outputs

FieldTypeDescription
playliststringThe name of the Playlist
all_validbooleanIf all the Playlist Entry's are valid
entry_lenunsigned integerHow many Playlist Entry's there are in this Playlist
valid_lenunsigned integerHow many Playlist Entry's are valid
invalid_lenunsigned integerHow many Playlist Entry's are invalid
entriesarray of Playlist Entry objectsThe Playlist Entry's of the Playlist

Example Request

festival-cli playlist_single --playlist Hello 
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_single","params":{"playlist":"Hello"}}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "playlist": "Hello",
    "all_valid": false,
    "entry_len": 2,
    "valid_len": 1,
    "invalid_len": 1,
    "entries": [
      {
        "invalid": {
          "artist": "Artist Name",
          "album": "Album Title",
          "song": "Song Title"
        }
      },
      {
        "valid": {
          "key_artist": 46,
          "key_album": 168,
          "key_song": 1762,
          "artist": "Artist Name",
          "album": "Album Title",
          "song": "Song Title"
        }
      }
    ]
  },
  "id": 0
}

playlist_brief

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve the names of all Playlist's.

Names are sorted in lexicographical order.

Inputs

None

Outputs

FieldTypeDescription
lenunsigned integerHow many Playlist's there are
playlistsarray of string'sThe names of all Playlist's

Example Request

festival-cli playlist_brief
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_brief"}'

Example Response

{
  "jsonrpc": "2.0",
  "result": {
    "len": 3,
    "playlists": [
      "Playlist A",
      "Playlist B",
      "Playlist C"
    ]
  },
  "id": 0
}

playlist_full

🟒 Stable

This API is stable since festivald v1.0.0.


Retrieve full data of all Playlist's.

Playlists are sorted by their names in lexicographical order.

Inputs

None

Outputs

FieldTypeDescription
all_validbooleanIf every Playlist Entry is valid
playlist_lenunsigned integerHow many Playlist's there are
entry_lenunsigned integerHow many total Playlist Entry's there are
valid_lenunsigned integerHow many Playlist Entry's are valid
invalid_lenunsigned integerHow many Playlist Entry's are invalid
playlistsmap of Playlist objectsThe map's field keys are string's, the playlist names themselves

Example Request

festival-cli playlist_full
curl http://localhost:18425 -d '{"jsonrpc":"2.0","id":0,"method":"playlist_full"}'

Example Response 1

{
  "jsonrpc": "2.0",
  "result": {
    "all_valid": false,
    "playlist_len": 2,
    "entry_len": 3,
    "valid_len": 2,
    "invalid_len": 1,
    "playlists": { // <--- Note the '{' not '[' - this is a MAP not an ARRAY
      "hello": [ // <--- This Playlist's name is "hello"
        {
          "valid": {
            "key_artist": 46,
            "key_album": 168,
            "key_song": 1762,
            "artist": "Artist Name",
            "album": "Album Title",
            "song": "Song Title"
          }
        }
      ],
      "hmm": [ // <--- This Playlist's name is "hmm"
        {
          "invalid": {
            "artist": "Artist Name",
            "album": "Album Title",
            "song": "Song Title"
          }
        },
        {
          "valid": {
            "key_artist": 46,
            "key_album": 168,
            "key_song": 1762,
            "artist": "Artist Name",
            "album": "Album Title",
            "song": "Song Title"
          }
        }
      ]
    }
  },
  "id": 0
}

Example Response 2

If there are no playlists at all:

{
  "jsonrpc": "2.0",
  "result": {
    "all_valid": true,
    "playlist_len": 0,
    "entry_len": 0,
    "valid": 0,
    "invalid": 0,
    "playlists": {} // Empty MAP, not array `[]`
  },
  "id": 0
}

Example Response 3

If there is 1 empty playlist:

{
  "jsonrpc": "2.0",
  "result": {
    "all_valid": true,
    "playlist_len": 1,
    "entry_len": 0,
    "valid_len": 0,
    "invalid_len": 0,
    "playlists": {
      "hello": [] // <--- One empty playlist named "hello"
    }
  },
  "id": 0
}

REST

festivald (by default) exposes REST endpoints for accessing the underlying resources associated with the Collection via HTTP GET requests.

A simple way to access these files is via a browser, e.g, opening this link:

http://localhost:18425/art/Artist Name/Album Title

This will make the art of the album Album Title, owned by the artist Artist Name open directly in the browser (or make it download the image, if the direct_download configuration setting is enabled).

Opening something like:

http://localhost:18425/map/Artist Name/Album Title/Song Title

will download that song directly. In the future, the behavior of showing an inline player in browsers may be added to the direct_download config option.

If a file downloaded has a nested filename, the filename_separator config option will control what the separator will be. By default, this is -, so the filename of an archive of an Artist will look like:

Artist Name - Album Title.zip

Resource

The REST endpoint resources are in loosely grouped based on what type of data they are and what format they are outputted as.

These "groups" are referenced in authorization & API Stability.

REST resourceFile Format TypeDescriptionExample EndpointFilename Formatting
collectionzipThe whole Collection/collectionCollection - ${CREATION_UNIX_TIMESTAMP}.zip
playlistzipIndividual Playlist's/playlistPlaylist - ${PLAYLIST_NAME}.zip
artistzipIndividual Artist's/map/artist${ARTIST_NAME}.zip
albumzipIndividual Album's/current/album${ARTIST_NAME} - ${ALBUM_TITLE}.zip
songOriginal audio format (flac, mp3, etc)Individual Song's/rand/song${ARTIST_NAME} - ${ALBUM_TITLE} - ${SONG_TITLE}.${AUDIO_FORMAT}
artOriginal image format (png, jpg, etc)Individual Album art/current/art${ARTIST_NAME} - ${ALBUM_TITLE}.${IMAGE_FORMAT}

Missing Resource

If the underlying file for a resource is missing from the filesystem, festivald will respond to REST requests with an HTTP error.

For example, if an Artist is requested:

http://localhost:18425/map/Artist

And any underlying PATH is missing/moved/renamed from when the Collection was created:

mv "Song Title" "Song_Title"

festivald will now have a reference to a non-existent PATH and will not be able to find the file(s), so it will respond with something along the lines of:

Song file error: ${ARTIST_NAME} - ${ALBUM_TITLE} - Song Title.flac

You can re-create the Collection with collection_new to re-link these PATHs.

Disk Cache

festivald exclusively uses the Disk when operating with potentially heavy data.

All heavy files are streamed from disk, so none of them take up full space in physical memory.

Practically, what this means is that when serving files, festivald can get by with very little memory, although the Cache folder may get quite heavy.

The cache behavior can be configured in the config or via command-line options.

REST Quick Start

A quick start to using festivald's REST API.

View random Album art in a web browser with /rand/art

http://localhost:18425/rand/art

Download a random Song with /rand/song

http://localhost:18425/rand/song

Download a random Album in the ZIP format with /rand/album

http://localhost:18425/rand/album

Download a specific Artist in the ZIP format with /map/$ARTIST_NAME

http://localhost:18425/map/Artist Name

Download a specific Album by specific Artist in the ZIP format with /map/$ARTIST_NAME

http://localhost:18425/map/Artist Name/Album Title

Download the currently set Song with /current/song

http://localhost:18425/current/song

View the art of the currently set Song with /current/art

http://localhost:18425/current/art

Download all the art belonging to an Artist with /art/$ARTIST_NAME

http://localhost:18425/art/Artist Name

Download all the Song's in a Playlist in the ZIP format with /playlist/$PLAYLIST_NAME

http://localhost:18425/playlist/My Playlist 1

/key

Access audio files and/or art via a key.

This endpoint expects 2 more endpoints/inputs:

Where ${COMMON_OBJECT} is one of:

  • artist
  • album
  • song
  • art

The key must be the key number associated with the object.

See Common Objects/Key for more information on keys.

/key/artist/$ARTIST_KEY

🟒 Stable

This API is stable since festivald v1.0.0.


Download an Artist, using an Artist key.

Input

InputType
Artist keyunsigned integer

Output

ZIP of all artist's albums (including art if found).

Example Input

http://localhost:18425/key/artist/123

Example Output

File:

Artist Name.zip

Extracted:

Artist Name/
    β”œβ”€ Album Title 1/
    β”‚    β”œβ”€ Album Title 1.jpg
    β”‚    β”œβ”€ Song Title 1.mp3
    β”‚    β”œβ”€ Song Title 2.flac
    β”‚    β”œβ”€ Song Title 3.ogg
    β”‚
    │─ Album Title 2/
    β”‚    β”œβ”€ Album Title 2.png
    β”‚    β”œβ”€ Song Title 4.mp3
    β”‚    β”œβ”€ Song Title 5.flac
    β”‚    β”œβ”€ Song Title 6.ogg
    β”‚
    β”œβ”€ Album Title 3/
         β”œβ”€ Song Title 7.mp3
         β”œβ”€ Song Title 8.flac
         β”œβ”€ Song Title 9.ogg

/key/album/$ALBUM_KEY

🟒 Stable

This API is stable since festivald v1.0.0.


Download an Album using an Album key.

Input

InputType
Album keyunsigned integer

Output

Album in ZIP (including art if found).

Example Input

http://localhost:18425/key/album/123

Example Output

File:

Artist Name - Album Title.zip

Extracted:

Artist Name - Album Title/
  β”œβ”€ Album Title.jpg
  β”œβ”€ Song Title 1.mp3
  β”œβ”€ Song Title 2.flac
  β”œβ”€ Song Title 3.ogg

/key/song/$SONG_KEY

🟒 Stable

This API is stable since festivald v1.0.0.


Download a Song using a Song key.

Input

InputType
Song keyunsigned integer

Output

Song in original format.

Example Input

http://localhost:18425/key/song/123

Example Output

Artist Name - Album Title - Song Title.flac

/key/art/$ALBUM_KEY

🟒 Stable

This API is stable since festivald v1.0.0.


Download this Album's art, using an Album key.

Input

InputType
Album keyunsigned integer

Output

Art in original format.

Example Input

http://localhost:18425/key/art/123

Example Output

File:

Artist Name - Album Title.jpg

/map

This is the same as the /key endpoint, but instead of numbers, you can directly use:

  • Artist names
  • Album titles
  • Song titles

So instead of:

http://localhost:18425/key/song/123

you can use:

http://localhost:18425/map/Artist Name/Artist Title/Song Title

Browsers will secretly percent-encode this URL, so it'll actually be:

http://localhost:18425/map/Artist%20Name/Artist%20Title/Song%20Title

This is fine, festivald will decode it, along with any other percent encoding, so you can use spaces or any other UTF-8 characters directly in the URL:

http://localhost:18425/map/артист/❀️/γƒ’γƒ³γƒˆ γ˜γ‚ƒγͺい

The reason Artist names and Album titles have to be specified is to prevent collisions.

If there's 2 songs in your Collection called: Hello World, which one should festivald return?

Since Artist names are unique, and Album titles within Artist's are unique, they serve as an identifier.

Also note: words are case-sensitive and must be exact.

If you have an Album called Hello World, none of these inputs will work:

  • Hello world
  • hello World
  • HELlo World
  • HelloWorld
  • H3ll0 W0rld

The input must exactly be Hello World.

/map/$ARTIST_NAME

🟒 Stable

This API is stable since festivald v1.0.0.


Download an Artist, using the Artist's name.

Input

InputType
Artist namestring

Output

ZIP of all artist's albums (including art if found).

Example Input

http://localhost:18425/map/Artist Name

Example Output

File:

Artist Name.zip

Extracted:

Artist Name/
    β”œβ”€ Album Title 1/
    β”‚    β”œβ”€ Album Title 1.jpg
    β”‚    β”œβ”€ Song Title 1.mp3
    β”‚    β”œβ”€ Song Title 2.flac
    β”‚    β”œβ”€ Song Title 3.ogg
    β”‚
    │─ Album Title 2/
    β”‚    β”œβ”€ Album Title 2.png
    β”‚    β”œβ”€ Song Title 4.mp3
    β”‚    β”œβ”€ Song Title 5.flac
    β”‚    β”œβ”€ Song Title 6.ogg
    β”‚
    β”œβ”€ Album Title 3/
         β”œβ”€ Song Title 7.mp3
         β”œβ”€ Song Title 8.flac
         β”œβ”€ Song Title 9.ogg

/map/$ARTIST_NAME/$ALBUM_TITLE

🟒 Stable

This API is stable since festivald v1.0.0.


Download an Album using the Artist's name, and Album title.

Input

InputType
Artist namestring
Album titlestring

Output

Album in ZIP (including art if found).

Example Input

http://localhost:18425/map/Artist Name/Album Title

Example Output

File:

Artist Name - Album Title.zip

Extracted:

Artist Name - Album Title/
  β”œβ”€ Album Title.jpg
  β”œβ”€ Song Title 1.mp3
  β”œβ”€ Song Title 2.flac
  β”œβ”€ Song Title 3.ogg

/map/$ARTIST_NAME/$ALBUM_TITLE/$SONG_TITLE

🟒 Stable

This API is stable since festivald v1.0.0.


Download a Song, using the Artist's name, Album title, and Song title.

Input

InputType
Artist namestring
Album titlestring
Song titlestring

Output

OutputType
Song in original formataudio file

Example Input

http://localhost:18425/map/Artist Name/Album Title/Song Title

Example Output

Artist Name - Album Title - Song Title.flac

/current

Download the currently set Artist, Album, Song, or art.

Returns an HTTP error if no Song is currently set.

/current/artist

🟒 Stable

This API is stable since festivald v1.0.0.


Download the Artist of the currently set Song.

Input

None

Output

ZIP of all artist's albums (including art if found).

Example Input

http://localhost:18425/current/artist

Example Output

File:

Artist Name.zip

Extracted:

Artist Name/
    β”œβ”€ Album Name 1/
    β”‚    β”œβ”€ Album Name 1.jpg
    β”‚    β”œβ”€ Song Name 1.mp3
    β”‚    β”œβ”€ Song Name 2.flac
    β”‚    β”œβ”€ Song Name 3.ogg
    β”‚
    │─ Album Name 2/
    β”‚    β”œβ”€ Album Name 2.png
    β”‚    β”œβ”€ Song Name 4.mp3
    β”‚    β”œβ”€ Song Name 5.flac
    β”‚    β”œβ”€ Song Name 6.ogg
    β”‚
    β”œβ”€ Album Name 3/
         β”œβ”€ Song Name 7.mp3
         β”œβ”€ Song Name 8.flac
         β”œβ”€ Song Name 9.ogg

/current/album

🟒 Stable

This API is stable since festivald v1.0.0.


Download the Album of the currently set Song (including art if found).

Input

None

Output

Album in archive (including art if found).

Example Input

http://localhost:18425/current/album

Example Output

File:

Artist Name - Album Title.zip

Extracted:

Artist Name - Album Title/
  β”œβ”€ Album Name.jpg
  β”œβ”€ Song Name 1.mp3
  β”œβ”€ Song Name 2.flac
  β”œβ”€ Song Name 3.ogg

/current/song

🟒 Stable

This API is stable since festivald v1.0.0.


Download the currently set Song.

Input

None

Output

Song in original format.

Example Input

http://localhost:18425/current/song

Example Output

Artist Name - Album Title - Song Title.flac

/current/art

🟒 Stable

This API is stable since festivald v1.0.0.


Download the Album art of the currently set Song.

If no art was found, this will respond with an HTTP error.

Input

None

Output

Art in original format.

Example Input

http://localhost:18425/current/art

Example Output

Artist Name - Album Title.jpg

/rand

Download a random Artist, Album, Song or art.

This will return an HTTP error if the Collection is empty.

Repeating is allowed, so you may encounter the same object multiple times in a row.

/rand/artist

🟒 Stable

This API is stable since festivald v1.0.0.


Download a random Artist.

Input

None

Output

ZIP of all artist's albums (including art if found).

Example Input

http://localhost:18425/rand/artist

Example Output

File:

Artist Name.zip

Extracted:

Artist Name/
    β”œβ”€ Album Name 1/
    β”‚    β”œβ”€ Album Name 1.jpg
    β”‚    β”œβ”€ Song Name 1.mp3
    β”‚    β”œβ”€ Song Name 2.flac
    β”‚    β”œβ”€ Song Name 3.ogg
    β”‚
    │─ Album Name 2/
    β”‚    β”œβ”€ Album Name 2.png
    β”‚    β”œβ”€ Song Name 4.mp3
    β”‚    β”œβ”€ Song Name 5.flac
    β”‚    β”œβ”€ Song Name 6.ogg
    β”‚
    β”œβ”€ Album Name 3/
         β”œβ”€ Song Name 7.mp3
         β”œβ”€ Song Name 8.flac
         β”œβ”€ Song Name 9.ogg

/rand/album

🟒 Stable

This API is stable since festivald v1.0.0.


Download a random Album.

Input

None

Output

Album in ZIP (including art if found).

Example Input

http://localhost:18425/rand/album

Example Output

File:

Artist Name - Album Title.zip

Extracted:

Artist Name - Album Title/
  β”œβ”€ Album Name.jpg
  β”œβ”€ Song Name 1.mp3
  β”œβ”€ Song Name 2.flac
  β”œβ”€ Song Name 3.ogg

/rand/song

🟒 Stable

This API is stable since festivald v1.0.0.


Download a random Song.

Input

None

Output

Song in original format.

Example Input

http://localhost:18425/rand/song

Example Output

Artist Name - Album Title - Song Title.flac

/rand/art

🟒 Stable

This API is stable since festivald v1.0.0.


Download a random Album art.

If no art was found, the response will be an HTTP error.

Input

None

Output

Art in original format.

Example Input

http://localhost:18425/rand/art

Example Output

Artist Name - Album Title.jpg

/art

This is the same as the /map endpoint, but only for downloading Album art.

/art/$ARTIST_NAME

🟒 Stable

This API is stable since festivald v1.0.0.


Download all the Album art owned by this Artist, using the Artist's name.

Input

InputType
Artist namestring

Output

ZIP of all the art owned by this Artist.

Example Input

http://localhost:18425/art/Artist Name

Example Output

File:

Art - Artist Name.zip

Extracted:

Art - Artist Name/
    β”œβ”€ Album Name 1.jpg
    │─ Album Name 2.png
    β”œβ”€ Album Name 3.webp

/art/$ARTIST_NAME/$ALBUM_TITLE

🟒 Stable

This API is stable since festivald v1.0.0.


Download an Album's art, using the Artist's name, and Album title

Input

InputType
Artist namestring
Album titlestring

Output

Album art in original format.

Example Input

http://localhost:18425/art/Artist Name/Album Title

Example Output

Art - Artist Name - Album Title.png

/playlist/$PLAYLIST_NAME

🟒 Stable

This API is stable since festivald v1.0.0.


Download all the Song's in a Playlist.

Invalid Entry's will be ignored.

Each Song file will be prefixed with its index in the playlist.

The formatting is as such:

${INDEX}${SEPARATOR}${ARTIST_NAME}${SEPARATOR}${ALBUM_TITLE}${SEPARATOR}${SONG_TITLE}.${SONG_EXTENSION}

For example, if the filename_separator was left as the default -:

11 - Artist Name - Album Title - Song Title.mp3

Index starts at 0.

Input

InputType
Playlist namestring

Output

Playlist (valid Song files only) in ZIP.

Example Input

http://localhost:18425/playlist/My Playlist 2

Example Output

File:

Playlist - My Playlist 2.zip

Extracted:

Playlist - My Playlist 2/
  β”œβ”€ 0 - Artist Name - Album Title - Song Name.mp3
  β”œβ”€ 1 - Artist Name - Album Title - Song Name.flac
  β”œβ”€ 2 - Artist Name - Album Title - Song Name.ogg

/collection

🟒 Stable

This API is stable since festivald v1.0.0.


Download the entire Collection.

Warning

This will cause festivald to use at least the same amount of disk space your Collection's audio & art files take up.

For example, if all your Song's combined are 100GB in size, festivald will use at least 100GB in disk space when receiving this request. Further same requests will not further disk usage, depending on your cache_time configuration.

festivald may also take a while to respond to the client, as it is copying, organizing, and archiving the entire Collection.


Input

None

Output

Archive including:

Example Input

http://localhost:18425/collection

Example Output

File:

Collection${FILENAME_SEPARATOR}${CREATION_UNIX_TIMESTAMP}.zip

E.g:

Collection - 1690812809.zip

Extracted:

Collection - 1690812809/
  β”‚
  β”‚
  β”œβ”€ Artist Name 1/
  β”‚      β”œβ”€ Album Name 1/
  β”‚      β”‚    β”œβ”€ Album Name 1.jpg
  β”‚      β”‚    β”œβ”€ Song Name 1.mp3
  β”‚      β”‚    β”œβ”€ Song Name 2.flac
  β”‚      β”‚    β”œβ”€ Song Name 3.ogg
  β”‚      β”‚
  β”‚      │─ Album Name 2/
  β”‚      β”‚    β”œβ”€ Album Name 2.png
  β”‚      β”‚    β”œβ”€ Song Name 4.mp3
  β”‚      β”‚    β”œβ”€ Song Name 5.flac
  β”‚      β”‚    β”œβ”€ Song Name 6.ogg
  β”‚      β”‚
  β”‚      β”œβ”€ Album Name 3/
  β”‚           β”œβ”€ Song Name 7.mp3
  β”‚           β”œβ”€ Song Name 8.flac
  β”‚           β”œβ”€ Song Name 9.ogg
  β”‚
  β”‚
  β”œβ”€ Artist Name 2/
  β”‚      β”œβ”€ Album Name 4/
  β”‚      β”‚    β”œβ”€ Album Name 4.jpg
  β”‚      β”‚    β”œβ”€ Song Name 10.mp3
  β”‚      β”‚    β”œβ”€ Song Name 12.flac
  β”‚      β”‚    β”œβ”€ Song Name 13.ogg
  β”‚      β”‚
  β”‚      │─ Album Name 5/
  β”‚      β”‚    β”œβ”€ Album Name 5.png
  β”‚      β”‚    β”œβ”€ Song Name 14.mp3
  β”‚      β”‚    β”œβ”€ Song Name 15.flac
  β”‚      β”‚    β”œβ”€ Song Name 16.ogg
  β”‚      β”‚
  β”‚      β”œβ”€ Album Name 6/
  β”‚           β”œβ”€ Song Name 17.mp3
  β”‚           β”œβ”€ Song Name 18.flac
  β”‚           β”œβ”€ Song Name 19.ogg
  β”‚
  β”‚
  β”œβ”€ [... etc ...]