RadioMaster logoRadioMaster Download

Guide · Extend RadioMaster

How to make a RadioMaster plugin

A plugin is a small program, in any language, that RadioMaster runs when something happens on air. Post the current song to Discord, write it to a file for OBS, light the ON AIR sign, log to your own database, or control the station from another system.

Start from the example

  1. Open Tools → Plugins and press 📂 Open plugins folder. RadioMaster creates the folder, with a working example in example-now-playing, and opens it. The window shows where the folder is.
  2. Copy the example folder, rename it, and change its plugin.json and script.
  3. Press ⟳ Reload plugins. Your plugin appears in the list with a switch to turn it on or off.
  4. Press Send a test event to run it straight away. Anything it prints shows up in the plugin's Log.

plugin.json

Every plugin is a folder inside plugins with a plugin.json:

{
  "name": "Now playing to Discord",
  "description": "Posts every song to our #now-playing channel.",
  "command": "python",
  "args": ["discord.py"],
  "events": ["track_started"],
  "mode": "event"
}
FieldMeaning
name, descriptionShown in the Plugins window
command, argsThe program to run. It starts in the plugin's own folder
eventsWhich events it wants (below), or ["*"] for all of them
mode"event" (the default) runs once per event. "service" starts with RadioMaster and keeps running

Events

EventWhenExtra fields
app_startRadioMaster startedversion
app_exitRadioMaster is closing
track_startedA song, voice track or jingle from the playlist startedtitle, artist, album, genre, year, path, duration, text
item_startedAnother playlist row started (stream relay, line input, speech, teaser…)title, text
playback_stoppedPlayback stopped
hourThe top of every hourhour
encoderA stream encoder connected, failed or stoppedencoder, name, state

Every event also has event and time (ISO 8601).

How a plugin gets the event

  • Event plugins get the event as one line of JSON on standard input, and as environment variables: RM_EVENT, RM_TITLE, RM_ARTIST, RM_PATH and so on (each field in capitals with RM_ in front). A run that takes longer than 60 seconds is stopped.
  • Service plugins get one JSON line on standard input per event, for as long as RadioMaster runs. When RadioMaster closes, standard input is closed: exit when that happens.

Control RadioMaster from a plugin

Print a line starting with RM: and RadioMaster runs it as a station command:

RM: STOP
RM: VOLUME 60
RM: PLAYLIST Evening
RM: ENCODER START 1
RM: RULE Station IDs
RM: GENERATE Overnight

Examples

Write the current song to a file for OBS (Python)

import json, sys
e = json.loads(sys.stdin.readline())
open("nowplaying.txt", "w", encoding="utf-8").write(f"{e['artist']} - {e['title']}")

Post to a Discord webhook (PowerShell)

$e = [Console]::In.ReadLine() | ConvertFrom-Json
$body = @{ content = "Now playing: $($e.artist) - $($e.title)" } | ConvertTo-Json
Invoke-RestMethod -Uri "https://discord.com/api/webhooks/…" -Method Post -Body $body -ContentType "application/json"

with "command": "powershell", "args": ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "discord.ps1"].

Lower the volume at the top of every hour (a service, Python)

import json, sys
for line in sys.stdin:
    e = json.loads(line)
    if e["event"] == "hour":
        print("RM: VOLUME 70", flush=True)

Shell script (macOS and Linux)

printf '%s - %s\n' "$RM_ARTIST" "$RM_TITLE" > nowplaying.txt

Only install plugins you trust. Plugins run with your account's rights. While the app is connected to RadioMaster Server, plugins keep running on your own computer.

The remote control API

To control RadioMaster from another computer, a stream deck or a web page, turn on the remote control API in Settings → Remote API: tick Enable, choose the port (9258 by default) and an API password, then restart RadioMaster. Every call is a simple GET that answers with JSON:

CallDoes
/api/statusState, artist, title, position, duration, volume, next and the playlist length
/api/play, /api/pause, /api/stopPlay, pause or resume, stop
/api/next, /api/prevNext or previous
/api/volume?v=0.8Set the volume, 0 to 1
/api/seek?s=30Jump to 30 seconds into the song
/api/cart?i=0Fire cart pad 1 (counting from 0)
/api/insert?path=…Put a file after the song on air

Add &pw=PASSWORD to every call when a password is set, for example:

curl "http://192.168.1.10:9258/api/status?pw=yourpassword"

The API is plain HTTP, so keep it on your own network.