From 071e595766b89f020494cbec12b19fc8d433cd64 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 16 Jan 2023 20:56:51 -0600 Subject: [PATCH] Implement horizontal scrolling protocol extension for Sunshine --- src/Input.h | 6 ++++++ src/InputStream.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/Limelight-internal.h | 2 ++ src/Limelight.h | 6 ++++++ 4 files changed, 54 insertions(+) diff --git a/src/Input.h b/src/Input.h index 2e31d92..4cc2029 100644 --- a/src/Input.h +++ b/src/Input.h @@ -110,4 +110,10 @@ typedef struct _NV_SCROLL_PACKET { short zero3; } NV_SCROLL_PACKET, *PNV_SCROLL_PACKET; +#define SS_HSCROLL_MAGIC 0x55000001 +typedef struct _SS_HSCROLL_PACKET { + NV_INPUT_HEADER header; + short scrollAmount; +} SS_HSCROLL_PACKET, *PSS_HSCROLL_EVENT; + #pragma pack(pop) diff --git a/src/InputStream.c b/src/InputStream.c index df70c7b..6822429 100644 --- a/src/InputStream.c +++ b/src/InputStream.c @@ -44,6 +44,7 @@ typedef struct _PACKET_HOLDER { NV_CONTROLLER_PACKET controller; NV_MULTI_CONTROLLER_PACKET multiController; NV_SCROLL_PACKET scroll; + SS_HSCROLL_PACKET hscroll; NV_HAPTICS_PACKET haptics; NV_UNICODE_PACKET unicode; } packet; @@ -949,3 +950,42 @@ int LiSendHighResScrollEvent(short scrollAmount) { int LiSendScrollEvent(signed char scrollClicks) { return LiSendHighResScrollEvent(scrollClicks * LI_WHEEL_DELTA); } + +// Send a high resolution horizontal scroll event +int LiSendHighResHScrollEvent(short scrollAmount) { + PPACKET_HOLDER holder; + int err; + + if (!initialized) { + return -2; + } + + // This is a protocol extension only supported with Sunshine + if (!IS_SUNSHINE()) { + return -3; + } + + if (scrollAmount == 0) { + return 0; + } + + holder = allocatePacketHolder(0); + if (holder == NULL) { + return -1; + } + + holder->packet.hscroll.header.size = BE32(sizeof(SS_HSCROLL_PACKET) - sizeof(uint32_t)); + holder->packet.hscroll.header.magic = LE32(SS_HSCROLL_MAGIC); + holder->packet.hscroll.scrollAmount = BE16(scrollAmount); + + err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); + if (err != LBQ_SUCCESS) { + LC_ASSERT(err == LBQ_BOUND_EXCEEDED); + Limelog("Input queue reached maximum size limit\n"); + freePacketHolder(holder); + } +} + +int LiSendHScrollEvent(signed char scrollClicks) { + return LiSendHighResHScrollEvent(scrollClicks * LI_WHEEL_DELTA); +} diff --git a/src/Limelight-internal.h b/src/Limelight-internal.h index 15fd9d1..d9b4456 100644 --- a/src/Limelight-internal.h +++ b/src/Limelight-internal.h @@ -55,6 +55,8 @@ extern uint16_t VideoPortNumber; (AppVersionQuad[0] == (a) && AppVersionQuad[1] > (b)) || \ (AppVersionQuad[0] == (a) && AppVersionQuad[1] == (b) && AppVersionQuad[2] >= (c))) +#define IS_SUNSHINE() (AppVersionQuad[3] == -1) + #define UDP_RECV_POLL_TIMEOUT_MS 100 // At this value or above, we will request high quality audio unless CAPABILITY_SLOW_OPUS_DECODER diff --git a/src/Limelight.h b/src/Limelight.h index 1f0612d..8ce50a8 100644 --- a/src/Limelight.h +++ b/src/Limelight.h @@ -599,6 +599,12 @@ int LiSendScrollEvent(signed char scrollClicks); // scrolling (Apple Trackpads, Microsoft Precision Touchpads, etc.). int LiSendHighResScrollEvent(short scrollAmount); +// These functions send horizontal scroll events to the host which are +// analogous to LiSendScrollEvent() and LiSendHighResScrollEvent(). +// This is a Sunshine protocol extension. +int LiSendHScrollEvent(signed char scrollClicks); +int LiSendHighResHScrollEvent(short scrollAmount); + // This function returns a time in milliseconds with an implementation-defined epoch. uint64_t LiGetMillis(void);