From 3c9241022a3c62b6ddd71d34b4b2123d405c167c Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Wed, 3 Jul 2019 21:31:52 -0700 Subject: [PATCH 1/8] chansrv: add audin.c/h --- sesman/chansrv/Makefile.am | 4 +- sesman/chansrv/audin.c | 104 +++++++++++++++++++++++++++++++++++++ sesman/chansrv/audin.h | 25 +++++++++ sesman/chansrv/chansrv.c | 3 ++ 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 sesman/chansrv/audin.c create mode 100644 sesman/chansrv/audin.h diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 05007757..293efeca 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -70,7 +70,9 @@ xrdp_chansrv_SOURCES = \ sound.c \ sound.h \ xcommon.c \ - xcommon.h + xcommon.h \ + audin.c \ + audin.h xrdp_chansrv_LDFLAGS = \ $(X_LIBS) diff --git a/sesman/chansrv/audin.c b/sesman/chansrv/audin.c new file mode 100644 index 00000000..17629010 --- /dev/null +++ b/sesman/chansrv/audin.c @@ -0,0 +1,104 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2019 + * + * 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. + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include + +#include "os_calls.h" +#include "chansrv.h" +#include "log.h" + +static struct chansrv_drdynvc_procs g_audin_info; +static int g_audio_chanid = 0; + +/*****************************************************************************/ +static int +audio_send_version(int chan_id) +{ + int error; + struct stream *s; + + LOG(0, ("audio_send_version:")); + make_stream(s); + init_stream(s, 32); + out_uint8(s, 1); /* MSG_SNDIN_VERSION */ + out_uint32_le(s, 1); /* version */ + error = chansrv_drdynvc_data(chan_id, s->data, 5); + free_stream(s); + return error; +} + +/*****************************************************************************/ +static int +audin_open_response(int chan_id, int creation_status) +{ + LOG(0, ("audin_open_response: creation_status %d", creation_status)); + if (creation_status == 0) + { + return audio_send_version(chan_id); + } + return 0; +} + +/*****************************************************************************/ +static int +audin_close_response(int chan_id) +{ + LOG(0, ("audin_close_response:")); + return 0; +} + +/*****************************************************************************/ +static int +audin_data_first(int chan_id, char *data, int bytes, int total_bytes) +{ + LOG(0, ("audin_data_first:")); + return 0; +} + +/*****************************************************************************/ +static int +audin_data(int chan_id, char *data, int bytes) +{ + LOG(0, ("audin_data:")); + g_hexdump(data, bytes); + return 0; +} + +/*****************************************************************************/ +int +audin_init(void) +{ + int error; + + LOG(0, ("audin_init:")); + g_memset(&g_audin_info, 0, sizeof(g_audin_info)); + g_audin_info.open_response = audin_open_response; + g_audin_info.close_response = audin_close_response; + g_audin_info.data_first = audin_data_first; + g_audin_info.data = audin_data; + error = chansrv_drdynvc_open("AUDIO_INPUT", 1, &g_audin_info, + &g_audio_chanid); + LOG(0, ("audin_init: error %d", error)); + return error; +} diff --git a/sesman/chansrv/audin.h b/sesman/chansrv/audin.h new file mode 100644 index 00000000..17cf6f8f --- /dev/null +++ b/sesman/chansrv/audin.h @@ -0,0 +1,25 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2019 + * + * 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. + */ + +#ifndef _AUDIN_H_ +#define _AUDIN_H_ + +int +audin_init(void); + +#endif diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 04a73000..4dde8bef 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -37,6 +37,7 @@ #include "xcommon.h" #include "chansrv_fuse.h" #include "xrdp_sockets.h" +#include "audin.h" static struct trans *g_lis_trans = 0; static struct trans *g_con_trans = 0; @@ -415,6 +416,8 @@ process_message_channel_setup(struct stream *s) rail_init(); } + audin_init(); + return rv; } From a9a823b0dae106d2a73178ca8074632795c4afc9 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 4 Jul 2019 23:52:18 -0700 Subject: [PATCH 2/8] chansrv: audio in partial working --- sesman/chansrv/audin.c | 369 ++++++++++++++++++++++++++++++++++++++++- sesman/chansrv/audin.h | 3 + 2 files changed, 363 insertions(+), 9 deletions(-) diff --git a/sesman/chansrv/audin.c b/sesman/chansrv/audin.c index 17629010..98eda69e 100644 --- a/sesman/chansrv/audin.c +++ b/sesman/chansrv/audin.c @@ -14,6 +14,9 @@ * 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. + * + * MS-RDPEAI + * */ #if defined(HAVE_CONFIG_H) @@ -27,27 +30,328 @@ #include "os_calls.h" #include "chansrv.h" #include "log.h" +#include "xrdp_constants.h" + +#define MSG_SNDIN_VERSION 1 +#define MSG_SNDIN_FORMATS 2 +#define MSG_SNDIN_OPEN 3 +#define MSG_SNDIN_OPEN_REPLY 4 +#define MSG_SNDIN_DATA_INCOMING 5 +#define MSG_SNDIN_DATA 6 +#define MSG_SNDIN_FORMATCHANGE 7 + +#define AUDIN_VERSION 0x00000001 + +#define AUDIN_NAME "AUDIO_INPUT" +#define AUDIN_FLAGS 1 /* WTS_CHANNEL_OPTION_DYNAMIC */ + +struct xr_wave_format_ex +{ + int wFormatTag; + int nChannels; + int nSamplesPerSec; + int nAvgBytesPerSec; + int nBlockAlign; + int wBitsPerSample; + int cbSize; + uint8_t *data; +}; + +static uint8_t g_pcm_44100_data[] = { 0 }; +static struct xr_wave_format_ex g_pcm_44100 = +{ + WAVE_FORMAT_PCM, /* wFormatTag */ + 2, /* num of channels */ + 44100, /* samples per sec */ + 176400, /* avg bytes per sec */ + 4, /* block align */ + 16, /* bits per sample */ + 0, /* data size */ + g_pcm_44100_data /* data */ +}; static struct chansrv_drdynvc_procs g_audin_info; -static int g_audio_chanid = 0; +static int g_audio_chanid; +static struct stream *g_in_s; + +static struct xr_wave_format_ex *g_server_formats[] = +{ + &g_pcm_44100, + NULL +}; + +static struct xr_wave_format_ex **g_client_formats = NULL; + +static int g_current_format = 0; /* index in g_client_formats */ + +/*****************************************************************************/ +static int +cleanup_client_formats(void) +{ + int index; + + if (g_client_formats == NULL) + { + return 0; + } + index = 0; + while (g_client_formats[index] != NULL) + { + g_free(g_client_formats[index]->data); + g_free(g_client_formats[index]); + } + g_free(g_client_formats); + g_client_formats = NULL; + return 0; +} /*****************************************************************************/ static int audio_send_version(int chan_id) { int error; + int bytes; struct stream *s; LOG(0, ("audio_send_version:")); make_stream(s); init_stream(s, 32); - out_uint8(s, 1); /* MSG_SNDIN_VERSION */ - out_uint32_le(s, 1); /* version */ - error = chansrv_drdynvc_data(chan_id, s->data, 5); + out_uint8(s, MSG_SNDIN_VERSION); + out_uint32_le(s, AUDIN_VERSION); + s_mark_end(s); + bytes = (int) (s->end - s->data); + error = chansrv_drdynvc_data(chan_id, s->data, bytes); free_stream(s); return error; } +/*****************************************************************************/ +static int +audio_send_formats(int chan_id) +{ + int error; + int bytes; + int num_formats; + int index; + struct stream *s; + struct xr_wave_format_ex *wf; + + LOG(0, ("audio_send_formats:")); + num_formats = sizeof(g_server_formats) / + sizeof(g_server_formats[0]) - 1; + make_stream(s); + init_stream(s, 8192 * num_formats); + out_uint8(s, MSG_SNDIN_FORMATS); + out_uint32_le(s, num_formats); + out_uint32_le(s, 0); /* cbSizeFormatsPacket */ + for (index = 0; index < num_formats; index++) + { + wf = g_server_formats[index]; + out_uint16_le(s, wf->wFormatTag); + out_uint16_le(s, wf->nChannels); + out_uint32_le(s, wf->nSamplesPerSec); + out_uint32_le(s, wf->nAvgBytesPerSec); + out_uint16_le(s, wf->nBlockAlign); + out_uint16_le(s, wf->wBitsPerSample); + bytes = wf->cbSize; + out_uint16_le(s, bytes); + if (bytes > 0) + { + out_uint8p(s, wf->data, bytes); + } + } + s_mark_end(s); + bytes = (int) (s->end - s->data); + error = chansrv_drdynvc_data(chan_id, s->data, bytes); + free_stream(s); + return error; +} + +/*****************************************************************************/ +static int +audio_send_open(int chan_id) +{ + int error; + int bytes; + struct stream *s; + struct xr_wave_format_ex *wf; + + LOG(0, ("audio_send_open:")); + make_stream(s); + init_stream(s, 8192); + out_uint8(s, MSG_SNDIN_OPEN); + out_uint32_le(s, 2048); /* FramesPerPacket */ + out_uint32_le(s, g_current_format); /* initialFormat */ + wf = g_client_formats[g_current_format]; + out_uint16_le(s, wf->wFormatTag); + out_uint16_le(s, wf->nChannels); + out_uint32_le(s, wf->nSamplesPerSec); + out_uint32_le(s, wf->nAvgBytesPerSec); + out_uint16_le(s, wf->nBlockAlign); + out_uint16_le(s, wf->wBitsPerSample); + bytes = wf->cbSize; + out_uint16_le(s, bytes); + if (bytes > 0) + { + out_uint8p(s, wf->data, bytes); + } + s_mark_end(s); + bytes = (int) (s->end - s->data); + error = chansrv_drdynvc_data(chan_id, s->data, bytes); + free_stream(s); + return error; +} + +/*****************************************************************************/ +static int +audin_process_version(int chan_id, struct stream *s) +{ + int version; + + LOG(0, ("audin_process_version:")); + if (!s_check_rem(s, 4)) + { + LOG(0, ("audin_process_version: parse error")); + return 1; + } + in_uint32_le(s, version); + LOG(0, ("audin_process_version: version %d", version)); + return audio_send_formats(chan_id); +} + +/*****************************************************************************/ +static int +audin_process_formats(int chan_id, struct stream *s) +{ + int index; + int num_formats; + struct xr_wave_format_ex *wf; + + LOG(0, ("audin_process_formats:")); + cleanup_client_formats(); + if (!s_check_rem(s, 8)) + { + LOG(0, ("audin_process_formats: parse error")); + return 1; + } + in_uint32_le(s, num_formats); + in_uint8s(s, 4); /* cbSizeFormatsPacket */ + g_client_formats = g_new0(struct xr_wave_format_ex *, num_formats + 1); + for (index = 0; index < num_formats; index++) + { + if (!s_check_rem(s, 18)) + { + LOG(0, ("audin_process_formats: parse error")); + return 1; + } + wf = g_new0(struct xr_wave_format_ex, 1); + g_client_formats[index] = wf; + in_uint16_le(s, wf->wFormatTag); + in_uint16_le(s, wf->nChannels); + in_uint32_le(s, wf->nSamplesPerSec); + in_uint32_le(s, wf->nAvgBytesPerSec); + in_uint16_le(s, wf->nBlockAlign); + in_uint16_le(s, wf->wBitsPerSample); + in_uint16_le(s, wf->cbSize); + if (wf->cbSize > 0) + { + if (!s_check_rem(s, wf->cbSize)) + { + LOG(0, ("audin_process_formats: parse error")); + return 1; + } + wf->data = g_new0(uint8_t, wf->cbSize); + in_uint8a(s, wf->data, wf->cbSize); + } + } + audio_send_open(chan_id); + return 0; +} + +/*****************************************************************************/ +static int +audin_process_open_reply(int chan_id, struct stream *s) +{ + int result; + + if (!s_check_rem(s, 4)) + { + LOG(0, ("audin_process_open_reply: parse error")); + return 1; + } + in_uint32_le(s, result); + LOG(0, ("audin_process_open_reply: result %d", result)); + return 0; +} + +/*****************************************************************************/ +static int +audin_process_incoming_data(int chan_id, struct stream *s) +{ + LOG(0, ("audin_process_incoming_data:")); + return 0; +} + +/*****************************************************************************/ +static int +audin_process_data(int chan_id, struct stream *s) +{ + int data_bytes; + + data_bytes = (int) (s->end - s->p); + LOG(0, ("audin_process_data: data_bytes %d", data_bytes)); + return 0; +} + +/*****************************************************************************/ +static int +audin_process_format_change(int chan_id, struct stream *s) +{ + LOG(0, ("audin_process_format_change:")); + if (!s_check_rem(s, 4)) + { + LOG(0, ("audin_process_format_change: parse error")); + return 1; + } + in_uint32_le(s, g_current_format); + return 0; +} + +/*****************************************************************************/ +static int +audin_process_msg(int chan_id, struct stream *s) +{ + int code; + + LOG(0, ("audin_process_msg:")); + if (!s_check_rem(s, 1)) + { + LOG(0, ("audin_process_msg: parse error")); + return 1; + } + in_uint8(s, code); + LOG(0, ("audin_process_msg: code %d", code)); + switch (code) + { + case MSG_SNDIN_VERSION: + return audin_process_version(chan_id, s); + case MSG_SNDIN_FORMATS: + return audin_process_formats(chan_id, s); + case MSG_SNDIN_OPEN_REPLY: + return audin_process_open_reply(chan_id, s); + case MSG_SNDIN_DATA_INCOMING: + return audin_process_incoming_data(chan_id, s); + case MSG_SNDIN_DATA: + return audin_process_data(chan_id, s); + case MSG_SNDIN_FORMATCHANGE: + return audin_process_format_change(chan_id, s); + default: + LOG(0, ("audin_process_msg: unprocessed code %d", code)); + break; + } + return 0; +} + /*****************************************************************************/ static int audin_open_response(int chan_id, int creation_status) @@ -68,21 +372,65 @@ audin_close_response(int chan_id) return 0; } +/*****************************************************************************/ +static int +audin_data_fragment(int chan_id, char *data, int bytes) +{ + int rv; + int left; + + LOG(0, ("audin_data_fragment:")); + if (!s_check_rem(g_in_s, bytes)) + { + left = (int) (g_in_s->end - g_in_s->p); + LOG(0, ("audin_data_fragment: error bytes %d left %d", bytes, left)); + return 1; + } + out_uint8a(g_in_s, data, bytes); + if (g_in_s->p == g_in_s->end) + { + g_in_s->p = g_in_s->data; + rv = audin_process_msg(chan_id, g_in_s); + free_stream(g_in_s); + g_in_s = NULL; + return rv; + } + return 0; +} + /*****************************************************************************/ static int audin_data_first(int chan_id, char *data, int bytes, int total_bytes) { LOG(0, ("audin_data_first:")); - return 0; + if (g_in_s != NULL) + { + LOG(0, ("audin_data_first: warning g_in_s is not nil")); + free_stream(g_in_s); + } + make_stream(g_in_s); + init_stream(g_in_s, total_bytes); + g_in_s->end = g_in_s->data + total_bytes; + return audin_data_fragment(chan_id, data, bytes); } /*****************************************************************************/ static int audin_data(int chan_id, char *data, int bytes) { + struct stream ls; + LOG(0, ("audin_data:")); - g_hexdump(data, bytes); - return 0; + //g_hexdump(data, bytes); + if (g_in_s == NULL) + { + g_memset(&ls, 0, sizeof(ls)); + ls.data = data; + ls.p = ls.data; + ls.end = ls.p + bytes; + return audin_process_msg(chan_id, &ls); + } + return audin_data_fragment(chan_id, data, bytes); } /*****************************************************************************/ @@ -97,8 +445,11 @@ audin_init(void) g_audin_info.close_response = audin_close_response; g_audin_info.data_first = audin_data_first; g_audin_info.data = audin_data; - error = chansrv_drdynvc_open("AUDIO_INPUT", 1, &g_audin_info, - &g_audio_chanid); + g_audio_chanid = 0; + g_in_s = NULL; + error = chansrv_drdynvc_open(AUDIN_NAME, AUDIN_FLAGS, + &g_audin_info, /* callback functions */ + &g_audio_chanid); /* chansrv chan_id */ LOG(0, ("audin_init: error %d", error)); return error; } diff --git a/sesman/chansrv/audin.h b/sesman/chansrv/audin.h index 17cf6f8f..d13efd08 100644 --- a/sesman/chansrv/audin.h +++ b/sesman/chansrv/audin.h @@ -14,6 +14,9 @@ * 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. + * + * MS-RDPEAI + * */ #ifndef _AUDIN_H_ From ae40ff27c8604cc87ea02bf74dc294eaac0f62b2 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sun, 7 Jul 2019 22:05:46 -0700 Subject: [PATCH 3/8] chansrv: audin close should chose channel --- sesman/chansrv/audin.c | 37 ++++++++++++++++++++++++++++++++++--- sesman/chansrv/audin.h | 6 ++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/sesman/chansrv/audin.c b/sesman/chansrv/audin.c index 98eda69e..cb0da874 100644 --- a/sesman/chansrv/audin.c +++ b/sesman/chansrv/audin.c @@ -369,6 +369,10 @@ static int audin_close_response(int chan_id) { LOG(0, ("audin_close_response:")); + g_audio_chanid = 0; + cleanup_client_formats(); + free_stream(g_in_s); + g_in_s = NULL; return 0; } @@ -437,8 +441,6 @@ audin_data(int chan_id, char *data, int bytes) int audin_init(void) { - int error; - LOG(0, ("audin_init:")); g_memset(&g_audin_info, 0, sizeof(g_audin_info)); g_audin_info.open_response = audin_open_response; @@ -447,9 +449,38 @@ audin_init(void) g_audin_info.data = audin_data; g_audio_chanid = 0; g_in_s = NULL; + return 0; +} + +/*****************************************************************************/ +int +audin_deinit(void) +{ + return 0; +} + +/*****************************************************************************/ +int +audin_start(void) +{ + int error; + + LOG(0, ("audin_start:")); + if (g_audio_chanid != 0) + { + return 1; + } error = chansrv_drdynvc_open(AUDIN_NAME, AUDIN_FLAGS, &g_audin_info, /* callback functions */ &g_audio_chanid); /* chansrv chan_id */ - LOG(0, ("audin_init: error %d", error)); + LOG(0, ("audin_start: error %d", error)); return error; } + +/*****************************************************************************/ +int +audin_stop(void) +{ + chansrv_drdynvc_close(g_audio_chanid); + return 0; +} diff --git a/sesman/chansrv/audin.h b/sesman/chansrv/audin.h index d13efd08..7569bc4f 100644 --- a/sesman/chansrv/audin.h +++ b/sesman/chansrv/audin.h @@ -24,5 +24,11 @@ int audin_init(void); +int +audin_deinit(void); +int +audin_start(void); +int +audin_stop(void); #endif From c5798df0bd0c4b49600e5dede32b080474515935 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 8 Jul 2019 18:25:59 -0700 Subject: [PATCH 4/8] chansrv: hook up audin --- sesman/chansrv/audin.c | 46 +++++++++++++++++++++++++++++++++++------- sesman/chansrv/sound.c | 11 ++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/sesman/chansrv/audin.c b/sesman/chansrv/audin.c index cb0da874..76958414 100644 --- a/sesman/chansrv/audin.c +++ b/sesman/chansrv/audin.c @@ -31,6 +31,7 @@ #include "chansrv.h" #include "log.h" #include "xrdp_constants.h" +#include "fifo.h" #define MSG_SNDIN_VERSION 1 #define MSG_SNDIN_FORMATS 2 @@ -45,6 +46,9 @@ #define AUDIN_NAME "AUDIO_INPUT" #define AUDIN_FLAGS 1 /* WTS_CHANNEL_OPTION_DYNAMIC */ +extern FIFO g_in_fifo; /* in sound.c */ +extern int g_bytes_in_fifo; /* in sound.c */ + struct xr_wave_format_ex { int wFormatTag; @@ -99,6 +103,7 @@ cleanup_client_formats(void) { g_free(g_client_formats[index]->data); g_free(g_client_formats[index]); + index++; } g_free(g_client_formats); g_client_formats = NULL; @@ -147,17 +152,19 @@ audio_send_formats(int chan_id) for (index = 0; index < num_formats; index++) { wf = g_server_formats[index]; + LOG(0, ("audio_send_formats: sending format wFormatTag 0x%4.4x " + "nChannels %d nSamplesPerSec %d", + wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec)); out_uint16_le(s, wf->wFormatTag); out_uint16_le(s, wf->nChannels); out_uint32_le(s, wf->nSamplesPerSec); out_uint32_le(s, wf->nAvgBytesPerSec); out_uint16_le(s, wf->nBlockAlign); out_uint16_le(s, wf->wBitsPerSample); - bytes = wf->cbSize; - out_uint16_le(s, bytes); - if (bytes > 0) + out_uint16_le(s, wf->cbSize); + if (wf->cbSize > 0) { - out_uint8p(s, wf->data, bytes); + out_uint8p(s, wf->data, wf->cbSize); } } s_mark_end(s); @@ -253,6 +260,9 @@ audin_process_formats(int chan_id, struct stream *s) in_uint16_le(s, wf->nBlockAlign); in_uint16_le(s, wf->wBitsPerSample); in_uint16_le(s, wf->cbSize); + LOG(0, ("audin_process_formats: recved format wFormatTag 0x%4.4x " + "nChannels %d nSamplesPerSec %d", + wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec)); if (wf->cbSize > 0) { if (!s_check_rem(s, wf->cbSize)) @@ -280,7 +290,7 @@ audin_process_open_reply(int chan_id, struct stream *s) return 1; } in_uint32_le(s, result); - LOG(0, ("audin_process_open_reply: result %d", result)); + LOG(0, ("audin_process_open_reply: result 0x%8.8x", result)); return 0; } @@ -297,9 +307,18 @@ static int audin_process_data(int chan_id, struct stream *s) { int data_bytes; + struct stream *ls; data_bytes = (int) (s->end - s->p); LOG(0, ("audin_process_data: data_bytes %d", data_bytes)); + + xstream_new(ls, data_bytes); + g_memcpy(ls->data, s->p, data_bytes); + ls->p += data_bytes; + s_mark_end(ls); + fifo_insert(&g_in_fifo, (void *) ls); + g_bytes_in_fifo += data_bytes; + return 0; } @@ -314,6 +333,8 @@ audin_process_format_change(int chan_id, struct stream *s) return 1; } in_uint32_le(s, g_current_format); + LOG(0, ("audin_process_format_change: g_current_format %d", + g_current_format)); return 0; } @@ -356,7 +377,7 @@ audin_process_msg(int chan_id, struct stream *s) static int audin_open_response(int chan_id, int creation_status) { - LOG(0, ("audin_open_response: creation_status %d", creation_status)); + LOG(0, ("audin_open_response: creation_status 0x%8.8x", creation_status)); if (creation_status == 0) { return audio_send_version(chan_id); @@ -456,6 +477,7 @@ audin_init(void) int audin_deinit(void) { + LOG(0, ("audin_deinit:")); return 0; } @@ -464,16 +486,25 @@ int audin_start(void) { int error; + struct stream* s; LOG(0, ("audin_start:")); if (g_audio_chanid != 0) { return 1; } + + /* if there is any data in FIFO, discard it */ + while ((s = (struct stream *) fifo_remove(&g_in_fifo)) != NULL) + { + xstream_free(s); + } + g_bytes_in_fifo = 0; + error = chansrv_drdynvc_open(AUDIN_NAME, AUDIN_FLAGS, &g_audin_info, /* callback functions */ &g_audio_chanid); /* chansrv chan_id */ - LOG(0, ("audin_start: error %d", error)); + LOG(0, ("audin_start: error %d g_audio_chanid %d", error, g_audio_chanid)); return error; } @@ -481,6 +512,7 @@ audin_start(void) int audin_stop(void) { + LOG(0, ("audin_stop:")); chansrv_drdynvc_close(g_audio_chanid); return 0; } diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index 7120ec22..5e65ad3a 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -35,6 +35,7 @@ #include "xrdp_sockets.h" #include "chansrv_common.h" #include "list.h" +#include "audin.h" #if defined(XRDP_FDK_AAC) #include @@ -71,8 +72,8 @@ static struct trans *g_audio_c_trans_in = 0; /* connection */ static int g_training_sent_time = 0; static int g_cBlockNo = 0; static int g_bytes_in_stream = 0; -static FIFO g_in_fifo; -static int g_bytes_in_fifo = 0; +FIFO g_in_fifo; +int g_bytes_in_fifo = 0; static int g_time_diff = 0; static int g_best_time_diff = 0; @@ -1772,11 +1773,13 @@ sound_sndsrvr_source_data_in(struct trans *trans) } else if (cmd == PA_CMD_START_REC) { - sound_input_start_recording(); + //sound_input_start_recording(); + audin_start(); } else if (cmd == PA_CMD_STOP_REC) { - sound_input_stop_recording(); + //sound_input_stop_recording(); + audin_stop(); } xstream_free(s); From 8aedd317623f0ce9b5a74d9efac4de871659e47a Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 8 Jul 2019 22:03:27 -0700 Subject: [PATCH 5/8] chansrv: use rdpsnd record if supported, else try AUDIO_INPUT(MS-RDPEAI) --- sesman/chansrv/sound.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index 5e65ad3a..f94e9562 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -241,6 +241,8 @@ static struct xr_wave_format_ex *g_wave_inp_formats[] = 0 }; +static int g_rdpsnd_can_rec = 0; + static int g_client_input_format_index = 0; static int g_server_input_format_index = 0; @@ -1561,6 +1563,7 @@ sound_process_input_formats(struct stream *s, int size) LOG(10, ("sound_process_input_formats: size=%d", size)); + g_rdpsnd_can_rec = 1; in_uint8s(s, 8); /* skip 8 bytes */ in_uint16_le(s, num_formats); in_uint8s(s, 2); /* skip version */ @@ -1773,13 +1776,25 @@ sound_sndsrvr_source_data_in(struct trans *trans) } else if (cmd == PA_CMD_START_REC) { - //sound_input_start_recording(); - audin_start(); + if (g_rdpsnd_can_rec) + { + sound_input_start_recording(); + } + else + { + audin_start(); + } } else if (cmd == PA_CMD_STOP_REC) { - //sound_input_stop_recording(); - audin_stop(); + if (g_rdpsnd_can_rec) + { + sound_input_stop_recording(); + } + else + { + audin_stop(); + } } xstream_free(s); From 933394c6be98e9be326ba8fc4434bda0caf3e457 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 8 Jul 2019 22:40:31 -0700 Subject: [PATCH 6/8] chansrv: remove excessive logging --- sesman/chansrv/audin.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sesman/chansrv/audin.c b/sesman/chansrv/audin.c index 76958414..1b87fc8a 100644 --- a/sesman/chansrv/audin.c +++ b/sesman/chansrv/audin.c @@ -298,7 +298,7 @@ audin_process_open_reply(int chan_id, struct stream *s) static int audin_process_incoming_data(int chan_id, struct stream *s) { - LOG(0, ("audin_process_incoming_data:")); + LOG(10, ("audin_process_incoming_data:")); return 0; } @@ -310,7 +310,7 @@ audin_process_data(int chan_id, struct stream *s) struct stream *ls; data_bytes = (int) (s->end - s->p); - LOG(0, ("audin_process_data: data_bytes %d", data_bytes)); + LOG(10, ("audin_process_data: data_bytes %d", data_bytes)); xstream_new(ls, data_bytes); g_memcpy(ls->data, s->p, data_bytes); @@ -344,14 +344,14 @@ audin_process_msg(int chan_id, struct stream *s) { int code; - LOG(0, ("audin_process_msg:")); + LOG(10, ("audin_process_msg:")); if (!s_check_rem(s, 1)) { LOG(0, ("audin_process_msg: parse error")); return 1; } in_uint8(s, code); - LOG(0, ("audin_process_msg: code %d", code)); + LOG(10, ("audin_process_msg: code %d", code)); switch (code) { case MSG_SNDIN_VERSION: @@ -404,7 +404,7 @@ audin_data_fragment(int chan_id, char *data, int bytes) int rv; int left; - LOG(0, ("audin_data_fragment:")); + LOG(10, ("audin_data_fragment:")); if (!s_check_rem(g_in_s, bytes)) { left = (int) (g_in_s->end - g_in_s->p); @@ -427,7 +427,7 @@ audin_data_fragment(int chan_id, char *data, int bytes) static int audin_data_first(int chan_id, char *data, int bytes, int total_bytes) { - LOG(0, ("audin_data_first:")); + LOG(10, ("audin_data_first:")); if (g_in_s != NULL) { LOG(0, ("audin_data_first: warning g_in_s is not nil")); @@ -445,7 +445,7 @@ audin_data(int chan_id, char *data, int bytes) { struct stream ls; - LOG(0, ("audin_data:")); + LOG(10, ("audin_data:")); //g_hexdump(data, bytes); if (g_in_s == NULL) { From 417bb71abf7976f27d2a653507d1897950445124 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 8 Jul 2019 22:45:58 -0700 Subject: [PATCH 7/8] chansrv: env var to disable rdpsnd record --- sesman/chansrv/sound.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index f94e9562..87e65c50 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -1563,7 +1563,10 @@ sound_process_input_formats(struct stream *s, int size) LOG(10, ("sound_process_input_formats: size=%d", size)); - g_rdpsnd_can_rec = 1; + if (g_getenv("XRDP_NO_RDPSND_REC") == NULL) + { + g_rdpsnd_can_rec = 1; + } in_uint8s(s, 8); /* skip 8 bytes */ in_uint16_le(s, num_formats); in_uint8s(s, 2); /* skip version */ From cf67dd56bfa73352180a8d4af89af8a16dc7c2fe Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Wed, 10 Jul 2019 11:18:07 -0700 Subject: [PATCH 8/8] chansrv: no logic change, fix typo --- sesman/chansrv/audin.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/sesman/chansrv/audin.c b/sesman/chansrv/audin.c index 1b87fc8a..1ca2de30 100644 --- a/sesman/chansrv/audin.c +++ b/sesman/chansrv/audin.c @@ -75,7 +75,7 @@ static struct xr_wave_format_ex g_pcm_44100 = }; static struct chansrv_drdynvc_procs g_audin_info; -static int g_audio_chanid; +static int g_audin_chanid; static struct stream *g_in_s; static struct xr_wave_format_ex *g_server_formats[] = @@ -112,13 +112,13 @@ cleanup_client_formats(void) /*****************************************************************************/ static int -audio_send_version(int chan_id) +audin_send_version(int chan_id) { int error; int bytes; struct stream *s; - LOG(0, ("audio_send_version:")); + LOG(0, ("audin_send_version:")); make_stream(s); init_stream(s, 32); out_uint8(s, MSG_SNDIN_VERSION); @@ -132,7 +132,7 @@ audio_send_version(int chan_id) /*****************************************************************************/ static int -audio_send_formats(int chan_id) +audin_send_formats(int chan_id) { int error; int bytes; @@ -141,7 +141,7 @@ audio_send_formats(int chan_id) struct stream *s; struct xr_wave_format_ex *wf; - LOG(0, ("audio_send_formats:")); + LOG(0, ("audin_send_formats:")); num_formats = sizeof(g_server_formats) / sizeof(g_server_formats[0]) - 1; make_stream(s); @@ -152,7 +152,7 @@ audio_send_formats(int chan_id) for (index = 0; index < num_formats; index++) { wf = g_server_formats[index]; - LOG(0, ("audio_send_formats: sending format wFormatTag 0x%4.4x " + LOG(0, ("audin_send_formats: sending format wFormatTag 0x%4.4x " "nChannels %d nSamplesPerSec %d", wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec)); out_uint16_le(s, wf->wFormatTag); @@ -176,14 +176,14 @@ audio_send_formats(int chan_id) /*****************************************************************************/ static int -audio_send_open(int chan_id) +audin_send_open(int chan_id) { int error; int bytes; struct stream *s; struct xr_wave_format_ex *wf; - LOG(0, ("audio_send_open:")); + LOG(0, ("audin_send_open:")); make_stream(s); init_stream(s, 8192); out_uint8(s, MSG_SNDIN_OPEN); @@ -223,7 +223,7 @@ audin_process_version(int chan_id, struct stream *s) } in_uint32_le(s, version); LOG(0, ("audin_process_version: version %d", version)); - return audio_send_formats(chan_id); + return audin_send_formats(chan_id); } /*****************************************************************************/ @@ -274,7 +274,7 @@ audin_process_formats(int chan_id, struct stream *s) in_uint8a(s, wf->data, wf->cbSize); } } - audio_send_open(chan_id); + audin_send_open(chan_id); return 0; } @@ -380,7 +380,7 @@ audin_open_response(int chan_id, int creation_status) LOG(0, ("audin_open_response: creation_status 0x%8.8x", creation_status)); if (creation_status == 0) { - return audio_send_version(chan_id); + return audin_send_version(chan_id); } return 0; } @@ -390,7 +390,7 @@ static int audin_close_response(int chan_id) { LOG(0, ("audin_close_response:")); - g_audio_chanid = 0; + g_audin_chanid = 0; cleanup_client_formats(); free_stream(g_in_s); g_in_s = NULL; @@ -468,7 +468,7 @@ audin_init(void) g_audin_info.close_response = audin_close_response; g_audin_info.data_first = audin_data_first; g_audin_info.data = audin_data; - g_audio_chanid = 0; + g_audin_chanid = 0; g_in_s = NULL; return 0; } @@ -489,7 +489,7 @@ audin_start(void) struct stream* s; LOG(0, ("audin_start:")); - if (g_audio_chanid != 0) + if (g_audin_chanid != 0) { return 1; } @@ -503,8 +503,8 @@ audin_start(void) error = chansrv_drdynvc_open(AUDIN_NAME, AUDIN_FLAGS, &g_audin_info, /* callback functions */ - &g_audio_chanid); /* chansrv chan_id */ - LOG(0, ("audin_start: error %d g_audio_chanid %d", error, g_audio_chanid)); + &g_audin_chanid); /* chansrv chan_id */ + LOG(0, ("audin_start: error %d g_audin_chanid %d", error, g_audin_chanid)); return error; } @@ -513,6 +513,6 @@ int audin_stop(void) { LOG(0, ("audin_stop:")); - chansrv_drdynvc_close(g_audio_chanid); + chansrv_drdynvc_close(g_audin_chanid); return 0; }