diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c index dbb515d99..07c24ede3 100644 --- a/channels/audin/client/oss/audin_oss.c +++ b/channels/audin/client/oss/audin_oss.c @@ -37,9 +37,9 @@ #include #include #if defined(__OpenBSD__) - #include +#include #else - #include +#include #endif #include @@ -49,14 +49,15 @@ #include "audin_main.h" -typedef struct _AudinOSSDevice { +typedef struct _AudinOSSDevice +{ IAudinDevice iface; - FREERDP_DSP_CONTEXT *dsp_context; + FREERDP_DSP_CONTEXT* dsp_context; HANDLE thread; HANDLE stopEvent; - + audinFormat format; UINT32 FramesPerPacket; int dev_unit; @@ -70,211 +71,259 @@ typedef struct _AudinOSSDevice { WLog_ERR(TAG, "%s: %i - %s\n", _text, _error, strerror(_error)); -static int audin_oss_get_format(audinFormat *format) { +static int audin_oss_get_format(audinFormat* format) +{ + switch (format->wFormatTag) + { + case WAVE_FORMAT_PCM: - 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; + 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; + case WAVE_FORMAT_MULAW: + return AFMT_MU_LAW; #endif - case WAVE_FORMAT_ADPCM: - case WAVE_FORMAT_DVI_ADPCM: - return AFMT_S16_LE; + 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) { +static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format) +{ int req_fmt = 0; 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; + 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; +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; + + 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) +static void* audin_oss_thread_func(void* arg) { char dev_name[PATH_MAX] = "/dev/dsp"; char mixer_name[PATH_MAX] = "/dev/mixer"; int pcm_handle = -1, mixer_handle; - BYTE *buffer = NULL, *encoded_data; + BYTE* buffer = NULL, *encoded_data; int tmp, buffer_size, encoded_size; - AudinOSSDevice *oss = (AudinOSSDevice*)arg; + AudinOSSDevice* oss = (AudinOSSDevice*)arg; if (arg == NULL) goto err_out; - if (oss->dev_unit != -1) { + if (oss->dev_unit != -1) + { snprintf(dev_name, (PATH_MAX - 1), "/dev/dsp%i", oss->dev_unit); snprintf(mixer_name, PATH_MAX - 1, "/dev/mixer%i", oss->dev_unit); } + WLog_INFO(TAG, "open: %s", dev_name); - if ((pcm_handle = open(dev_name, O_RDONLY)) < 0) { + + if ((pcm_handle = open(dev_name, O_RDONLY)) < 0) + { OSS_LOG_ERR("sound dev open failed", errno); goto err_out; } /* Set rec volume to 100%. */ - if ((mixer_handle = open(mixer_name, O_RDWR)) < 0) { + if ((mixer_handle = open(mixer_name, O_RDWR)) < 0) + { OSS_LOG_ERR("mixer open failed, not critical", errno); - } else { + } + else + { tmp = (100 | (100 << 8)); + if (ioctl(mixer_handle, MIXER_WRITE(SOUND_MIXER_MIC), &tmp) == -1) OSS_LOG_ERR("WRITE_MIXER - SOUND_MIXER_MIC, not critical", errno); + tmp = (100 | (100 << 8)); + if (ioctl(mixer_handle, MIXER_WRITE(SOUND_MIXER_RECLEV), &tmp) == -1) OSS_LOG_ERR("WRITE_MIXER - SOUND_MIXER_RECLEV, not critical", errno); + close(mixer_handle); } + #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) { + + 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) { + } + 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_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8)); buffer = (BYTE*)malloc((buffer_size + sizeof(void*))); - if (NULL == buffer) { + + if (NULL == buffer) + { OSS_LOG_ERR("malloc() fail", errno); goto err_out; } - ZeroMemory(buffer, buffer_size); + ZeroMemory(buffer, buffer_size); freerdp_dsp_context_reset_adpcm(oss->dsp_context); - while (WaitForSingleObject(oss->stopEvent, 0) != WAIT_OBJECT_0) { + while (WaitForSingleObject(oss->stopEvent, 0) != WAIT_OBJECT_0) + { tmp = read(pcm_handle, buffer, buffer_size); - if (tmp < 0) { /* Error happen. */ + + /* Error happen. */ + if (tmp < 0) + { 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; + 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) { + + if (pcm_handle != -1) + { WLog_INFO(TAG, "close: %s", dev_name); 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; - +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; +static void audin_oss_close(IAudinDevice* device) +{ + AudinOSSDevice* oss = (AudinOSSDevice*)device; if (device == NULL) return; - if (oss->stopEvent != NULL) { + if (oss->stopEvent != NULL) + { SetEvent(oss->stopEvent); WaitForSingleObject(oss->thread, INFINITE); - CloseHandle(oss->stopEvent); oss->stopEvent = NULL; - CloseHandle(oss->thread); oss->thread = NULL; } @@ -283,81 +332,79 @@ static void audin_oss_close(IAudinDevice *device) { oss->user_data = NULL; } -static void audin_oss_free(IAudinDevice *device) { - AudinOSSDevice *oss = (AudinOSSDevice*)device; +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[] = { +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) { +static void audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) +{ int status; - char *str_num, *eptr; + char* str_num, *eptr; DWORD flags; - COMMAND_LINE_ARGUMENT_A *arg; - AudinOSSDevice *oss = (AudinOSSDevice*)device; - + 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 { + do + { if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; CommandLineSwitchStart(arg) - - CommandLineSwitchCase(arg, "dev") { + 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); + } + 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; - +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/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c index 2f583eb4e..82299b3be 100644 --- a/channels/rdpsnd/client/oss/rdpsnd_oss.c +++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c @@ -37,9 +37,9 @@ #include #include #if defined(__OpenBSD__) - #include +#include #else - #include +#include #endif #include @@ -51,7 +51,8 @@ typedef struct rdpsnd_oss_plugin rdpsndOssPlugin; -struct rdpsnd_oss_plugin { +struct rdpsnd_oss_plugin +{ rdpsndDevicePlugin device; int pcm_handle; @@ -63,69 +64,85 @@ struct rdpsnd_oss_plugin { int latency; AUDIO_FORMAT format; - FREERDP_DSP_CONTEXT *dsp_context; + FREERDP_DSP_CONTEXT* dsp_context; }; -#define OSS_LOG_ERR(_text, _error) { \ - if (_error != 0) \ - WLog_ERR(TAG, "%s: %i - %s", _text, _error, strerror(_error)); \ -} +#define OSS_LOG_ERR(_text, _error) \ + { \ + if (_error != 0) \ + WLog_ERR(TAG, "%s: %i - %s", _text, _error, strerror(_error)); \ + } -static int rdpsnd_oss_get_format(AUDIO_FORMAT *format) { +static int rdpsnd_oss_get_format(AUDIO_FORMAT* format) +{ + switch (format->wFormatTag) + { + case WAVE_FORMAT_PCM: - 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; + 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; + case WAVE_FORMAT_MULAW: + return AFMT_MU_LAW; #endif - case WAVE_FORMAT_ADPCM: - case WAVE_FORMAT_DVI_ADPCM: - return AFMT_S16_LE; + case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_DVI_ADPCM: + return AFMT_S16_LE; } return 0; } -static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin *device, AUDIO_FORMAT *format) { +static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format) +{ int req_fmt = 0; - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)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; + 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 = rdpsnd_oss_get_format(format); - if (oss->pcm_handle != -1) { /* Check really supported formats by dev. */ + + /* Check really supported formats by dev. */ + if (oss->pcm_handle != -1) + { if ((req_fmt & oss->supported_formats) == 0) return FALSE; - } else { + } + else + { if (req_fmt == 0) return FALSE; } @@ -133,31 +150,39 @@ static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin *device, AUDIO_FORMAT return TRUE; } -static void rdpsnd_oss_set_format(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) { +static void rdpsnd_oss_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) +{ int tmp; - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; if (device == NULL || oss->pcm_handle == -1 || format == NULL) return; - + oss->latency = latency; CopyMemory(&(oss->format), format, sizeof(AUDIO_FORMAT)); - tmp = rdpsnd_oss_get_format(format); + if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1) 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); + tmp = format->nSamplesPerSec; + if (ioctl(oss->pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1) 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); } -static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) { +static void rdpsnd_oss_open_mixer(rdpsndOssPlugin* oss) +{ int devmask = 0; char mixer_name[PATH_MAX] = "/dev/mixer"; @@ -166,12 +191,16 @@ static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) { if (oss->dev_unit != -1) snprintf(mixer_name, PATH_MAX - 1, "/dev/mixer%i", oss->dev_unit); - if ((oss->mixer_handle = open(mixer_name, O_RDWR)) < 0) { + + if ((oss->mixer_handle = open(mixer_name, O_RDWR)) < 0) + { OSS_LOG_ERR("mixer open failed", errno); oss->mixer_handle = -1; return; } - if (ioctl(oss->mixer_handle, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { + + if (ioctl(oss->mixer_handle, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) + { OSS_LOG_ERR("SOUND_MIXER_READ_DEVMASK failed", errno); close(oss->mixer_handle); oss->mixer_handle = -1; @@ -179,104 +208,120 @@ static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) { } } -static void rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) { +static void rdpsnd_oss_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency) +{ char dev_name[PATH_MAX] = "/dev/dsp"; - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; if (device == NULL || oss->pcm_handle != -1) return; 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) { + + if ((oss->pcm_handle = open(dev_name, O_WRONLY)) < 0) + { OSS_LOG_ERR("sound dev open failed", errno); oss->pcm_handle = -1; return; } + #if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_OUTPUT flag. */ int mask = 0; - if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1) { + if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1) + { OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno); - } else if ((mask & PCM_CAP_OUTPUT) == 0) { + } + else if ((mask & PCM_CAP_OUTPUT) == 0) + { OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP); close(oss->pcm_handle); oss->pcm_handle = -1; return; } + #endif - if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &oss->supported_formats) == -1) { + + if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &oss->supported_formats) == -1) + { OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed", errno); close(oss->pcm_handle); oss->pcm_handle = -1; return; } + freerdp_dsp_context_reset_adpcm(oss->dsp_context); rdpsnd_oss_set_format(device, format, latency); rdpsnd_oss_open_mixer(oss); } -static void rdpsnd_oss_close(rdpsndDevicePlugin *device) { - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; +static void rdpsnd_oss_close(rdpsndDevicePlugin* device) +{ + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; if (device == NULL) return; - if (oss->pcm_handle != -1) { + if (oss->pcm_handle != -1) + { WLog_INFO(TAG, "close: dsp"); close(oss->pcm_handle); oss->pcm_handle = -1; } - if (oss->mixer_handle != -1) { + if (oss->mixer_handle != -1) + { WLog_INFO(TAG, "close: mixer"); close(oss->mixer_handle); oss->mixer_handle = -1; } } -static void rdpsnd_oss_free(rdpsndDevicePlugin *device) { - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; +static void rdpsnd_oss_free(rdpsndDevicePlugin* device) +{ + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; if (device == NULL) return; rdpsnd_oss_close(device); freerdp_dsp_context_free(oss->dsp_context); - free(oss); } -static UINT32 rdpsnd_oss_get_volume(rdpsndDevicePlugin *device) { +static UINT32 rdpsnd_oss_get_volume(rdpsndDevicePlugin* device) +{ int vol; UINT32 dwVolume; UINT16 dwVolumeLeft, dwVolumeRight; - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; - + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; /* On error return 50% volume. */ dwVolumeLeft = ((50 * 0xFFFF) / 100); /* 50% */ dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */ dwVolume = ((dwVolumeLeft << 16) | dwVolumeRight); - + if (device == NULL || oss->mixer_handle == -1) return dwVolume; - - if (ioctl(oss->mixer_handle, MIXER_READ(SOUND_MIXER_VOLUME), &vol) == -1) { + + if (ioctl(oss->mixer_handle, MIXER_READ(SOUND_MIXER_VOLUME), &vol) == -1) + { OSS_LOG_ERR("MIXER_READ", errno); return dwVolume; } - + dwVolumeLeft = (((vol & 0x7f) * 0xFFFF) / 100); dwVolumeRight = ((((vol >> 8) & 0x7f) * 0xFFFF) / 100); dwVolume = ((dwVolumeLeft << 16) | dwVolumeRight); - return dwVolume; } -static void rdpsnd_oss_set_volume(rdpsndDevicePlugin *device, UINT32 value) { +static void rdpsnd_oss_set_volume(rdpsndDevicePlugin* device, UINT32 value) +{ int left, right; - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; if (device == NULL || oss->mixer_handle == -1) return; @@ -288,42 +333,47 @@ static void rdpsnd_oss_set_volume(rdpsndDevicePlugin *device, UINT32 value) { left = 0; else if (left > 100) left = 100; + if (right < 0) right = 0; else if (right > 100) right = 100; left |= (right << 8); + if (ioctl(oss->mixer_handle, MIXER_WRITE(SOUND_MIXER_VOLUME), &left) == -1) OSS_LOG_ERR("WRITE_MIXER", errno); } -static void rdpsnd_oss_wave_decode(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) { - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; +static void rdpsnd_oss_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) +{ + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; if (device == NULL || wave == NULL) return; - switch (oss->format.wFormatTag) { - case WAVE_FORMAT_ADPCM: - oss->dsp_context->decode_ms_adpcm(oss->dsp_context, - wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); - wave->length = oss->dsp_context->adpcm_size; - wave->data = oss->dsp_context->adpcm_buffer; - break; - case WAVE_FORMAT_DVI_ADPCM: - oss->dsp_context->decode_ima_adpcm(oss->dsp_context, - wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); - wave->length = oss->dsp_context->adpcm_size; - wave->data = oss->dsp_context->adpcm_buffer; - break; + switch (oss->format.wFormatTag) + { + case WAVE_FORMAT_ADPCM: + oss->dsp_context->decode_ms_adpcm(oss->dsp_context, + wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); + wave->length = oss->dsp_context->adpcm_size; + wave->data = oss->dsp_context->adpcm_buffer; + break; + case WAVE_FORMAT_DVI_ADPCM: + oss->dsp_context->decode_ima_adpcm(oss->dsp_context, + wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign); + wave->length = oss->dsp_context->adpcm_size; + wave->data = oss->dsp_context->adpcm_buffer; + break; } } -static void rdpsnd_oss_wave_play(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) { - BYTE *data; +static void rdpsnd_oss_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) +{ + BYTE* data; int offset, size, status, latency; - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; if (device == NULL || wave == NULL) return; @@ -333,58 +383,67 @@ static void rdpsnd_oss_wave_play(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) size = wave->length; latency = oss->latency; - while (offset < size) { + while (offset < size) + { status = write(oss->pcm_handle, &data[offset], (size - offset)); - if (status < 0) { + + if (status < 0) + { OSS_LOG_ERR("write fail", errno); rdpsnd_oss_close(device); rdpsnd_oss_open(device, NULL, latency); break; } + offset += status; } + /* From rdpsnd_main.c */ wave->wTimeStampB = wave->wTimeStampA + wave->wAudioLength + 65 + latency; wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + 65 + latency; } -static COMMAND_LINE_ARGUMENT_A rdpsnd_oss_args[] = { +static COMMAND_LINE_ARGUMENT_A rdpsnd_oss_args[] = +{ { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "device" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *args) { +static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args) +{ int status; - char *str_num, *eptr; + char* str_num, *eptr; DWORD flags; - COMMAND_LINE_ARGUMENT_A *arg; - rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device; - + COMMAND_LINE_ARGUMENT_A* arg; + rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device; 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) return status; arg = rdpsnd_oss_args; - do { + do + { if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; CommandLineSwitchStart(arg) - - CommandLineSwitchCase(arg, "dev") { + 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); + } + while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return status; } @@ -393,13 +452,12 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *a #define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry #endif -int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { - ADDIN_ARGV *args; - rdpsndOssPlugin *oss; - +int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) +{ + ADDIN_ARGV* args; + rdpsndOssPlugin* oss; oss = (rdpsndOssPlugin*)malloc(sizeof(rdpsndOssPlugin)); ZeroMemory(oss, sizeof(rdpsndOssPlugin)); - oss->device.Open = rdpsnd_oss_open; oss->device.FormatSupported = rdpsnd_oss_format_supported; oss->device.SetFormat = rdpsnd_oss_set_format; @@ -409,17 +467,12 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE oss->device.WavePlay = rdpsnd_oss_wave_play; oss->device.Close = rdpsnd_oss_close; oss->device.Free = rdpsnd_oss_free; - oss->pcm_handle = -1; oss->mixer_handle = -1; oss->dev_unit = -1; - args = pEntryPoints->args; rdpsnd_oss_parse_addin_args((rdpsndDevicePlugin*)oss, args); - oss->dsp_context = freerdp_dsp_context_new(); - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)oss); - return 0; } diff --git a/channels/tsmf/client/oss/tsmf_oss.c b/channels/tsmf/client/oss/tsmf_oss.c index e0cf77953..30f9ab73b 100644 --- a/channels/tsmf/client/oss/tsmf_oss.c +++ b/channels/tsmf/client/oss/tsmf_oss.c @@ -43,12 +43,13 @@ #include "tsmf_audio.h" -typedef struct _TSMFOSSAudioDevice { +typedef struct _TSMFOSSAudioDevice +{ ITSMFAudioDevice iface; char dev_name[PATH_MAX]; int pcm_handle; - + UINT32 sample_rate; UINT32 channels; UINT32 bits_per_sample; @@ -62,44 +63,59 @@ typedef struct _TSMFOSSAudioDevice { WLog_ERR(TAG, "%s: %i - %s", _text, _error, strerror(_error)); -static BOOL tsmf_oss_open(ITSMFAudioDevice *audio, const char *device) { +static BOOL tsmf_oss_open(ITSMFAudioDevice* audio, const char* device) +{ int tmp; int error; - TSMFOssAudioDevice *oss = (TSMFOssAudioDevice*)audio; + TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio; if (oss == NULL || oss->pcm_handle != -1) return FALSE; - if (device == NULL) { /* Default device. */ + if (device == NULL) /* Default device. */ + { strncpy(oss->dev_name, "/dev/dsp", sizeof(oss->dev_name)); - } else { + } + else + { strncpy(oss->dev_name, device, sizeof(oss->dev_name)); } - if ((oss->pcm_handle = open(oss->dev_name, O_WRONLY)) < 0) { + if ((oss->pcm_handle = open(oss->dev_name, O_WRONLY)) < 0) + { OSS_LOG_ERR("sound dev open failed", errno); oss->pcm_handle = -1; return FALSE; } + #if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_OUTPUT flag. */ tmp = 0; - if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1) { + + if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1) + { OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno); - } else if ((mask & PCM_CAP_OUTPUT) == 0) { + } + else if ((mask & PCM_CAP_OUTPUT) == 0) + { OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP); close(oss->pcm_handle); oss->pcm_handle = -1; return FALSE; } + #endif tmp = 0; - if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &tmp) == -1) { + + if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &tmp) == -1) + { OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed", errno); close(oss->pcm_handle); oss->pcm_handle = -1; return FALSE; } - if ((AFMT_S16_LE & tmp) == 0) { + + if ((AFMT_S16_LE & tmp) == 0) + { OSS_LOG_ERR("SNDCTL_DSP_GETFMTS - AFMT_S16_LE", EOPNOTSUPP); close(oss->pcm_handle); oss->pcm_handle = -1; @@ -107,13 +123,13 @@ static BOOL tsmf_oss_open(ITSMFAudioDevice *audio, const char *device) { } WLog_INFO(TAG, "open: %s", oss->dev_name); - return TRUE; } -static BOOL tsmf_oss_set_format(ITSMFAudioDevice *audio, UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample) { +static BOOL tsmf_oss_set_format(ITSMFAudioDevice* audio, UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample) +{ int tmp; - TSMFOssAudioDevice *oss = (TSMFOssAudioDevice*)audio; + TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio; if (oss == NULL || oss->pcm_handle == -1) return FALSE; @@ -121,49 +137,61 @@ static BOOL tsmf_oss_set_format(ITSMFAudioDevice *audio, UINT32 sample_rate, UIN oss->sample_rate = sample_rate; oss->channels = channels; oss->bits_per_sample = bits_per_sample; - tmp = AFMT_S16_LE; + if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1) OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed", errno); + tmp = channels; + if (ioctl(oss->pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1) OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed", errno); + tmp = sample_rate; + if (ioctl(oss->pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1) OSS_LOG_ERR("SNDCTL_DSP_SPEED failed", errno); + tmp = ((bits_per_sample / 8) * channels * sample_rate); + if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno); DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d", - sample_rate, channels, bits_per_sample); - + sample_rate, channels, bits_per_sample); return TRUE; } -static BOOL tsmf_oss_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size) { +static BOOL tsmf_oss_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size) +{ int status; UINT32 offset; - TSMFOssAudioDevice *oss = (TSMFOssAudioDevice*)audio; - + TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio; DEBUG_TSMF("tsmf_oss_play: data_size %d", data_size); if (oss == NULL || oss->pcm_handle == -1) return FALSE; - if (data == NULL || data_size == 0) { + + if (data == NULL || data_size == 0) + { free(data); return TRUE; } offset = 0; oss->data_size_last = data_size; - while (offset < data_size) { + + while (offset < data_size) + { status = write(oss->pcm_handle, &data[offset], (data_size - offset)); - if (status < 0) { + + if (status < 0) + { OSS_LOG_ERR("write fail", errno); free(data); return FALSE; } + offset += status; } @@ -171,9 +199,10 @@ static BOOL tsmf_oss_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size) return TRUE; } -static UINT64 tsmf_oss_get_latency(ITSMFAudioDevice *audio) { +static UINT64 tsmf_oss_get_latency(ITSMFAudioDevice* audio) +{ UINT64 latency = 0; - TSMFOssAudioDevice *oss = (TSMFOssAudioDevice*)audio; + TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio; if (oss == NULL) return 0; @@ -183,20 +212,23 @@ static UINT64 tsmf_oss_get_latency(ITSMFAudioDevice *audio) { return latency; } -static void tsmf_oss_flush(ITSMFAudioDevice *audio) +static void tsmf_oss_flush(ITSMFAudioDevice* audio) { } -static void tsmf_oss_free(ITSMFAudioDevice *audio) { - TSMFOssAudioDevice *oss = (TSMFOssAudioDevice*)audio; +static void tsmf_oss_free(ITSMFAudioDevice* audio) +{ + TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio; if (oss == NULL) return; - if (oss->pcm_handle != -1) { + if (oss->pcm_handle != -1) + { WLog_INFO(TAG, "close: %s", oss->dev_name); close(oss->pcm_handle); } + free(oss); } @@ -204,9 +236,9 @@ static void tsmf_oss_free(ITSMFAudioDevice *audio) { #define freerdp_tsmf_client_audio_subsystem_entry oss_freerdp_tsmf_client_audio_subsystem_entry #endif -ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void) +ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void) { - TSMFOssAudioDevice *oss; + TSMFOssAudioDevice* oss; oss = (TSMFOssAudioDevice*)malloc(sizeof(TSMFOssAudioDevice)); ZeroMemory(oss, sizeof(TSMFOssAudioDevice)); oss->iface.Open = tsmf_oss_open; @@ -216,6 +248,5 @@ ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void) oss->iface.Flush = tsmf_oss_flush; oss->iface.Free = tsmf_oss_free; oss->pcm_handle = -1; - return (ITSMFAudioDevice*)oss; }