diff --git a/channels/rdpsnd/client/CMakeLists.txt b/channels/rdpsnd/client/CMakeLists.txt index 65c3bb346..2c35ac2c9 100644 --- a/channels/rdpsnd/client/CMakeLists.txt +++ b/channels/rdpsnd/client/CMakeLists.txt @@ -54,3 +54,5 @@ endif() if(WITH_OPENSLES) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "opensles" "") endif() + +add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "fake" "") diff --git a/channels/rdpsnd/client/fake/CMakeLists.txt b/channels/rdpsnd/client/fake/CMakeLists.txt new file mode 100644 index 000000000..fd0240a90 --- /dev/null +++ b/channels/rdpsnd/client/fake/CMakeLists.txt @@ -0,0 +1,33 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2019 Armin Novak +# Copyright 2019 Thincast Technologies GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +define_channel_client_subsystem("rdpsnd" "fake" "") + +set(${MODULE_PREFIX}_SRCS + rdpsnd_fake.c) + +include_directories(..) + +add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") + +list(APPEND ${MODULE_PREFIX}_LIBS freerdp) +list(APPEND ${MODULE_PREFIX}_LIBS winpr) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/Fake") diff --git a/channels/rdpsnd/client/fake/rdpsnd_fake.c b/channels/rdpsnd/client/fake/rdpsnd_fake.c new file mode 100644 index 000000000..579e79383 --- /dev/null +++ b/channels/rdpsnd/client/fake/rdpsnd_fake.c @@ -0,0 +1,175 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Output Virtual Channel + * + * Copyright 2019 Armin Novak + * Copyright 2019 Thincast Technologies GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include + +#include + +#include "rdpsnd_main.h" + +typedef struct rdpsnd_fake_plugin rdpsndFakePlugin; + +struct rdpsnd_fake_plugin +{ + rdpsndDevicePlugin device; +}; + +static BOOL rdpsnd_fake_open(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format, UINT32 latency) +{ + return TRUE; +} + +static void rdpsnd_fake_close(rdpsndDevicePlugin* device) +{ + +} + +static BOOL rdpsnd_fake_set_volume(rdpsndDevicePlugin* device, UINT32 value) +{ + return TRUE; +} + +static void rdpsnd_fake_free(rdpsndDevicePlugin* device) +{ + rdpsndFakePlugin* fake = (rdpsndFakePlugin*) device; + + if (!fake) + return; + + free(fake); +} + +static BOOL rdpsnd_fake_format_supported(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format) +{ + return TRUE; +} + +static BOOL rdpsnd_fake_set_format(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format, int latency) +{ + return TRUE; +} + +static UINT rdpsnd_fake_play(rdpsndDevicePlugin* device, const BYTE* data, size_t size) +{ + return CHANNEL_RC_OK; +} + +static void rdpsnd_fake_start(rdpsndDevicePlugin* device) +{ + +} + +static COMMAND_LINE_ARGUMENT_A rdpsnd_fake_args[] = +{ + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } +}; + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rdpsnd_fake_parse_addin_args(rdpsndFakePlugin* fake, ADDIN_ARGV* args) +{ + int status; + DWORD flags; + COMMAND_LINE_ARGUMENT_A* arg; + + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + + status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, + rdpsnd_fake_args, flags, fake, NULL, NULL); + if (status < 0) + return ERROR_INVALID_DATA; + + arg = rdpsnd_fake_args; + do + { + if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) + continue; + + CommandLineSwitchStart(arg) + + CommandLineSwitchEnd(arg) + } + while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; +} + +#ifdef BUILTIN_CHANNELS +#define freerdp_rdpsnd_client_subsystem_entry fake_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry +#endif + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +{ + ADDIN_ARGV* args; + rdpsndFakePlugin* fake; + UINT ret; + + fake = (rdpsndFakePlugin*) calloc(1, sizeof(rdpsndFakePlugin)); + if (!fake) + return CHANNEL_RC_NO_MEMORY; + + fake->device.Open = rdpsnd_fake_open; + fake->device.FormatSupported = rdpsnd_fake_format_supported; + fake->device.SetVolume = rdpsnd_fake_set_volume; + fake->device.Play = rdpsnd_fake_play; + fake->device.Start = rdpsnd_fake_start; + fake->device.Close = rdpsnd_fake_close; + fake->device.Free = rdpsnd_fake_free; + + args = pEntryPoints->args; + if (args->argc > 1) + { + ret = rdpsnd_fake_parse_addin_args(fake, args); + if (ret != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "error parsing arguments"); + goto error; + } + } + + ret = CHANNEL_RC_NO_MEMORY; + + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, &fake->device); + return CHANNEL_RC_OK; + +error: + rdpsnd_fake_free(&fake->device); + return ret; +} diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index db4a5086d..092936082 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -837,6 +837,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd) #if defined(WITH_WINMM) { "winmm", ""}, #endif + { "fake", "" } }; ADDIN_ARGV* args; UINT status = ERROR_INTERNAL_ERROR; @@ -853,9 +854,6 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd) if (rdpsnd->subsystem) { - if (strcmp(rdpsnd->subsystem, "fake") == 0) - return CHANNEL_RC_OK; - if ((status = rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args))) { WLog_ERR(TAG, "unable to load the %s subsystem plugin because of error %"PRIu32"",