diff --git a/channels/audin/client/CMakeLists.txt b/channels/audin/client/CMakeLists.txt index 07e6df705..81b9cbb4e 100644 --- a/channels/audin/client/CMakeLists.txt +++ b/channels/audin/client/CMakeLists.txt @@ -33,6 +33,10 @@ install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPT set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") +if(WITH_OSS) + add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "oss" "") +endif() + if(WITH_ALSA) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "") endif() diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index 92cdb36bf..d197476fc 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -376,7 +376,7 @@ static void audin_alsa_close(IAudinDevice* device) COMMAND_LINE_ARGUMENT_A audin_alsa_args[] = { - { "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; @@ -387,7 +387,7 @@ static void audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg COMMAND_LINE_ARGUMENT_A* arg; AudinALSADevice* alsa = (AudinALSADevice*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_alsa_args, flags, alsa, NULL, NULL); @@ -400,7 +400,7 @@ static void audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "audio-dev") + CommandLineSwitchCase(arg, "dev") { alsa->device_name = _strdup(arg->Value); } diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 35a15824e..8ec37f7c1 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -97,7 +97,7 @@ static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, w Stream_Read_UINT32(s, Version); - DEBUG_DVC("Version=%d", Version); + DEBUG_DVC("process_version: Version=%d", Version); out = Stream_New(NULL, 5); Stream_Write_UINT8(out, MSG_SNDIN_VERSION); @@ -130,7 +130,7 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w UINT32 cbSizeFormatsPacket; Stream_Read_UINT32(s, NumFormats); - DEBUG_DVC("NumFormats %d", NumFormats); + DEBUG_DVC("process_formats: NumFormats %d", NumFormats); if ((NumFormats < 1) || (NumFormats > 1000)) { WLog_ERR(TAG, "bad NumFormats %d", NumFormats); @@ -158,7 +158,7 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w format.data = Stream_Pointer(s); Stream_Seek(s, format.cbSize); - DEBUG_DVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d " + DEBUG_DVC("process_formats: wFormatTag=%d nChannels=%d nSamplesPerSec=%d " "nBlockAlign=%d wBitsPerSample=%d cbSize=%d", format.wFormatTag, format.nChannels, format.nSamplesPerSec, format.nBlockAlign, format.wBitsPerSample, format.cbSize); @@ -171,7 +171,7 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w continue; if (audin->device && audin->device->FormatSupported(audin->device, &format)) { - DEBUG_DVC("format ok"); + DEBUG_DVC("process_formats: format ok"); /* Store the agreed format in the corresponding index */ callback->formats[callback->formats_count++] = format; @@ -257,7 +257,7 @@ static int audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStr Stream_Read_UINT32(s, FramesPerPacket); Stream_Read_UINT32(s, initialFormat); - DEBUG_DVC("FramesPerPacket=%d initialFormat=%d", + DEBUG_DVC("process_open: FramesPerPacket=%d initialFormat=%d", FramesPerPacket, initialFormat); if (initialFormat >= (UINT32) callback->formats_count) @@ -289,7 +289,7 @@ static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallb Stream_Read_UINT32(s, NewFormat); - DEBUG_DVC("NewFormat=%d", NewFormat); + DEBUG_DVC("process_format_change: NewFormat=%d", NewFormat); if (NewFormat >= (UINT32) callback->formats_count) { @@ -319,7 +319,7 @@ static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, Stream_Read_UINT8(data, MessageId); - DEBUG_DVC("MessageId=0x%x", MessageId); + DEBUG_DVC("on_data_received: MessageId=0x%x", MessageId); switch (MessageId) { @@ -353,7 +353,7 @@ static int audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; - DEBUG_DVC(""); + DEBUG_DVC("on_close"); if (audin->device) IFCALL(audin->device->Close, audin->device); @@ -371,7 +371,7 @@ static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallba AUDIN_CHANNEL_CALLBACK* callback; AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback; - DEBUG_DVC(""); + DEBUG_DVC("on_new_channel_connection"); callback = (AUDIN_CHANNEL_CALLBACK*) malloc(sizeof(AUDIN_CHANNEL_CALLBACK)); ZeroMemory(callback, sizeof(AUDIN_CHANNEL_CALLBACK)); @@ -391,7 +391,7 @@ static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; - DEBUG_DVC(""); + DEBUG_DVC("plugin_initialize"); audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) malloc(sizeof(AUDIN_LISTENER_CALLBACK)); ZeroMemory(audin->listener_callback, sizeof(AUDIN_LISTENER_CALLBACK)); @@ -408,7 +408,7 @@ static int audin_plugin_terminated(IWTSPlugin* pPlugin) { AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; - DEBUG_DVC(""); + DEBUG_DVC("plugin_terminated"); if (audin->device) { @@ -438,7 +438,7 @@ static void audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi return; } - DEBUG_DVC("device registered."); + DEBUG_DVC("register_device_plugin: device registered."); audin->device = device; } @@ -589,6 +589,15 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } #endif +#if defined(WITH_OSS) + if (!audin->device) + { + audin_set_subsystem(audin, "oss"); + audin_set_device_name(audin, "default"); + audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args); + } +#endif + #if defined(WITH_ALSA) if (!audin->device) { diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index 54d601d20..8c289431d 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -333,7 +333,7 @@ static void audin_opensles_close(IAudinDevice* device) static COMMAND_LINE_ARGUMENT_A audin_opensles_args[] = { - { "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "", + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; @@ -348,7 +348,7 @@ static int audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, DEBUG_DVC("device=%p, args=%p", device, args); - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_opensles_args, flags, opensles, NULL, NULL); @@ -364,7 +364,7 @@ static int audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "audio-dev") + CommandLineSwitchCase(arg, "dev") { opensles->device_name = _strdup(arg->Value); } diff --git a/channels/audin/client/oss/CMakeLists.txt b/channels/audin/client/oss/CMakeLists.txt new file mode 100644 index 000000000..1b34fd0de --- /dev/null +++ b/channels/audin/client/oss/CMakeLists.txt @@ -0,0 +1,35 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright (c) 2015 Rozhuk Ivan +# +# 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("audin" "oss" "") + +set(${MODULE_PREFIX}_SRCS + audin_oss.c) + +include_directories(..) +include_directories(${OSS_INCLUDE_DIRS}) + +add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") + + + +set(${MODULE_PREFIX}_LIBS freerdp ${OSS_LIBRARIES}) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets) + diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c new file mode 100644 index 000000000..b4f23c377 --- /dev/null +++ b/channels/audin/client/oss/audin_oss.c @@ -0,0 +1,342 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Input Redirection Virtual Channel - OSS implementation + * + * Copyright (c) 2015 Rozhuk Ivan + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "audin_main.h" + +typedef struct _AudinOSSDevice { + IAudinDevice iface; + + FREERDP_DSP_CONTEXT* dsp_context; + + HANDLE thread; + HANDLE stopEvent; + + audinFormat format; + UINT32 FramesPerPacket; + int dev_unit; + + AudinReceive receive; + void* user_data; +} AudinOSSDevice; + +#define OSS_LOG_ERR(_text, _error) \ + if (_error != 0) \ + WLog_ERR(TAG, "%s: %i - %s\n", _text, _error, strerror(_error)); + + +static int audin_oss_get_format(audinFormat *format) { + + switch (format->wFormatTag) { + case WAVE_FORMAT_PCM: + switch (format->wBitsPerSample) { + case 8: + return AFMT_S8; + case 16: + return AFMT_S16_LE; + } + break; + case WAVE_FORMAT_ALAW: + return AFMT_A_LAW; +#if 0 /* This does not work on my desktop. */ + case WAVE_FORMAT_MULAW: + return AFMT_MU_LAW; +#endif + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + return AFMT_S16_LE; + } + + return 0; +} + +static BOOL audin_oss_format_supported(IAudinDevice *device, audinFormat *format) { + int req_fmt = 0; + AudinOSSDevice *oss = (AudinOSSDevice*)device; + + if (device == NULL || format == NULL) + return FALSE; + + switch (format->wFormatTag) { + case WAVE_FORMAT_PCM: + if (format->cbSize != 0 || + format->nSamplesPerSec > 48000 || + (format->wBitsPerSample != 8 && format->wBitsPerSample != 16) || + (format->nChannels != 1 && format->nChannels != 2)) + return FALSE; + break; + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + if (format->nSamplesPerSec > 48000 || + format->wBitsPerSample != 4 || + (format->nChannels != 1 && format->nChannels != 2)) + return FALSE; + break; + } + + req_fmt = audin_oss_get_format(format); + if (req_fmt == 0) + return FALSE; + + return TRUE; +} + +static void audin_oss_set_format(IAudinDevice *device, audinFormat *format, UINT32 FramesPerPacket) { + AudinOSSDevice *oss = (AudinOSSDevice*)device; + + if (device == NULL || format == NULL) + return; + + oss->FramesPerPacket = FramesPerPacket; + CopyMemory(&(oss->format), format, sizeof(audinFormat)); + switch (format->wFormatTag) { + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + oss->FramesPerPacket *= 4; /* Compression ratio. */ + oss->format.wBitsPerSample *= 4; + break; + } +} + +static void *audin_oss_thread_func(void *arg) +{ + char dev_name[PATH_MAX] = "/dev/dsp"; + int pcm_handle = -1; + BYTE *buffer = NULL, *encoded_data; + int tmp, buffer_size, encoded_size; + AudinOSSDevice *oss = (AudinOSSDevice*)arg; + + if (arg == NULL) + goto err_out; + + if (oss->dev_unit != -1) + snprintf(dev_name, (PATH_MAX - 1), "/dev/dsp%i", oss->dev_unit); + WLog_INFO(TAG, "open: %s", dev_name); + if ((pcm_handle = open(dev_name, O_RDONLY)) < 0) { + OSS_LOG_ERR("sound dev open failed", errno); + goto err_out; + } +#if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_INPUT flag. */ + tmp = 0; + if (ioctl(pcm_handle, SNDCTL_DSP_GETCAPS, &tmp) == -1) { + OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno); + } else if ((tmp & PCM_CAP_INPUT) == 0) { + OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP); + goto err_out; + } +#endif + /* Set format. */ + tmp = audin_oss_get_format(&oss->format); + if (ioctl(pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1) + OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed", errno); + tmp = oss->format.nChannels; + if (ioctl(pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1) + OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed", errno); + tmp = oss->format.nSamplesPerSec; + if (ioctl(pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1) + OSS_LOG_ERR("SNDCTL_DSP_SPEED failed", errno); + tmp = oss->format.nBlockAlign; + if (ioctl(pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) + OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno); + + buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8)); + buffer = (BYTE*)malloc((buffer_size + sizeof(void*))); + if (NULL == buffer) { + OSS_LOG_ERR("malloc() fail", errno); + goto err_out; + } + ZeroMemory(buffer, buffer_size); + + freerdp_dsp_context_reset_adpcm(oss->dsp_context); + + while (WaitForSingleObject(oss->stopEvent, 0) != WAIT_OBJECT_0) { + tmp = read(pcm_handle, buffer, buffer_size); + if (tmp < 0) { /* Error happen. */ + OSS_LOG_ERR("read() error", errno); + continue; + } + if (tmp < buffer_size) /* Not enouth data. */ + continue; + /* Process. */ + switch (oss->format.wFormatTag) { + case WAVE_FORMAT_ADPCM: + oss->dsp_context->encode_ms_adpcm(oss->dsp_context, + buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign); + encoded_data = oss->dsp_context->adpcm_buffer; + encoded_size = oss->dsp_context->adpcm_size; + break; + case WAVE_FORMAT_DVI_ADPCM: + oss->dsp_context->encode_ima_adpcm(oss->dsp_context, + buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign); + encoded_data = oss->dsp_context->adpcm_buffer; + encoded_size = oss->dsp_context->adpcm_size; + break; + default: + encoded_data = buffer; + encoded_size = buffer_size; + break; + } + if (0 != oss->receive(encoded_data, encoded_size, oss->user_data)) + break; + } + +err_out: + if (pcm_handle != -1) + close(pcm_handle); + free(buffer); + + ExitThread(0); + + return NULL; +} + +static void audin_oss_open(IAudinDevice *device, AudinReceive receive, void *user_data) { + AudinOSSDevice *oss = (AudinOSSDevice*)device; + + oss->receive = receive; + oss->user_data = user_data; + + oss->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + oss->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL); +} + +static void audin_oss_close(IAudinDevice *device) { + AudinOSSDevice *oss = (AudinOSSDevice*)device; + + if (device == NULL) + return; + + if (oss->stopEvent != NULL) { + SetEvent(oss->stopEvent); + WaitForSingleObject(oss->thread, INFINITE); + + CloseHandle(oss->stopEvent); + oss->stopEvent = NULL; + + CloseHandle(oss->thread); + oss->thread = NULL; + } + + oss->receive = NULL; + oss->user_data = NULL; +} + +static void audin_oss_free(IAudinDevice *device) { + AudinOSSDevice *oss = (AudinOSSDevice*)device; + + if (device == NULL) + return; + + audin_oss_close(device); + freerdp_dsp_context_free(oss->dsp_context); + + free(oss); +} + +COMMAND_LINE_ARGUMENT_A audin_oss_args[] = { + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } +}; + +static void audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) { + int status; + char *str_num, *eptr; + DWORD flags; + COMMAND_LINE_ARGUMENT_A *arg; + AudinOSSDevice *oss = (AudinOSSDevice*)device; + + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + + status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, audin_oss_args, flags, oss, NULL, NULL); + if (status < 0) + return; + + arg = audin_oss_args; + + do { + if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) + continue; + + CommandLineSwitchStart(arg) + + CommandLineSwitchCase(arg, "dev") { + str_num = _strdup(arg->Value); + oss->dev_unit = strtol(str_num, &eptr, 10); + if (oss->dev_unit < 0 || *eptr != '\0') + oss->dev_unit = -1; + free(str_num); + } + + CommandLineSwitchEnd(arg) + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); +} + +#ifdef STATIC_CHANNELS +#define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry +#endif + +int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { + ADDIN_ARGV *args; + AudinOSSDevice *oss; + + oss = (AudinOSSDevice*)malloc(sizeof(AudinOSSDevice)); + ZeroMemory(oss, sizeof(AudinOSSDevice)); + + oss->iface.Open = audin_oss_open; + oss->iface.FormatSupported = audin_oss_format_supported; + oss->iface.SetFormat = audin_oss_set_format; + oss->iface.Close = audin_oss_close; + oss->iface.Free = audin_oss_free; + + oss->dev_unit = -1; + + args = pEntryPoints->args; + audin_oss_parse_addin_args(oss, args); + + oss->dsp_context = freerdp_dsp_context_new(); + + pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)oss); + + return 0; +} diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index 90e9cdb7c..73b45f36c 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -450,7 +450,7 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u static COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = { - { "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; @@ -461,7 +461,7 @@ static void audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a COMMAND_LINE_ARGUMENT_A* arg; AudinPulseDevice* pulse = (AudinPulseDevice*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_pulse_args, flags, pulse, NULL, NULL); @@ -474,7 +474,7 @@ static void audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "audio-dev") + CommandLineSwitchCase(arg, "dev") { pulse->device_name = _strdup(arg->Value); } diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c index 9a2a46ba4..5f1b6bbdd 100644 --- a/channels/audin/client/winmm/audin_winmm.c +++ b/channels/audin/client/winmm/audin_winmm.c @@ -246,7 +246,7 @@ static void audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* u static COMMAND_LINE_ARGUMENT_A audin_winmm_args[] = { - { "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; @@ -257,7 +257,7 @@ static void audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a COMMAND_LINE_ARGUMENT_A* arg; AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_winmm_args, flags, winmm, NULL, NULL); @@ -270,7 +270,7 @@ static void audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "audio-dev") + CommandLineSwitchCase(arg, "dev") { winmm->device_name = _strdup(arg->Value); } diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 9b76ebb90..94b1e0396 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -45,7 +45,7 @@ static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, if (dvcman->num_listeners < MAX_PLUGINS) { - WLog_DBG(TAG, "%d.%s.", dvcman->num_listeners, pszChannelName); + WLog_DBG(TAG, "create_listener: %d.%s.", dvcman->num_listeners, pszChannelName); listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER)); ZeroMemory(listener, sizeof(DVCMAN_LISTENER)); @@ -67,7 +67,7 @@ static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, } else { - WLog_WARN(TAG, "Maximum DVC listener number reached."); + WLog_WARN(TAG, "create_listener: Maximum DVC listener number reached."); return 1; } } @@ -78,14 +78,14 @@ static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const cha if (dvcman->num_plugins < MAX_PLUGINS) { - WLog_DBG(TAG, "num_plugins %d", dvcman->num_plugins); dvcman->plugin_names[dvcman->num_plugins] = name; dvcman->plugins[dvcman->num_plugins++] = pPlugin; + WLog_DBG(TAG, "register_plugin: num_plugins %d", dvcman->num_plugins); return 0; } else { - WLog_WARN(TAG, "Maximum DVC plugin number reached."); + WLog_WARN(TAG, "register_plugin: Maximum DVC plugin number reached."); return 1; } } @@ -335,7 +335,7 @@ static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) { DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; - WLog_DBG(TAG, "id=%d", channel->channel_id); + WLog_DBG(TAG, "close_channel_iface: id=%d", channel->channel_id); return 1; } @@ -409,6 +409,7 @@ int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId pCallback = channel->channel_callback; if (pCallback->OnOpen) pCallback->OnOpen(pCallback); + WLog_DBG(TAG, "open_channel: ChannelId %d", ChannelId); } return 0; @@ -569,7 +570,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN UINT32 chunkLength; int status; - WLog_DBG(TAG, "ChannelId=%d size=%d", ChannelId, dataSize); + WLog_DBG(TAG, "write_data: ChannelId=%d size=%d", ChannelId, dataSize); if (drdynvc->channel_error != CHANNEL_RC_OK) return 1; @@ -656,6 +657,7 @@ static int drdynvc_send_capability_response(drdynvcPlugin* drdynvc) int status; wStream* s; + WLog_DBG(TAG, "capability_response"); s = Stream_New(NULL, 4); Stream_Write_UINT16(s, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ Stream_Write_UINT16(s, drdynvc->version); @@ -676,7 +678,7 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in { int status; - WLog_DBG(TAG, "Sp=%d cbChId=%d", Sp, cbChId); + WLog_DBG(TAG, "capability_request Sp=%d cbChId=%d", Sp, cbChId); Stream_Seek(s, 1); /* pad */ Stream_Read_UINT16(s, drdynvc->version); @@ -746,7 +748,7 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); - WLog_DBG(TAG, "ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); + WLog_DBG(TAG, "process_create_request: ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); @@ -792,7 +794,7 @@ static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId ChannelId = drdynvc_read_variable_uint(s, cbChId); Length = drdynvc_read_variable_uint(s, Sp); - WLog_DBG(TAG, "ChannelId=%d Length=%d", ChannelId, Length); + WLog_DBG(TAG, "process_data_first: Sp=%d cbChId=%d, ChannelId=%d Length=%d", Sp, cbChId, ChannelId, Length); status = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId, Length); @@ -807,7 +809,7 @@ static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStr UINT32 ChannelId; ChannelId = drdynvc_read_variable_uint(s, cbChId); - WLog_DBG(TAG, "ChannelId=%d", ChannelId); + WLog_DBG(TAG, "process_data: Sp=%d cbChId=%d, ChannelId=%d", Sp, cbChId, ChannelId); return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s); } @@ -821,7 +823,7 @@ static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbC ChannelId = drdynvc_read_variable_uint(s, cbChId); - WLog_DBG(TAG, "ChannelId=%d", ChannelId); + WLog_DBG(TAG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%d", Sp, cbChId, ChannelId); dvcman_close_channel(drdynvc->channel_mgr, ChannelId); @@ -858,7 +860,7 @@ static void drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s) Sp = (value & 0x0c) >> 2; cbChId = (value & 0x03) >> 0; - WLog_DBG(TAG, "Cmd=0x%x", Cmd); + WLog_DBG(TAG, "order_recv: Cmd=0x%x, Sp=%d cbChId=%d, ChannelId=%d", Cmd, Sp, cbChId); switch (Cmd) { diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c index 6c87ac359..706a15616 100644 --- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c +++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c @@ -606,7 +606,7 @@ static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* COMMAND_LINE_ARGUMENT_A* arg; rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_alsa_args, flags, alsa, NULL, NULL); if (status < 0) diff --git a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c index b709ad8f1..d73f91fbe 100644 --- a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c +++ b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c @@ -395,7 +395,7 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device, DEBUG_SND("opensles=%p, args=%p", opensles, args); - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_opensles_args, flags, opensles, NULL, NULL); diff --git a/channels/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c index eac6029dc..4cb4bc981 100644 --- a/channels/rdpsnd/client/oss/rdpsnd_oss.c +++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c @@ -64,7 +64,7 @@ struct rdpsnd_oss_plugin { #define OSS_LOG_ERR(_text, _error) \ if (_error != 0) \ - WLog_ERR(TAG, "%s: %i - %s\n", _text, _error, strerror(_error)); + WLog_ERR(TAG, "%s: %i - %s", _text, _error, strerror(_error)); static int rdpsnd_oss_get_format(AUDIO_FORMAT *format) { @@ -140,16 +140,16 @@ static void rdpsnd_oss_set_format(rdpsndDevicePlugin *device, AUDIO_FORMAT *form tmp = rdpsnd_oss_get_format(format); if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1) - OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed.", errno); + OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed", errno); tmp = format->nChannels; if (ioctl(oss->pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1) - OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed.", errno); + OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed", errno); tmp = format->nSamplesPerSec; if (ioctl(oss->pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1) - OSS_LOG_ERR("SNDCTL_DSP_SPEED failed.", errno); + OSS_LOG_ERR("SNDCTL_DSP_SPEED failed", errno); tmp = format->nBlockAlign; if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) - OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed.", errno); + OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno); } static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) { @@ -183,6 +183,7 @@ static void rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, in if (oss->dev_unit != -1) snprintf(dev_name, PATH_MAX - 1, "/dev/dsp%i", oss->dev_unit); + WLog_INFO(TAG, "open: %s", dev_name); if ((oss->pcm_handle = open(dev_name, O_WRONLY)) < 0) { OSS_LOG_ERR("sound dev open failed", errno); oss->pcm_handle = -1; @@ -192,7 +193,7 @@ static void rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, in int mask = 0; if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1) { - OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory.", errno); + OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno); } else if ((mask & PCM_CAP_OUTPUT) == 0) { OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP); close(oss->pcm_handle); @@ -201,7 +202,7 @@ static void rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, in } #endif if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &oss->supported_formats) == -1) { - OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed.", errno); + OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed", errno); close(oss->pcm_handle); oss->pcm_handle = -1; return; @@ -363,7 +364,7 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *a COMMAND_LINE_ARGUMENT_A *arg; rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, rdpsnd_oss_args, flags, oss, NULL, NULL); if (status < 0) @@ -386,8 +387,7 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *a } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return status; } diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index 912563fe9..e350e8c73 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -597,7 +597,7 @@ static void rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV COMMAND_LINE_ARGUMENT_A* arg; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_pulse_args, flags, pulse, NULL, NULL); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 4e6f49791..70ca8e8ba 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -2026,7 +2026,6 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) UINT32 index; ADDIN_ARGV* args; - settings->DynamicChannelCount = 0; if ((freerdp_static_channel_collection_find(settings, "rdpsnd")) || (freerdp_dynamic_channel_collection_find(settings, "tsmf"))) { diff --git a/winpr/include/winpr/cmdline.h b/winpr/include/winpr/cmdline.h index 6c5f605db..48db262d0 100644 --- a/winpr/include/winpr/cmdline.h +++ b/winpr/include/winpr/cmdline.h @@ -59,6 +59,9 @@ #define COMMAND_LINE_SEPARATOR_EQUAL 0x00000200 #define COMMAND_LINE_SEPARATOR_SPACE 0x00000400 +/* Supress COMMAND_LINE_ERROR_NO_KEYWORD return. */ +#define COMMAND_LINE_IGN_UNKNOWN_KEYWORD 0x00001000 + /* Command-Line Parsing Error Codes */ #define COMMAND_LINE_ERROR -1000 diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index 58c831cb0..153e22211 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -28,6 +28,7 @@ #include #ifndef _WIN32 +#include #include #include #include diff --git a/winpr/libwinpr/utils/cmdline.c b/winpr/libwinpr/utils/cmdline.c index 3ac9213ef..e55b738f1 100644 --- a/winpr/libwinpr/utils/cmdline.c +++ b/winpr/libwinpr/utils/cmdline.c @@ -160,8 +160,11 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* if ((sigil_length > 0) || (flags & COMMAND_LINE_SIGIL_NONE) || (flags & COMMAND_LINE_SIGIL_NOT_ESCAPED)) { - if (length < (sigil_length + 1)) + if (length < (sigil_length + 1)) { + if ((flags & COMMAND_LINE_IGN_UNKNOWN_KEYWORD)) + continue; return COMMAND_LINE_ERROR_NO_KEYWORD; + } keyword_index = sigil_index + sigil_length; keyword = (char*) &argv[i][keyword_index]; @@ -362,7 +365,7 @@ int CommandLineParseArgumentsA(int argc, LPCSTR* argv, COMMAND_LINE_ARGUMENT_A* return COMMAND_LINE_STATUS_PRINT_VERSION; } - if (!found) + if (!found && (flags & COMMAND_LINE_IGN_UNKNOWN_KEYWORD) == 0) return COMMAND_LINE_ERROR_NO_KEYWORD; } }