rdpsnd: subsystems: Add proxy subsystem
authorkubistika <kmizrachi18@gmail.com>
Tue, 13 Aug 2019 08:27:46 +0000 (11:27 +0300)
committerakallabeth <akallabeth@users.noreply.github.com>
Thu, 29 Aug 2019 12:39:17 +0000 (14:39 +0200)
channels/rdpsnd/client/CMakeLists.txt
channels/rdpsnd/client/proxy/CMakeLists.txt [new file with mode: 0644]
channels/rdpsnd/client/proxy/rdpsnd_proxy.c [new file with mode: 0644]

index e66f23a..1860fd8 100644 (file)
@@ -57,4 +57,8 @@ if(WITH_OPENSLES)
        add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "opensles" "")
 endif()
 
+if (WITH_SERVER)
+       add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "proxy" "")
+endif()
+
 add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "fake" "")
diff --git a/channels/rdpsnd/client/proxy/CMakeLists.txt b/channels/rdpsnd/client/proxy/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2d40750
--- /dev/null
@@ -0,0 +1,33 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# Copyright 2019 Armin Novak <armin.novak@thincast.com>
+# 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" "proxy" "")
+
+set(${MODULE_PREFIX}_SRCS
+       rdpsnd_proxy.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/proxy")
diff --git a/channels/rdpsnd/client/proxy/rdpsnd_proxy.c b/channels/rdpsnd/client/proxy/rdpsnd_proxy.c
new file mode 100644 (file)
index 0000000..16c4edf
--- /dev/null
@@ -0,0 +1,149 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * FreeRDP rdpsnd proxy subsystem
+ *
+ * Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <winpr/crt.h>
+#include <winpr/stream.h>
+#include <winpr/cmdline.h>
+#include <winpr/sysinfo.h>
+#include <freerdp/types.h>
+#include <freerdp/server/rdpsnd.h>
+#include <freerdp/client/rdpsnd.h>
+
+#include "rdpsnd_main.h"
+#include "../../../../server/proxy/pf_context.h"
+
+typedef struct rdpsnd_proxy_plugin rdpsndProxyPlugin;
+
+struct rdpsnd_proxy_plugin
+{
+       rdpsndDevicePlugin device;
+       RdpsndServerContext* rdpsnd_server;
+};
+
+static BOOL rdpsnd_proxy_open(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format, UINT32 latency)
+{
+       rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device;
+
+       /* update proxy's rdpsnd server latency */
+       proxy->rdpsnd_server->latency = latency;
+       return TRUE;
+}
+
+static void rdpsnd_proxy_close(rdpsndDevicePlugin* device)
+{
+       /* do nothing */
+}
+
+static BOOL rdpsnd_proxy_set_volume(rdpsndDevicePlugin* device, UINT32 value)
+{
+       rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device;
+       proxy->rdpsnd_server->SetVolume(proxy->rdpsnd_server, value, value);
+       return TRUE;
+}
+
+static void rdpsnd_proxy_free(rdpsndDevicePlugin* device)
+{
+       rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*) device;
+
+       if (!proxy)
+               return;
+
+       free(proxy);
+}
+
+static BOOL rdpsnd_proxy_format_supported(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format)
+{
+       rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device;
+
+       /* use the same format that proxy's server used */
+       if (proxy->rdpsnd_server->selected_client_format == format->wFormatTag)
+               return TRUE;
+
+       return FALSE;
+}
+
+static UINT rdpsnd_proxy_play(rdpsndDevicePlugin* device, const BYTE* data, size_t size)
+{
+       rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device;
+       UINT64 start = GetTickCount();
+       proxy->rdpsnd_server->SendSamples(proxy->rdpsnd_server, data, size / 4, start);
+       return GetTickCount() - start;
+}
+
+static void rdpsnd_proxy_start(rdpsndDevicePlugin* device)
+{
+       /* do nothing */
+}
+
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+
+
+#ifdef BUILTIN_CHANNELS
+#define freerdp_rdpsnd_client_subsystem_entry  proxy_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;
+       rdpsndProxyPlugin* proxy;
+       pClientContext* pc;
+       proxy = (rdpsndProxyPlugin*) calloc(1, sizeof(rdpsndProxyPlugin));
+
+       if (!proxy)
+               return CHANNEL_RC_NO_MEMORY;
+
+       proxy->device.Open = rdpsnd_proxy_open;
+       proxy->device.FormatSupported = rdpsnd_proxy_format_supported;
+       proxy->device.SetVolume = rdpsnd_proxy_set_volume;
+       proxy->device.Play = rdpsnd_proxy_play;
+       proxy->device.Start = rdpsnd_proxy_start;
+       proxy->device.Close = rdpsnd_proxy_close;
+       proxy->device.Free = rdpsnd_proxy_free;
+       args = pEntryPoints->args;
+
+       pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, &proxy->device);
+       pc = (pClientContext*) freerdp_rdpsnd_get_context(pEntryPoints->rdpsnd);
+       if (pc == NULL)
+       {
+               free(proxy);
+               return ERROR_INTERNAL_ERROR;
+       }
+
+       proxy->rdpsnd_server = pc->pdata->ps->rdpsnd;
+       return CHANNEL_RC_OK;
+}