mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-13 07:17:28 +00:00
[client] audio: add optional LGMP transport
This commit is contained in:
@@ -41,6 +41,11 @@ target_link_libraries(lgmp-transport-tests
|
||||
lg_common
|
||||
lgmp
|
||||
)
|
||||
if(ENABLE_AUDIO)
|
||||
target_compile_definitions(lgmp-transport-tests PRIVATE
|
||||
ENABLE_AUDIO
|
||||
)
|
||||
endif()
|
||||
add_test(NAME lgmp-transport-tests
|
||||
COMMAND lgmp-transport-tests
|
||||
)
|
||||
@@ -141,6 +146,31 @@ foreach(name IN LISTS LGMP_CLIPBOARD_CASES)
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(ENABLE_AUDIO)
|
||||
add_executable(lgmp-audio-tests
|
||||
lgmp_audio_test.c
|
||||
../src/kb_hid.c
|
||||
)
|
||||
target_compile_definitions(lgmp-audio-tests PRIVATE
|
||||
ENABLE_AUDIO
|
||||
)
|
||||
target_include_directories(lgmp-audio-tests PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../transports/LGMP"
|
||||
)
|
||||
target_link_libraries(lgmp-audio-tests
|
||||
${EXE_FLAGS}
|
||||
transport_LGMP
|
||||
lg_common
|
||||
lgmp
|
||||
)
|
||||
add_test(NAME lgmp-audio
|
||||
COMMAND lgmp-audio-tests
|
||||
)
|
||||
set_tests_properties(lgmp-audio PROPERTIES
|
||||
TIMEOUT 20
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(wayland-motion-tests
|
||||
motion_test.c
|
||||
)
|
||||
|
||||
1229
client/tests/lgmp_audio_test.c
Normal file
1229
client/tests/lgmp_audio_test.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,9 @@
|
||||
#include "interface/transport.h"
|
||||
|
||||
#include <LGProtocol/KVMFR.h>
|
||||
#ifdef ENABLE_AUDIO
|
||||
#include "common/KVMFRAudio.h"
|
||||
#endif
|
||||
#include <LGProtocol/KVMFRRecovery.h>
|
||||
#include <LGProtocol/LGMPConfig.h>
|
||||
#include "common/debug.h"
|
||||
@@ -96,6 +99,42 @@ static bool waitForQueuesEmpty(PLGMPHost host, PLGMPHostQueue frameQueue,
|
||||
|
||||
struct VideoStatusTrace;
|
||||
|
||||
#ifdef ENABLE_AUDIO
|
||||
struct AudioStatusTrace
|
||||
{
|
||||
atomic_uint count;
|
||||
atomic_bool available;
|
||||
};
|
||||
|
||||
static void audioStatusChanged(void * opaque,
|
||||
const LG_AudioStatus * status)
|
||||
{
|
||||
struct AudioStatusTrace * trace = opaque;
|
||||
atomic_store_explicit(
|
||||
&trace->available, status->available, memory_order_relaxed);
|
||||
atomic_fetch_add_explicit(&trace->count, 1, memory_order_release);
|
||||
}
|
||||
|
||||
static bool readAudioClaim(PLGMPHost host, PLGMPHostQueue queue,
|
||||
KVMFRAudioClaim * claim, uint32_t * clientID)
|
||||
{
|
||||
for (unsigned i = 0; i < WAIT_TIMEOUT; ++i)
|
||||
{
|
||||
size_t size = sizeof(*claim);
|
||||
const LGMP_STATUS status = lgmpHostReadDataWithSource(
|
||||
queue, claim, &size, clientID);
|
||||
if (status == LGMP_OK)
|
||||
return size == sizeof(*claim) && *clientID != 0 &&
|
||||
lgmpHostAckData(queue) == LGMP_OK;
|
||||
if (status != LGMP_ERR_QUEUE_EMPTY ||
|
||||
lgmpHostProcess(host) != LGMP_OK)
|
||||
return false;
|
||||
usleep(1000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct WaitState
|
||||
{
|
||||
LG_Transport * transport;
|
||||
@@ -330,12 +369,20 @@ int main(void)
|
||||
PLGMPMemory malformedFrameMemory = NULL;
|
||||
PLGMPMemory pointerMemory = NULL;
|
||||
PLGMPMemory malformedPointerMemory = NULL;
|
||||
#ifdef ENABLE_AUDIO
|
||||
PLGMPMemory audioResponseMemory = NULL;
|
||||
#endif
|
||||
LG_Transport * transport = NULL;
|
||||
LG_Transport * secondTransport = NULL;
|
||||
LG_Transport * thirdTransport = NULL;
|
||||
LG_Transport * nestedTransport = NULL;
|
||||
LG_Transport * admittedTransport = NULL;
|
||||
const LG_FrameOps * frameOps = NULL;
|
||||
#ifdef ENABLE_AUDIO
|
||||
const LG_AudioOps * audioOps = NULL;
|
||||
void * audioOpaque = NULL;
|
||||
struct AudioStatusTrace audioTrace = { 0 };
|
||||
#endif
|
||||
struct VideoStatusTrace videoTrace;
|
||||
struct VideoStatusTrace secondVideoTrace;
|
||||
memset(&videoTrace, 0, sizeof(videoTrace));
|
||||
@@ -364,6 +411,7 @@ int main(void)
|
||||
KVMFR session = { 0 };
|
||||
memcpy(session.magic, KVMFR_MAGIC, sizeof(session.magic));
|
||||
session.version = KVMFR_VERSION;
|
||||
session.features = KVMFR_FEATURE_AUDIO;
|
||||
memcpy(session.hostver, "transport-test", sizeof("transport-test"));
|
||||
|
||||
CHECK(lgmpHostInit(hostMemory, TEST_SHM_SIZE, &host, sizeof(session),
|
||||
@@ -415,6 +463,10 @@ int main(void)
|
||||
LGMP_OK);
|
||||
CHECK(lgmpHostMemAlloc(host, sizeof(KVMFRCursor),
|
||||
&malformedPointerMemory) == LGMP_OK);
|
||||
#ifdef ENABLE_AUDIO
|
||||
CHECK(lgmpHostMemAlloc(host, sizeof(KVMFRAudioStreamResponse),
|
||||
&audioResponseMemory) == LGMP_OK);
|
||||
#endif
|
||||
KVMFRCursor * malformedPointer = lgmpHostMemPtr(malformedPointerMemory);
|
||||
malformedPointer->height = 2;
|
||||
malformedPointer->pitch = UINT32_MAX;
|
||||
@@ -484,6 +536,14 @@ int main(void)
|
||||
LG_TransportSession admittedSession;
|
||||
CHECK(LGT_LGMP.connectCancellable(
|
||||
admittedTransport, &admittedSession, NULL, NULL) == LG_TRANSPORT_OK);
|
||||
CHECK(transportSession.features & LG_TRANSPORT_FEATURE_AUDIO);
|
||||
#ifdef ENABLE_AUDIO
|
||||
CHECK(LGT_LGMP.getAudioOps);
|
||||
audioOps = LGT_LGMP.getAudioOps(transport, &audioOpaque);
|
||||
CHECK(audioOps && audioOpaque);
|
||||
#else
|
||||
CHECK(!LGT_LGMP.getAudioOps);
|
||||
#endif
|
||||
videoTrace.transport = transport;
|
||||
videoTrace.ops = frameOps;
|
||||
frameOps->setStatusListener(
|
||||
@@ -560,6 +620,69 @@ int main(void)
|
||||
&videoTrace.pointerEpoch, memory_order_acquire));
|
||||
frameOps->releasePointer(transport, &pointer);
|
||||
|
||||
#ifdef ENABLE_AUDIO
|
||||
audioOps->setStatusListener(audioOpaque,
|
||||
audioStatusChanged, &audioTrace);
|
||||
CHECK(atomic_load_explicit(&audioTrace.count, memory_order_acquire) == 1);
|
||||
CHECK(!atomic_load_explicit(
|
||||
&audioTrace.available, memory_order_acquire));
|
||||
|
||||
struct WaitState audioPointerWait =
|
||||
{
|
||||
.transport = transport,
|
||||
.ops = frameOps,
|
||||
.status = LG_TRANSPORT_ERROR,
|
||||
};
|
||||
pthread_t audioPointerThread;
|
||||
CHECK(pthread_create(&audioPointerThread, NULL,
|
||||
waitForVideo, &audioPointerWait) == 0);
|
||||
|
||||
KVMFRAudioClaim audioClaim;
|
||||
uint32_t audioClientID = 0;
|
||||
CHECK(readAudioClaim(host, pointerQueue,
|
||||
&audioClaim, &audioClientID));
|
||||
CHECK(audioClaim.messageType == KVMFR_MESSAGE_AUDIO_CLAIM);
|
||||
CHECK(audioClaim.version == KVMFR_AUDIO_CONTROL_VERSION);
|
||||
CHECK(audioClaim.size == sizeof(audioClaim));
|
||||
frameOps->cancelPointerWait(transport);
|
||||
CHECK(pthread_join(audioPointerThread, NULL) == 0);
|
||||
CHECK(audioPointerWait.status == LG_TRANSPORT_TIMEOUT);
|
||||
|
||||
KVMFRAudioStreamResponse * audioResponse =
|
||||
lgmpHostMemPtr(audioResponseMemory);
|
||||
*audioResponse = (KVMFRAudioStreamResponse)
|
||||
{
|
||||
.magic = KVMFR_AUDIO_RESPONSE_MAGIC,
|
||||
.version = KVMFR_AUDIO_CONTROL_VERSION,
|
||||
.size = sizeof(*audioResponse),
|
||||
.requestGeneration = audioClaim.requestGeneration,
|
||||
.boundClientID = audioClientID,
|
||||
.result = KVMFR_AUDIO_RESPONSE_BUSY,
|
||||
.claimToken = audioClaim.claimToken,
|
||||
};
|
||||
|
||||
unsigned audioRecipients = 0;
|
||||
CHECK(lgmpHostQueuePostForClients(pointerQueue,
|
||||
UINT64_C(0x7f7f7f7f) << 32, pointerMemory,
|
||||
&audioClientID, 1, &audioRecipients) == LGMP_OK);
|
||||
CHECK(audioRecipients == 1);
|
||||
CHECK(lgmpHostQueuePostForClients(pointerQueue,
|
||||
KVMFR_AUDIO_CONTROL_UDATA, pointerMemory,
|
||||
&audioClientID, 1, &audioRecipients) == LGMP_OK);
|
||||
CHECK(audioRecipients == 1);
|
||||
CHECK(lgmpHostQueuePostForClients(pointerQueue,
|
||||
KVMFR_AUDIO_CONTROL_UDATA, audioResponseMemory,
|
||||
&audioClientID, 1, &audioRecipients) == LGMP_OK);
|
||||
CHECK(audioRecipients == 1);
|
||||
CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION,
|
||||
pointerMemory) == LGMP_OK);
|
||||
CHECK(frameOps->nextPointer(transport, &pointer) == LG_TRANSPORT_OK);
|
||||
CHECK(pointer.x == wirePointer->x && pointer.y == wirePointer->y);
|
||||
frameOps->releasePointer(transport, &pointer);
|
||||
CHECK(waitForQueuesEmpty(host, frameQueue, pointerQueue));
|
||||
audioOps->setStatusListener(audioOpaque, NULL, NULL);
|
||||
#endif
|
||||
|
||||
const uint64_t frameEpoch = atomic_load_explicit(
|
||||
&videoTrace.frameEpoch, memory_order_acquire);
|
||||
const uint64_t pointerEpoch = atomic_load_explicit(
|
||||
@@ -1024,6 +1147,9 @@ cleanup:
|
||||
if (transport)
|
||||
LGT_LGMP.destroy(&transport);
|
||||
option_free();
|
||||
#ifdef ENABLE_AUDIO
|
||||
lgmpHostMemFree(&audioResponseMemory);
|
||||
#endif
|
||||
lgmpHostMemFree(&pointerMemory);
|
||||
lgmpHostMemFree(&malformedPointerMemory);
|
||||
lgmpHostMemFree(&malformedFrameMemory);
|
||||
|
||||
Reference in New Issue
Block a user