-
-
Notifications
You must be signed in to change notification settings - Fork 4
Development specification
The plugin itself is only a translator between the StreamDeck Events and TouchPortal Events, specified in the Elgato SDK and this document.
The GoXLR protocol is quite simple, it does connect to a websocket server on path ws://<ipAddress>:6805/?GOXLRApp, and sends simple json objects.
Almost everything is from the SDK, the only things that are GoXLR specific, is the action id's and payloads.
Because the GoXLR connects to the server, you can have only one of them running on a single port. If you want more than one application to be connected, you will need a proxy/hub application to reroute to different ports (ports not possible to change in the official plugin).
A good place to start is looking into the Elgato StreamDeck SDK documentation. There you will find the documentation for the json documents.
Since the StreamDeck is button orientated, and Touch Portal is button-agnostic. The API cannot be used with the same behaviour. Some differences are:
- A Touch Portal plugin cannot know what is showing on the page at a given time (even with broadcast events).
- We need to always keep track of every profile change, and every thing in the routing table.
- We cannot configure a button from the plugin. Ex. change icon in a easy way.
- This needs to be configured in the Touch Portal Desktop App.
- We cannot fetch the list of profiles when configuring a button in TP on "opening the list".
- We can as a respond to another thing changing, ex. a client list, but this is a hack.
- We can fetch the list of profiles on App connection to the plugin, periodically etc.
- We cannot get the "current" state of what is configured, or save the state in a unhacky way.
{
"action":"com.tchelicon.goxlr.profilechange",
"context":"string value",
"event":"propertyInspectorDidAppear"
}{
"action":"com.tchelicon.goxlr.profilechange",
"context":"string value",
"event":"sendToPropertyInspector",
"payload":{
"Profiles":["Default - Red", "Default - Teal Blue", "Default - Vaporwave"]
}
}{
"action":"com.tchelicon.goXLR.ChangeProfile",
"context":"string value",
"event":"sendToPropertyInspector",
"payload":{
"Profiles":["Default - Red", "Default - Teal Blue", "Default - Vaporwave"]
}
}Profiles: List of all the profiles you can select.
{
"action":"com.tchelicon.goxlr.profilechange",
"event":"keyUp",
"payload":{
"settings":{
"SelectedProfile":"Default - Red"
}
}
}no response
{
"action":"com.tchelicon.goxlr.routingtable",
"event":"keyUp",
"payload":{
"settings":{
"RoutingAction":"Toggle",
"RoutingInput":"Music",
"RoutingOutput":"Line Out"
}
}
}RoutingAction: "Turn On", "Turn Off", "Toggle"
RoutingInput: "Mic", "Chat", "Music", "Game", "Console", "Line In", "System", "Samples"
RoutingOutput: "Headphones", "Broadcast Mix", "Line Out", "Chat Mic", "Sampler"
no response
There is two ways of registering for events. Either by replying to a goxlrConnectionEvent or by sending a willAppear event. The context field must be a unique string id for the profile, or the routing. And we would need one registration per item.
Ex. 5 profiles will need either 1 goxlrConnectionEvent, it then gets 5 getSettings events, and need to respond with 5 didReceiveSettings events.
In both situations, the GoXLR App will respond by sending a getSettings event. With either action com.tchelicon.goxlr.profilechange or action com.tchelicon.goxlr.routingtable.
Then the plugin needs to send back a didReceiveSettings event with the actual configuration.
- Request from GoXLR App:
{
"device": "GoXLR",
"event": "goxlrConnectionEvent"
}- Response from Plugin:
{
"event": "goxlrConnectionEvent",
"payload": [{
"action": "com.tchelicon.goxlr.profilechange",
"context": "Default - Red"
}, {
"action": "com.tchelicon.goxlr.routingtable",
"context": "Mic|Headphones"
}
]
}- Request from GoXLR App:
{
"action": "com.tchelicon.goxlr.profilechange",
"event": "getSettings",
"context": "Default - Red"
}and
{
"action": "com.tchelicon.goxlr.routingtable",
"event": "getSettings",
"context": "Mic|Headphones"
}- Response from Plugin:
{
"action": "com.tchelicon.goxlr.profilechange",
"event": "didReceiveSettings",
"context": "Default - Red",
"payload":{
"settings":{
"SelectedProfile":"Default - Red"
}
}
}and
{
"action": "com.tchelicon.goxlr.routingtable",
"event": "didReceiveSettings",
"context": "Mic|Headphones",
"payload":{
"settings":{
"RoutingAction":"Toggle",
"RoutingInput":"Mic",
"RoutingOutput":"Headphones"
}
}
}State updates will now come in as:
{
"action":"com.tchelicon.goxlr.profilechange",
"context":"Default - Red",
"event":"setState",
"payload":{
"state":1
}
}and
{
"action":"com.tchelicon.goxlr.routingtable",
"context":"Mic|Headphones",
"event":"setState",
"payload":{
"state":1
}
}Remember though, 1 is StateIsNotSet, and 0 is StateIsSet.
{
"action":"com.tchelicon.goxlr.profilechange",
"context":"Røde - ProCaster Red",
"event":"willAppear"
}Fallowed with a getSettings, didReceiveSettings, and setState event.
Warning: This seems to require the run of a propertyInspectorDidAppear before or after of the set context. Else the first result will always be not set state (second result will be correct).
{
"action":"com.tchelicon.goxlr.profilechange",
"context":"Røde - ProCaster Red",
"event":"willDisappear"
}