Expand description
§TrackAudio client library
trackaudio is a Rust client library for interacting with TrackAudio,
a modern voice communication application for VATSIM air traffic controllers.
This crate provides a high-level, async API for controlling TrackAudio programmatically via its WebSocket interface, allowing you to build custom integrations, automation tools, or alternative user interfaces.
§Features
- Async/await API: Built on Tokio for efficient async I/O
- Type-safe commands and events: Strongly-typed message protocol
- Request-response pattern: High-level API for commands that expect responses
- Event streaming: Subscribe to real-time events from TrackAudio
- Thread-safe: Client can be safely shared across threads
§Quick start
use trackaudio::{Command, Event, TrackAudioClient};
#[tokio::main]
async fn main() -> trackaudio::Result<()> {
// Connect to TrackAudio (defaults to ws://127.0.0.1:49080/ws)
let client = TrackAudioClient::connect_default().await?;
// Subscribe to events
let mut events = client.subscribe();
// Send a command
client.send(Command::PttPressed).await?;
// Listen for events
while let Ok(event) = events.recv().await {
match event {
Event::TxBegin(_) => println!("Started transmitting"),
Event::RxBegin(rx) => println!("Receiving from {}", rx.callsign),
_ => {}
}
}
Ok(())
}§High-level API
For common operations you can use TrackAudioApi, which wraps TrackAudioClient and
provides typed convenience methods based on the Request pattern:
use std::time::Duration;
use trackaudio::TrackAudioClient;
#[tokio::main]
async fn main() -> trackaudio::Result<()> {
let client = TrackAudioClient::connect_default().await?;
let api = client.api();
// Add a station and wait for its initial state
let station = api.add_station("LOVV_CTR", Some(Duration::from_secs(5))).await?;
println!("Added station: {station:?}");
// Change the main volume
let volume = api.change_main_volume(-20, None).await?;
println!("Changed main volume to {volume}");
Ok(())
}§Choosing between low-level and high-level APIs
-
Use
TrackAudioClientwhen you want full control: -
Use
TrackAudioApifor common operations with less boilerplate:- add/remove stations
- query station states
- adjust volumes and other simple settings
- transmit on all active frequencies
§Architecture
The library is organized around three main parts:
§TrackAudioClient
The core WebSocket client that handles connection management, command sending, and event distribution. Use this for low-level control or when you need to work directly with the command/event protocol.
§TrackAudioApi
A high-level API wrapper that provides convenient methods for common operations with built-in request-response matching and timeout handling.
§Messages
Command: Commands you send to TrackAudio (PTT, add station, set volume, etc.)Event: Events emitted by TrackAudio (station updates, RX/TX state changes, etc.)Request: Trait for typed request-response patterns
§Configuration
Use TrackAudioConfig to control connection parameters and internal behavior:
IPv4 and ws:// are currently supported; IPv6 and wss:// are not. Check the documentation of
TrackAudioConfig for more details on supported URL variants.
If you’re simply trying to connect to the default TrackAudio instance on your local machine,
you can use TrackAudioClient::connect_default to create a client with the default configuration:
use trackaudio::TrackAudioClient;
#[tokio::main]
async fn main() -> trackaudio::Result<()> {
let client = TrackAudioClient::connect_default().await?;
Ok(())
}If you need to customize the connection parameters, you can use TrackAudioClient::connect.
Connecting to a remote TrackAudio instance without modifying additional config values can be
performed via TrackAudioClient::connect_url:
use trackaudio::TrackAudioClient;
#[tokio::main]
async fn main() -> trackaudio::Result<()> {
// See [`TrackAudioConfig`] for supported URL variants.
let client = TrackAudioClient::connect_url("192.168.1.69").await?;
Ok(())
}§Request/response pattern
Some commands support a request/response style interaction by implementing the Request trait.
You can send these requests directly via TrackAudioClient::request:
use std::time::Duration;
use trackaudio::TrackAudioClient;
use trackaudio::messages::commands::GetStationStates;
#[tokio::main]
async fn main() -> trackaudio::Result<()> {
let client = TrackAudioClient::connect_default().await?;
// Get a snapshot of all station states
let states = client
.request(GetStationStates, Some(Duration::from_secs(5)))
.await?;
println!("We have {} stations", states.len());
Ok(())
}The Request implementation ties a concrete Command (e.g., GetStationStates
to the matching Event returned by TrackAudio, and converts them into a typed response
(e.g., Vec<StationState>).
§Working with frequencies
TrackAudio returns and expects all frequencies to be in Hertz, however that seem a bit cumbersome
to work with. The Frequency type stores values in Hertz internally but offers helpers for
Hz, kHz, and MHz:
use trackaudio::Frequency;
let a = Frequency::from_hz(132_600_000);
let b = Frequency::from_khz(132_600);
let c = Frequency::from_mhz(132.600);
assert_eq!(a, b);
assert_eq!(b, c);
assert_eq!(a.as_mhz(), 132.600);
// Convenient conversion to/from MHz as f64
let freq: Frequency = 132.600_f64.into();
let mhz: f64 = freq.into();
assert_eq!(freq.as_mhz(), mhz);
// Convenient conversion to/from Hz as u64
let freq: Frequency = 132_600_000_u64.into();
let hz: u64 = freq.into();
assert_eq!(freq.as_hz(), hz);§Error Handling
All operations return a Result<T> type with TrackAudioError variants:
use trackaudio::{TrackAudioClient, TrackAudioError};
async fn example() -> Result<(), Box<dyn std::error::Error>> {
match TrackAudioClient::connect_default().await {
Ok(client) => { /* use client */ },
Err(TrackAudioError::WebSocket(e)) => {
eprintln!("Connection failed: {}", e);
},
Err(TrackAudioError::Timeout) => {
eprintln!("Connection timed out");
},
Err(e) => {
eprintln!("Other error: {}", e);
}
}
Ok(())
}§Client-emitted events
In addition to events originating from TrackAudio itself, the client can inject internal events
via the Event::Client variant. These carry a ClientEvent and are used to report issues such as:
- Connection loss
- Failed command transmission
- Event deserialization errors
You receive them on the same broadcast channel as all other events.
§Features
tracing: integrate with thetracingcrate and emit spans for key operations (connect, send, request, etc.). Enabled by default.
§External Resources
Re-exports§
pub use messages::ClientEvent;pub use messages::Command;pub use messages::Event;pub use messages::Frequency;
Modules§
Structs§
- Track
Audio Api - A high-level client for interacting with the TrackAudio WebSocket API.
- Track
Audio Client TrackAudioClientis a client for interacting with a TrackAudio instance via WebSockets.- Track
Audio Config - Represents the configuration for a
TrackAudioClient.
Enums§
- Track
Audio Error - The
TrackAudioErrorenum represents various errors that can occur while using this crate.
Type Aliases§
- Result
- The crate’s
Resulttype, used throughout the library to indicate success or failure.