Documentation
¶
Overview ¶
Package broadcast streams completed trunked-radio calls to external call aggregators — Broadcastify Calls, RdioScanner, OpenMHz — and to live Icecast/ShoutCast audio servers.
The Manager subscribes to events.KindCallComplete (published by the recorder once a call's WAV is flushed to disk), resolves which backends want the call, encodes the audio to MP3 once, and dispatches it to each backend with bounded exponential-backoff retry. A call is skipped entirely when its talkgroup is flagged Stream=false or when it is shorter than the configured minimum duration.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Backend ¶
type Backend interface {
// Name is a short stable identifier used in logs and stats.
Name() string
// Accepts reports whether this backend wants calls from the named
// trunking system. An unfiltered backend accepts every system.
Accepts(systemName string) bool
// Send delivers the call. A non-nil error triggers a retry.
Send(ctx context.Context, c *Call) error
}
Backend is one outbound streaming destination. Implementations must be safe for concurrent Send calls — the Manager runs several upload workers. Send should treat a retry as a fresh attempt; the Manager handles backoff between attempts.
func NewBroadcastify ¶
func NewBroadcastify(cfg BroadcastifyConfig, hc *http.Client) (Backend, error)
NewBroadcastify builds a Broadcastify Calls backend.
func NewIcecast ¶
func NewIcecast(cfg IcecastConfig, log *slog.Logger) (Backend, error)
NewIcecast builds a live Icecast/ShoutCast streaming backend and starts its background source connection.
func NewOpenMHz ¶
func NewOpenMHz(cfg OpenMHzConfig, hc *http.Client) (Backend, error)
NewOpenMHz builds an OpenMHz upload backend.
func NewRdioScanner ¶
func NewRdioScanner(cfg RdioScannerConfig, hc *http.Client) (Backend, error)
NewRdioScanner builds an RdioScanner call-upload backend.
type BroadcastifyConfig ¶
type BroadcastifyConfig struct {
// Name is an optional label used in logs; defaults to
// "broadcastify".
Name string
// APIKey is the Broadcastify Calls API key for the system.
APIKey string
// SystemID is the numeric Broadcastify Calls system ID.
SystemID int
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
// Endpoint overrides the upload API URL (tests). Empty uses the
// production endpoint.
Endpoint string
}
BroadcastifyConfig configures one Broadcastify Calls feed.
type Call ¶
type Call struct {
System string
Protocol string
Talkgroup uint32
TalkgroupLabel string
Source uint32
FrequencyHz uint32
Encrypted bool
// AlgorithmID / KeyID surface the P25 encryption parameters when
// the in-call signalling has revealed them. Zero on clear calls
// and on encrypted calls whose Encryption Sync never arrived
// before the call ended. Aggregators that accept the fields can
// thread them into their API payload; aggregators that don't will
// just ignore them.
AlgorithmID uint8
KeyID uint16
Emergency bool
PatchedGroups []uint32
StartedAt time.Time
EndedAt time.Time
AudioPath string // .wav on disk written by the recorder
SampleRate int
// contains filtered or unexported fields
}
Call is a completed call queued for outbound streaming. It carries the call metadata plus a lazy MP3 accessor — the WAV on AudioPath is encoded to MP3 at most once regardless of how many backends consume it.
type IcecastConfig ¶
type IcecastConfig struct {
// Name is an optional log label; defaults to "icecast".
Name string
// Host and Port address the Icecast server.
Host string
Port int
// Mount is the mountpoint path (e.g. "/gophertrunk"). A leading
// slash is added when missing.
Mount string
// Username is the source username; defaults to "source".
Username string
// Password is the source password.
Password string
// StreamName is advertised to listeners via the Ice-Name header.
StreamName string
// SampleRate is the PCM rate used to synthesise inter-call
// silence; defaults to 8000.
SampleRate int
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
}
IcecastConfig configures one live Icecast/ShoutCast feed.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager fans completed calls out to the configured backends.
func NewManager ¶
NewManager validates opts and returns a Manager that has already subscribed to the bus (so calls completed before Run starts are not lost). The caller must invoke Run and, on shutdown, Close.
func (*Manager) Close ¶
Close releases the bus subscription, waits for Run to drain, then stops the upload workers. Safe to call multiple times.
func (*Manager) Run ¶
Run drains KindCallComplete events until ctx is cancelled or the bus subscription closes.
type OpenMHzConfig ¶
type OpenMHzConfig struct {
// Name is an optional log label; defaults to "openmhz".
Name string
// APIKey is the OpenMHz system API key.
APIKey string
// ShortName is the OpenMHz system short name (the path segment in
// the upload URL).
ShortName string
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
// Endpoint overrides the API base URL (tests). Empty uses the
// production endpoint.
Endpoint string
}
OpenMHzConfig configures one OpenMHz upload feed.
type Options ¶
type Options struct {
Bus *events.Bus
Log *slog.Logger
// Backends is the set of outbound destinations. A Manager with no
// backends is valid but inert.
Backends []Backend
// MinDuration drops calls shorter than this from every backend.
// Zero streams calls of any length.
MinDuration time.Duration
// Workers is the number of concurrent upload goroutines. Default 2.
Workers int
// MaxRetries is the per-backend retry budget on a failed Send.
// Default 3.
MaxRetries int
// RetryBase is the first backoff delay; it doubles per attempt.
// Default 2s.
RetryBase time.Duration
}
Options configure a Manager.
type RdioScannerConfig ¶
type RdioScannerConfig struct {
// Name is an optional log label; defaults to "rdioscanner".
Name string
// URL is the RdioScanner base URL (e.g. "https://scanner.example").
// The "/api/call-upload" path is appended automatically.
URL string
// APIKey is the RdioScanner system API key.
APIKey string
// SystemID is the numeric RdioScanner system ID.
SystemID int
// Systems restricts the feed to these trunking-system names.
// Empty streams every system.
Systems []string
}
RdioScannerConfig configures one RdioScanner call-upload feed.