lib: Add support for trigger effects and controller haptics

By default, no trigger effects and haptics are requested from the
console, lib users have to explicitly enable them for a session by
setting the new `enable_dualsense` flag on the session's
`ChiakiConnectInfo` struct.

Trigger Effects are simply a new Takion message type `11`  and
include the type of each effect and the effect data (10 bytes) for
each of the triggers. They are exposed as a new Chiaki event type
`CHIAKI_EVENT_TRIGGER_EFFECTS`.

Haptic effects are implemented in the protocol as a separate audio
stream, for which packets are only sent when there are actually
effects being played, i.e. silence is not explicitly encoded.
Audio data is 3kHz little endian 16 bit stereo sent in frames of
10 samples every 100ms. Note that the Takion AV header has the
codec field set to Opus, however this is not true.
Users can provide a new `ChiakiAudioSink` dedicated to haptics
via the new `chiaki_session_set_haptics_sink` API, which behaves
identical to the regular audio sink, except that it has a lower
frequency.
This commit is contained in:
Johannes Baiter 2022-11-01 10:01:21 +01:00 committed by Florian Märkl
commit 74d39e6314
11 changed files with 145 additions and 28 deletions

View file

@ -38,7 +38,7 @@ CHIAKI_EXPORT void chiaki_feedback_state_format_v9(uint8_t *buf, ChiakiFeedbackS
/**
* @param buf buffer of at least CHIAKI_FEEDBACK_STATE_BUF_SIZE_V12
*/
CHIAKI_EXPORT void chiaki_feedback_state_format_v12(uint8_t *buf, ChiakiFeedbackState *state);
CHIAKI_EXPORT void chiaki_feedback_state_format_v12(uint8_t *buf, ChiakiFeedbackState *state, bool enable_dualsense);
#define CHIAKI_HISTORY_EVENT_SIZE_MAX 0x5

View file

@ -78,6 +78,7 @@ typedef struct chiaki_connect_info_t
ChiakiConnectVideoProfile video_profile;
bool video_profile_auto_downgrade; // Downgrade video_profile if server does not seem to support it.
bool enable_keyboard;
bool enable_dualsense;
} ChiakiConnectInfo;
@ -121,6 +122,14 @@ typedef struct chiaki_rumble_event_t
uint8_t right; // high-frequency
} ChiakiRumbleEvent;
typedef struct chiaki_trigger_effects_event_t
{
uint8_t type_left;
uint8_t type_right;
uint8_t left[10];
uint8_t right[10];
} ChiakiTriggerEffectsEvent;
typedef enum {
CHIAKI_EVENT_CONNECTED,
CHIAKI_EVENT_LOGIN_PIN_REQUEST,
@ -129,6 +138,7 @@ typedef enum {
CHIAKI_EVENT_KEYBOARD_REMOTE_CLOSE,
CHIAKI_EVENT_RUMBLE,
CHIAKI_EVENT_QUIT,
CHIAKI_EVENT_TRIGGER_EFFECTS,
} ChiakiEventType;
typedef struct chiaki_event_t
@ -139,6 +149,7 @@ typedef struct chiaki_event_t
ChiakiQuitEvent quit;
ChiakiKeyboardEvent keyboard;
ChiakiRumbleEvent rumble;
ChiakiTriggerEffectsEvent trigger_effects;
struct
{
bool pin_incorrect; // false on first request, true if the pin entered before was incorrect
@ -170,6 +181,7 @@ typedef struct chiaki_session_t
ChiakiConnectVideoProfile video_profile;
bool video_profile_auto_downgrade;
bool enable_keyboard;
bool enable_dualsense;
} connect_info;
ChiakiTarget target;
@ -191,6 +203,7 @@ typedef struct chiaki_session_t
ChiakiVideoSampleCallback video_sample_cb;
void *video_sample_cb_user;
ChiakiAudioSink audio_sink;
ChiakiAudioSink haptics_sink;
ChiakiThread session_thread;
@ -246,6 +259,14 @@ static inline void chiaki_session_set_audio_sink(ChiakiSession *session, ChiakiA
session->audio_sink = *sink;
}
/**
* @param sink contents are copied
*/
static inline void chiaki_session_set_haptics_sink(ChiakiSession *session, ChiakiAudioSink *sink)
{
session->haptics_sink = *sink;
}
#ifdef __cplusplus
}
#endif

View file

@ -32,6 +32,7 @@ typedef struct chiaki_stream_connection_t
ChiakiPacketStats packet_stats;
ChiakiAudioReceiver *audio_receiver;
ChiakiVideoReceiver *video_receiver;
ChiakiAudioReceiver *haptics_receiver;
ChiakiFeedbackSender feedback_sender;
/**

View file

@ -27,7 +27,8 @@ extern "C" {
typedef enum chiaki_takion_message_data_type_t {
CHIAKI_TAKION_MESSAGE_DATA_TYPE_PROTOBUF = 0,
CHIAKI_TAKION_MESSAGE_DATA_TYPE_RUMBLE = 7,
CHIAKI_TAKION_MESSAGE_DATA_TYPE_9 = 9
CHIAKI_TAKION_MESSAGE_DATA_TYPE_9 = 9,
CHIAKI_TAKION_MESSAGE_DATA_TYPE_TRIGGER_EFFECTS = 11,
} ChiakiTakionMessageDataType;
typedef struct chiaki_takion_av_packet_t
@ -36,6 +37,7 @@ typedef struct chiaki_takion_av_packet_t
ChiakiSeqNum16 frame_index;
bool uses_nalu_info_structs;
bool is_video;
bool is_haptics;
ChiakiSeqNum16 unit_index;
uint16_t units_in_frame_total; // source + units_in_frame_fec
uint16_t units_in_frame_fec;
@ -46,8 +48,6 @@ typedef struct chiaki_takion_av_packet_t
uint64_t key_pos;
uint8_t byte_before_audio_data;
uint8_t *data; // not owned
size_t data_size;
} ChiakiTakionAVPacket;
@ -106,6 +106,7 @@ typedef struct chiaki_takion_connect_info_t
ChiakiTakionCallback cb;
void *cb_user;
bool enable_crypt;
bool enable_dualsense;
uint8_t protocol_version;
} ChiakiTakionConnectInfo;
@ -162,6 +163,8 @@ typedef struct chiaki_takion_t
ChiakiTakionAVPacketParse av_packet_parse;
ChiakiKeyState key_state;
bool enable_dualsense;
} ChiakiTakion;