[client] audio: initial addition of PipeWire audio support via SPICE

This commit is contained in:
Geoffrey McRae
2021-12-24 18:43:20 +11:00
parent 8ba4b56dba
commit e810577317
12 changed files with 444 additions and 4 deletions

View File

@@ -428,6 +428,13 @@ static struct Option options[] =
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{
.module = "spice",
.name = "audio",
.description = "Enable SPICE audio support",
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{
.module = "spice",
.name = "scaleCursor",
@@ -609,6 +616,7 @@ bool config_load(int argc, char * argv[])
g_params.useSpiceInput = option_get_bool("spice", "input" );
g_params.useSpiceClipboard = option_get_bool("spice", "clipboard");
g_params.useSpiceAudio = option_get_bool("spice", "audio" );
if (g_params.useSpiceClipboard)
{

View File

@@ -846,6 +846,66 @@ static void reportBadVersion()
DEBUG_ERROR("Please install the matching host application for this client");
}
void audioStart(int channels, int sampleRate, PSAudioFormat format,
uint32_t time)
{
/*
* we probe here so that the audiodev is operating in the context of the SPICE
* thread/loop to avoid any audio API threading issues
*/
static int probed = false;
if (!probed)
{
probed = true;
// search for the best audiodev to use
for(int i = 0; i < LG_AUDIODEV_COUNT; ++i)
if (LG_AudioDevs[i]->init())
{
g_state.audioDev = LG_AudioDevs[i];
DEBUG_INFO("Using AudioDev: %s", g_state.audioDev->name);
break;
}
if (!g_state.audioDev)
DEBUG_WARN("Failed to initialize an audio backend");
}
if (g_state.audioDev)
{
static int lastChannels = 0;
static int lastSampleRate = 0;
if (g_state.audioStarted)
{
if (channels != lastChannels || sampleRate != lastSampleRate)
g_state.audioDev->stop();
else
return;
}
lastChannels = channels;
lastSampleRate = sampleRate;
g_state.audioStarted = true;
DEBUG_INFO("%d channels @ %dHz", channels, sampleRate);
g_state.audioDev->start(channels, sampleRate);
}
}
void audioStop(void)
{
if (g_state.audioDev)
g_state.audioDev->stop();
g_state.audioStarted = false;
}
void audioData(uint8_t * data, size_t size)
{
if (g_state.audioDev)
g_state.audioDev->play(data, size);
}
static int lg_run(void)
{
g_cursor.sens = g_params.mouseSens;
@@ -921,7 +981,9 @@ static int lg_run(void)
}
// try to connect to the spice server
if (g_params.useSpiceInput || g_params.useSpiceClipboard)
if (g_params.useSpiceInput ||
g_params.useSpiceClipboard ||
g_params.useSpiceAudio)
{
if (g_params.useSpiceClipboard)
spice_set_clipboard_cb(
@@ -930,7 +992,14 @@ static int lg_run(void)
cb_spiceRelease,
cb_spiceRequest);
if (!spice_connect(g_params.spiceHost, g_params.spicePort, ""))
if (g_params.useSpiceAudio)
spice_set_audio_cb(
audioStart,
audioStop,
audioData);
if (!spice_connect(g_params.spiceHost, g_params.spicePort, "",
g_params.useSpiceAudio))
{
DEBUG_ERROR("Failed to connect to spice server");
return -1;

View File

@@ -24,6 +24,7 @@
#include "dynamic/displayservers.h"
#include "dynamic/renderers.h"
#include "dynamic/audiodev.h"
#include "common/thread.h"
#include "common/types.h"
@@ -133,6 +134,9 @@ struct AppState
bool resizeDone;
bool autoIdleInhibitState;
struct LG_AudioDevOps * audioDev;
bool audioStarted;
};
struct AppParams
@@ -154,6 +158,7 @@ struct AppParams
LG_RendererRotate winRotate;
bool useSpiceInput;
bool useSpiceClipboard;
bool useSpiceAudio;
const char * spiceHost;
unsigned int spicePort;
bool clipboardToVM;