From 3a4ead2e6c846d1e4b15395e04bc1b1e4303569f Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 24 Apr 2025 18:34:13 +0200 Subject: [PATCH] [rdpsnd/client] add parameters to pulse snd device plugin ... to specify pulseaudio client name and stream name --- channels/audin/client/pulse/audin_pulse.c | 45 ++++++++----- channels/rdpsnd/client/pulse/rdpsnd_pulse.c | 70 +++++++++++++-------- 2 files changed, 76 insertions(+), 39 deletions(-) diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index 826960bd7..0ca6cac87 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -45,6 +45,8 @@ typedef struct IAudinDevice iface; char* device_name; + char* client_name; + char* stream_name; UINT32 frames_per_packet; pa_threaded_mainloop* mainloop; pa_context* context; @@ -377,7 +379,7 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u pulse->receive = receive; pulse->user_data = user_data; pa_threaded_mainloop_lock(pulse->mainloop); - pulse->stream = pa_stream_new(pulse->context, "freerdp_audin", &pulse->sample_spec, NULL); + pulse->stream = pa_stream_new(pulse->context, pulse->stream_name, &pulse->sample_spec, NULL); if (!pulse->stream) { @@ -445,26 +447,30 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, const ADDIN_ARGV* args) +static UINT audin_pulse_parse_addin_args(AudinPulseDevice* pulse, const ADDIN_ARGV* args) { - int status = 0; - DWORD flags = 0; - const COMMAND_LINE_ARGUMENT_A* arg = NULL; - AudinPulseDevice* pulse = device; - COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", - NULL, NULL, -1, NULL, "audio device name" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = { + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, + "audio device name" }, + { "client_name", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, + "name of pulse client" }, + { "stream_name", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, + "name of pulse stream" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } + }; - flags = + const DWORD flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, audin_pulse_args, flags, pulse, - NULL, NULL); + const int status = CommandLineParseArgumentsA(args->argc, args->argv, audin_pulse_args, flags, + pulse, NULL, NULL); if (status < 0) return ERROR_INVALID_PARAMETER; - arg = audin_pulse_args; + const COMMAND_LINE_ARGUMENT_A* arg = audin_pulse_args; + const char* client_name = NULL; + const char* stream_name = NULL; do { if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) @@ -483,6 +489,16 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, const ADDIN_A CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + if (!client_name) + client_name = "freerdp"; + if (!stream_name) + stream_name = "freerdp_audin"; + + pulse->client_name = _strdup(client_name); + pulse->stream_name = _strdup(stream_name); + if (!pulse->client_name || !pulse->stream_name) + return ERROR_OUTOFMEMORY; + return CHANNEL_RC_OK; } @@ -530,7 +546,8 @@ FREERDP_ENTRY_POINT(UINT VCAPITYPE pulse_freerdp_audin_client_subsystem_entry( goto error_out; } - pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); + pulse->context = + pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), pulse->client_name); if (!pulse->context) { diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index 8c22d5ed9..f32b4e5e6 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -46,6 +46,8 @@ typedef struct rdpsndDevicePlugin device; char* device_name; + char* client_name; + char* stream_name; pa_threaded_mainloop* mainloop; pa_context* context; pa_sample_spec sample_spec; @@ -341,8 +343,10 @@ static BOOL rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, const AUDIO_F static BOOL rdpsnd_pulse_context_connect(rdpsndDevicePlugin* device) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + WINPR_ASSERT(pulse); - pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); + pulse->context = + pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), pulse->client_name); if (!pulse->context) return FALSE; @@ -362,6 +366,7 @@ static BOOL rdpsnd_pulse_open_stream(rdpsndDevicePlugin* device) pa_buffer_attr buffer_attr = { 0 }; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = { 0 }; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + WINPR_ASSERT(pulse); if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { @@ -384,7 +389,7 @@ static BOOL rdpsnd_pulse_open_stream(rdpsndDevicePlugin* device) return FALSE; } - pulse->stream = pa_stream_new(pulse->context, "freerdp", &pulse->sample_spec, NULL); + pulse->stream = pa_stream_new(pulse->context, pulse->stream_name, &pulse->sample_spec, NULL); if (!pulse->stream) { @@ -489,6 +494,8 @@ static void rdpsnd_pulse_free(rdpsndDevicePlugin* device) } free(pulse->device_name); + free(pulse->client_name); + free(pulse->stream_name); free(pulse); } @@ -654,32 +661,34 @@ static UINT rdpsnd_pulse_play(rdpsndDevicePlugin* device, const BYTE* data, size return (UINT32)val; } -static UINT rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, const ADDIN_ARGV* args) +static UINT rdpsnd_pulse_parse_addin_args(rdpsndPulsePlugin* pulse, const ADDIN_ARGV* args) { - int status = 0; - DWORD flags = 0; - const COMMAND_LINE_ARGUMENT_A* arg = NULL; - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; COMMAND_LINE_ARGUMENT_A rdpsnd_pulse_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "device" }, { "reconnect_delay_seconds", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "reconnect_delay_seconds" }, + { "client_name", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, + "name of pulse client" }, + { "stream_name", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, + "name of pulse stream" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; - flags = + const DWORD flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; WINPR_ASSERT(pulse); WINPR_ASSERT(args); - status = CommandLineParseArgumentsA(args->argc, args->argv, rdpsnd_pulse_args, flags, pulse, - NULL, NULL); + const int status = CommandLineParseArgumentsA(args->argc, args->argv, rdpsnd_pulse_args, flags, + pulse, NULL, NULL); if (status < 0) return ERROR_INVALID_DATA; - arg = rdpsnd_pulse_args; + const COMMAND_LINE_ARGUMENT_A* arg = rdpsnd_pulse_args; + const char* client_name = NULL; + const char* stream_name = NULL; do { if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) @@ -701,22 +710,35 @@ static UINT rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, const ADDI pulse->reconnect_delay_seconds = (time_t)val; } + CommandLineSwitchCase(arg, "client_name") + { + client_name = arg->Value; + } + CommandLineSwitchCase(arg, "stream_name") + { + stream_name = arg->Value; + } CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + if (!client_name) + client_name = "freerdp"; + if (!stream_name) + stream_name = "freerdp"; + + pulse->client_name = _strdup(client_name); + pulse->stream_name = _strdup(stream_name); + if (!pulse->client_name || !pulse->stream_name) + return ERROR_OUTOFMEMORY; return CHANNEL_RC_OK; } FREERDP_ENTRY_POINT(UINT VCAPITYPE pulse_freerdp_rdpsnd_client_subsystem_entry( PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)) { - const ADDIN_ARGV* args = NULL; - rdpsndPulsePlugin* pulse = NULL; - UINT ret = 0; - WINPR_ASSERT(pEntryPoints); - pulse = (rdpsndPulsePlugin*)calloc(1, sizeof(rdpsndPulsePlugin)); + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)calloc(1, sizeof(rdpsndPulsePlugin)); if (!pulse) return CHANNEL_RC_NO_MEMORY; @@ -729,18 +751,16 @@ FREERDP_ENTRY_POINT(UINT VCAPITYPE pulse_freerdp_rdpsnd_client_subsystem_entry( pulse->device.Close = rdpsnd_pulse_close; pulse->device.Free = rdpsnd_pulse_free; pulse->device.DefaultFormat = rdpsnd_pulse_default_format; - args = pEntryPoints->args; - if (args->argc > 1) + const ADDIN_ARGV* args = pEntryPoints->args; + UINT ret = rdpsnd_pulse_parse_addin_args(pulse, args); + + if (ret != CHANNEL_RC_OK) { - ret = rdpsnd_pulse_parse_addin_args(&pulse->device, args); - - if (ret != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "error parsing arguments"); - goto error; - } + WLog_ERR(TAG, "error parsing arguments"); + goto error; } + pulse->reconnect_delay_seconds = 5; pulse->reconnect_time = time(NULL);