Skip to content

Commit

Permalink
Add GRPC.tts(...) Lua API (#202)
Browse files Browse the repository at this point in the history
* Add GRPC.tts(...) Lua API

* Use InputPosition for positions in requests

* Add note about InputPosition to changelog
  • Loading branch information
rkusa authored Dec 6, 2022
1 parent 9919bdd commit 7fe8d4c
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 22 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `GetSessionId` API
- Added `GetDetectedTargets` API. Method follows the DCS implementation of controller's getDetectedTargets. Can optionally also return the unit or weapon objects tracked by the radar.
- Added `orientation` and `velocity` to `Unit` object
- Added `u`/`v` coordinates (offset from DCS map origin in meters) to `Position`s
- Added `u`/`v` coordinates (offset from DCS map origin in meters) to `Position`s used in responses. To not require them in requests, all positions provided in requests got changed to a new `InputPosition` type (you'll have to update your requests, simply replace `Position` with `InputPosition` in them).
- `GetRealTime` API
- Added `orientation` and `velocity` to `Weapon` object
- Added DCS `time` of the update to units stream (`StreamUnitsResponse`)
- Added `GetBallisticsCount` API
- Added `TtsService/Transmit` to synthesize text to speech and transmit it over SRS
- Added `GRPC.tts(ssml, frequency[, options])` Lua API

### Changed
- Unit objects now return the full group object in the `group` field to make event processing easier. This replaces the `group_name` and `group_category` fields and is a backwards incompatible change.
Expand Down
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,45 @@ You can also check for the present of a `\Logs\grpc.log` file.

The server will be running on port 50051 by default.

## Lua API

`DCS-gRPC` provides the following Lua APIs to interact with the server from within Lua.

- `GRPC.tts(ssml, frequency[, options])` - Synthesize text (`ssml`; SSML tags supported) to speech and transmit it over SRS on the `frequency` with the following optional `options` (and their defaults):
```lua
{
-- The plain text without any transformations made to it for the purpose of getting it spoken out
-- as desired (no SSML tags, no FOUR NINER instead of 49, ...). Even though this field is
-- optional, please consider providing it as it can be used to display the spoken text to players
-- with hearing impairments.
plaintext = null, -- e.g. `= "Hello Pilot"`

-- Name of the SRS client.
srsClientName = "DCS-gRPC",

-- The origin of the transmission. Relevant if the SRS server has "Line of
-- Sight" and/or "Distance Limit" enabled.
position = {
lat = 0.0,
lon = 0.0,
alt = 0.0, -- in meters
},

-- The coalition of the transmission. Relevant if the SRS server has "Secure
-- Coalition Radios" enabled. Supported values are: `blue` and `red`. Defaults
-- to being spectator if not specified.
coalition = null,

-- TTS provider to be use. Defaults to the one configured in your config or to Windows'
-- built-in TTS. Examples:
-- `= { aws = {} }` / `= { aws = { voice = "..." } }` enable AWS TTS
-- `= { azure = {} }` / `= { azure = { voice = "..." } }` enable Azure TTS
-- `= { gcloud = {} }` / `= { gcloud = { voice = "..." } }` enable Google Cloud TTS
-- `= { win = {} }` / `= { win = { voice = "..." } }` enable Windows TTS
provider = null,
}
```

## Client Development

`DCS-gRPC`, as the name implies, uses the [gRPC](https://grpc.io/) framework to handle communication between clients
Expand Down
5 changes: 5 additions & 0 deletions lua/DCS-gRPC/grpc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ GRPC.error = function(msg)
}
end

--
-- APIs exposed to Lua
--
GRPC.tts = grpc.tts

--
-- Logging methods
--
Expand Down
6 changes: 3 additions & 3 deletions protos/dcs/atmosphere/v0/atmosphere.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ message GetWindRequest {
// The position on the map we want the wind information for.
// Requires lat/lon/alt fields to be populated, there are
// no default values
dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
}

message GetWindResponse {
Expand All @@ -36,7 +36,7 @@ message GetWindWithTurbulenceRequest {
// The position on the map we want the wind information for.
// Requires lat/lon/alt fields to be populated, there are
// no default values
dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
}

message GetWindWithTurbulenceResponse {
Expand All @@ -50,7 +50,7 @@ message GetTemperatureAndPressureRequest {
// The position on the map we want the wind information for.
// Requires lat/lon/alt fields to be populated, there are
// no default values
dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
}

message GetTemperatureAndPressureResponse {
Expand Down
8 changes: 4 additions & 4 deletions protos/dcs/coalition/v0/coalition.proto
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ message AddGroupRequest {
bool hidden = 2;
bool late_activation = 3;
string name = 4;
dcs.common.v0.Position position = 5;
dcs.common.v0.InputPosition position = 5;
repeated Point waypoints = 6;
uint32 start_time = 7;
string task = 8;
Expand All @@ -71,7 +71,7 @@ message AddGroupRequest {
message GroundUnitTemplate {
string name = 1;
string type = 2;
dcs.common.v0.Position position = 3;
dcs.common.v0.InputPosition position = 3;
optional uint32 unit_id = 4;
optional uint32 heading = 5;
Skill skill = 6;
Expand Down Expand Up @@ -109,7 +109,7 @@ message AddGroupRequest {
POINT_TYPE_LAND = 5;
}

dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
AltitudeType altitude_type = 2;
PointType type = 3;
string action = 4;
Expand Down Expand Up @@ -160,7 +160,7 @@ message AddStaticObjectRequest {
optional uint32 rate = 6;

double heading = 7;
dcs.common.v0.Position position = 8;
dcs.common.v0.InputPosition position = 8;
// cargo mass in kilograms
uint32 cargo_mass = 9;
}
Expand Down
18 changes: 18 additions & 0 deletions protos/dcs/common/v0/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,24 @@ message Position {
double v = 5;
}

/**
* Position used in requests to DCS-gRPC.
*
* Latitude and Longitude are in Decimal Degrees format (e.g. 41.33 / 37.21).
* Negative values are used for West of the meridian and south of the equator.
*
* Altitude is given in meters above Mean Sea Level (MSL) and can be a decimal
* value.
*/
message InputPosition {
// Latitude in Decimal Degrees format
double lat = 1;
// Longitude in Decimal Degrees format
double lon = 2;
// Altitude in Meters above Mean Sea Level (MSL)
double alt = 3;
}

/**
* This type is returned if an object category cannot be determined
*
Expand Down
18 changes: 9 additions & 9 deletions protos/dcs/trigger/v0/trigger.proto
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ message SetUserFlagResponse {

message MarkToAllRequest {
string text = 2;
dcs.common.v0.Position position = 3;
dcs.common.v0.InputPosition position = 3;
bool read_only = 4;
string message = 5;
}
Expand All @@ -131,7 +131,7 @@ message MarkToAllResponse {
message MarkToCoalitionRequest {
uint32 id = 1;
string text = 2;
dcs.common.v0.Position position = 3;
dcs.common.v0.InputPosition position = 3;
dcs.common.v0.Coalition coalition = 4;
bool read_only = 5;
string message = 6;
Expand All @@ -144,7 +144,7 @@ message MarkToCoalitionResponse {
message MarkToGroupRequest {
uint32 id = 1;
string text = 2;
dcs.common.v0.Position position = 3;
dcs.common.v0.InputPosition position = 3;
uint32 group_id = 4;
bool read_only = 5;
string message = 6;
Expand All @@ -162,7 +162,7 @@ message RemoveMarkResponse {
}

message ExplosionRequest {
dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
uint32 power = 2;
}

Expand All @@ -181,7 +181,7 @@ message SmokeRequest {

// Altitude parameter will be ignored. Smoke always eminates from ground
// level which will be calculated server-side
dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
SmokeColor color = 2;
}

Expand All @@ -191,7 +191,7 @@ message SmokeResponse {
message IlluminationBombRequest {
// The altitude of Illumination Bombs is meters above ground. Ground level
// will be calculated server-side
dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
uint32 power = 2;
}

Expand All @@ -209,7 +209,7 @@ message SignalFlareRequest {

// Altitude parameter will be ignored. Signal flares always fire from
// ground level which will be calculated server-side
dcs.common.v0.Position position = 1;
dcs.common.v0.InputPosition position = 1;
FlareColor color = 2;
uint32 azimuth = 3;
}
Expand Down Expand Up @@ -251,7 +251,7 @@ enum Shape {

message MarkupToAllRequest {
Shape shape = 1;
repeated dcs.common.v0.Position points = 2;
repeated dcs.common.v0.InputPosition points = 2;
Color border_color = 3;
Color fill_color = 4;
LineType line_type = 5;
Expand All @@ -266,7 +266,7 @@ message MarkupToAllResponse {
message MarkupToCoalitionRequest {
Shape shape = 1;
dcs.common.v0.Coalition coalition = 2;
repeated dcs.common.v0.Position points = 3;
repeated dcs.common.v0.InputPosition points = 3;
Color border_color = 4;
Color fill_color = 5;
LineType line_type = 6;
Expand Down
4 changes: 2 additions & 2 deletions protos/dcs/tts/v0/tts.proto
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ message TransmitRequest {

// The origin of the transmission. Relevant if the SRS server has "Line of
// Sight" and/or "Distance Limit" enabled.
dcs.common.v0.Position position = 5;
dcs.common.v0.InputPosition position = 5;

// The coalition of the transmission. Relevant if the SRS server has "Secure
// Coalition Radios" enabled. Only Blue and Red are supported, all other
// values will fallback to Blue.
// values will fallback to Spectator.
dcs.common.v0.Coalition coalition = 6;

// Whether to keep the request open until the whole transmission was sent. If
Expand Down
13 changes: 13 additions & 0 deletions src/hot_reload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use std::{error, fmt};

use crate::server::TtsOptions;
use crate::Config;
use libloading::{Library, Symbol};
use mlua::prelude::*;
Expand Down Expand Up @@ -59,6 +60,18 @@ pub fn next(lua: &Lua, arg: (i32, Function)) -> LuaResult<bool> {
}
}

pub fn tts(lua: &Lua, arg: (String, u64, Option<TtsOptions>)) -> LuaResult<()> {
if let Some(ref lib) = *LIBRARY.read().unwrap() {
let f: Symbol<fn(lua: &Lua, arg: (String, u64, Option<TtsOptions>)) -> LuaResult<()>> = unsafe {
lib.get(b"tts")
.map_err(|err| mlua::Error::ExternalError(Arc::new(err)))?
};
f(lua, arg).map_err(take_error_ownership)
} else {
Ok(())
}
}

pub fn event(lua: &Lua, event: Value) -> LuaResult<()> {
if let Some(ref lib) = *LIBRARY.read().unwrap() {
let f: Symbol<fn(lua: &Lua, event: Value) -> LuaResult<()>> = unsafe {
Expand Down
15 changes: 14 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use config::Config;
use mlua::{prelude::*, LuaSerdeExt};
use mlua::{Function, Value};
use once_cell::sync::Lazy;
use server::Server;
use server::{Server, TtsOptions};
use stubs::mission::v0::StreamEventsResponse;
use thiserror::Error;

Expand Down Expand Up @@ -167,6 +167,17 @@ pub fn next(lua: &Lua, (env, callback): (i32, Function)) -> LuaResult<bool> {
Ok(false)
}

#[no_mangle]
pub fn tts(_lua: &Lua, (ssml, freq, opts): (String, u64, Option<TtsOptions>)) -> LuaResult<()> {
let start = Instant::now();
if let Some(server) = &*SERVER.read().unwrap() {
let _guard = server.stats().track_block_time(start);
server.tts(ssml, freq, opts);
}

Ok(())
}

#[no_mangle]
pub fn event(lua: &Lua, event: Value) -> LuaResult<()> {
let start = Instant::now();
Expand Down Expand Up @@ -253,6 +264,7 @@ pub fn dcs_grpc_hot_reload(lua: &Lua) -> LuaResult<LuaTable> {
"simulationFrame",
lua.create_function(hot_reload::simulation_frame)?,
)?;
exports.set("tts", lua.create_function(hot_reload::tts)?)?;
exports.set("logError", lua.create_function(hot_reload::log_error)?)?;
exports.set("logWarning", lua.create_function(hot_reload::log_warning)?)?;
exports.set("logInfo", lua.create_function(hot_reload::log_info)?)?;
Expand All @@ -269,6 +281,7 @@ pub fn dcs_grpc(lua: &Lua) -> LuaResult<LuaTable> {
exports.set("next", lua.create_function(next)?)?;
exports.set("event", lua.create_function(event)?)?;
exports.set("simulationFrame", lua.create_function(simulation_frame)?)?;
exports.set("tts", lua.create_function(tts)?)?;
exports.set("logError", lua.create_function(log_error)?)?;
exports.set("logWarning", lua.create_function(log_warning)?)?;
exports.set("logInfo", lua.create_function(log_info)?)?;
Expand Down
Loading

0 comments on commit 7fe8d4c

Please sign in to comment.