trunk-recorder-plugin 0.2.1

Plugins for Trunk Recorder Pro: the wire protocol between the recorder and a plugin process, and an SDK for writing plugins in Rust.
Documentation

trunk-recorder-plugin

Write plugins for Trunk Recorder Pro in Rust.

A plugin is a small program of its own. The recorder starts it, tells it what happens (a call starts, a recorded call lands on disk, a radio registers, …), and stops it. Plugins watch; they don't change what gets recorded. Uploaders (OpenMHz, Broadcastify), streamers, loggers and notifiers are all plugins.

The recorder and a plugin talk in JSON lines over stdin and stdout, so a plugin can be written in any language. This crate is the Rust side of that protocol, plus an SDK that does the plumbing for you:

  • Plugin and run: implement a trait, call run from main. The SDK reads the recorder's messages, parses your settings and answers --describe.
  • Settings forms: derive JsonSchema on your settings struct, and the recorder draws a form for it on its Plugins page.
  • CallQueue: an upload queue with retries and backoff, which saves the calls still waiting at shutdown and picks them up at the next start. It reports its own health to the recorder's dashboard: queue depth, upload time, and whether the service is up, degraded or down (name it with QueueOptions::endpoint).
  • Host::metrics: report the same yourself (Metrics: queue, timing, bytes sent, the services you talk to, and any figures of your own in extra) when you don't use the queue.
  • TalkgroupFilter: Trunk Recorder's talkgroup allow and deny patterns.
  • Multipart: a multipart/form-data body for any HTTP client.
  • testing: run a plugin without the recorder, and a mock web server to point it at.
use trunk_recorder_plugin::{topic, ConcludedCall, Host, Manifest, NoConfig, Plugin, Setup};

struct Hello { host: Host }

impl Plugin for Hello {
    type Config = NoConfig;
    type SystemConfig = NoConfig;
    fn manifest() -> Manifest {
        Manifest { name: "Hello".into(), subscribe: vec![topic::CALL_CONCLUDED.into()], ..trunk_recorder_plugin::manifest!() }
    }
    fn start(host: Host, _: Setup<NoConfig, NoConfig>) -> Result<Self, String> {
        Ok(Hello { host })
    }
    fn call_concluded(&mut self, call: ConcludedCall) {
        self.host.info(format!("TG {} for {} s", call.call.talkgroup, call.call.call_length));
    }
}

fn main() {
    trunk_recorder_plugin::run::<Hello>();
}

Getting started

Start from the plugin template. It's a working plugin with tests, CI and a release workflow that builds for every platform the recorder runs on, and its docs/ folder is the guide to writing plugins: the events, the settings form, uploading, testing and releasing.

Complete plugins to learn from: OpenMHz, Broadcastify Calls, Rdio Scanner, simplestream and upload-script.

Features

sdk (on by default) is everything for writing a plugin. The recorder itself uses only the protocol types, with default-features = false.

Versions

The crate follows semver. The protocol's API_VERSION is separate: it changes only when an older recorder can't run a newer plugin.

License

Either of Apache-2.0 or MIT, at your option, so your plugin can be licensed however you like. (The recorder itself is GPL-3.0.)