diff --git a/channels/rdpdr/client/serial/serial_main.c b/channels/rdpdr/client/serial/serial_main.c index 1a0b069eb..0ef98333a 100644 --- a/channels/rdpdr/client/serial/serial_main.c +++ b/channels/rdpdr/client/serial/serial_main.c @@ -85,7 +85,7 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) uint32 FileId; stream_seek(irp->input, 28); /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */ - /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */ + /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */ stream_read_uint32(irp->input, PathLength); freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(irp->input), &path, PathLength / 2); @@ -162,7 +162,8 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) } else { - buffer = (uint8*)xmalloc(Length); + buffer = (uint8*) xmalloc(Length); + if (!serial_tty_read(tty, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; @@ -318,7 +319,7 @@ static void serial_process_irp_list(SERIAL_DEVICE* serial) break; freerdp_thread_lock(serial->thread); - irp = (IRP*)list_dequeue(serial->irp_list); + irp = (IRP*) list_dequeue(serial->irp_list); freerdp_thread_unlock(serial->thread); if (irp == NULL) @@ -375,20 +376,22 @@ static void serial_irp_request(DEVICE* device, IRP* irp) static void serial_free(DEVICE* device) { - SERIAL_DEVICE* serial = (SERIAL_DEVICE*)device; IRP* irp; + SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device; DEBUG_SVC("freeing device"); freerdp_thread_stop(serial->thread); freerdp_thread_free(serial->thread); - while ((irp = (IRP*)list_dequeue(serial->irp_list)) != NULL) + while ((irp = (IRP*) list_dequeue(serial->irp_list)) != NULL) irp->Discard(irp); + list_free(serial->irp_list); - while ((irp = (IRP*)list_dequeue(serial->pending_irps)) != NULL) + while ((irp = (IRP*) list_dequeue(serial->pending_irps)) != NULL) irp->Discard(irp); + list_free(serial->pending_irps); xfree(serial); @@ -396,13 +399,13 @@ static void serial_free(DEVICE* device) int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { - SERIAL_DEVICE* serial; + int i, len; char* name; char* path; - int i, len; + SERIAL_DEVICE* serial; - name = (char*)pEntryPoints->plugin_data->data[1]; - path = (char*)pEntryPoints->plugin_data->data[2]; + name = (char*) pEntryPoints->plugin_data->data[1]; + path = (char*) pEntryPoints->plugin_data->data[2]; if (name[0] && path[0]) { @@ -415,6 +418,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) len = strlen(name); serial->device.data = stream_new(len + 1); + for (i = 0; i <= len; i++) stream_write_uint8(serial->device.data, name[i] < 0 ? '_' : name[i]); @@ -461,12 +465,13 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, uint32 file_id, uint32 return; } - irp = (IRP*)list_peek(serial->pending_irps); + irp = (IRP*) list_peek(serial->pending_irps); + while (irp) { if (irp->FileId != file_id || irp->MajorFunction != major) { - irp = (IRP*)list_next(serial->pending_irps, irp); + irp = (IRP*) list_next(serial->pending_irps, irp); continue; } @@ -494,7 +499,8 @@ static void serial_check_for_events(SERIAL_DEVICE* serial) DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); - irp = (IRP*)list_peek(serial->pending_irps); + irp = (IRP*) list_peek(serial->pending_irps); + while (irp) { prev = NULL; @@ -510,7 +516,7 @@ static void serial_check_for_events(SERIAL_DEVICE* serial) irp->Complete(irp); prev = irp; - irp = (IRP*)list_next(serial->pending_irps, irp); + irp = (IRP*) list_next(serial->pending_irps, irp); list_remove(serial->pending_irps, prev); wait_obj_set(serial->in_event); @@ -518,7 +524,7 @@ static void serial_check_for_events(SERIAL_DEVICE* serial) } if (!prev) - irp = (IRP*)list_next(serial->pending_irps, irp); + irp = (IRP*) list_next(serial->pending_irps, irp); } DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps)); @@ -537,8 +543,8 @@ void serial_get_timeouts(SERIAL_DEVICE* serial, IRP* irp, uint32* timeout, uint3 DEBUG_SVC("length read %u", Length); tty = serial->tty; - *timeout = (tty->read_total_timeout_multiplier * Length) + - tty->read_total_timeout_constant; + + *timeout = (tty->read_total_timeout_multiplier * Length) + tty->read_total_timeout_constant; *interval_timeout = tty->read_interval_timeout; DEBUG_SVC("timeouts %u %u", *timeout, *interval_timeout); @@ -554,37 +560,37 @@ static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp) switch (irp->MajorFunction) { - case IRP_MJ_WRITE: - DEBUG_SVC("handling IRP_MJ_WRITE"); - break; + case IRP_MJ_WRITE: + DEBUG_SVC("handling IRP_MJ_WRITE"); + break; - case IRP_MJ_READ: - DEBUG_SVC("handling IRP_MJ_READ"); + case IRP_MJ_READ: + DEBUG_SVC("handling IRP_MJ_READ"); - serial_get_timeouts(serial, irp, &timeout, &itv_timeout); + serial_get_timeouts(serial, irp, &timeout, &itv_timeout); - /* Check if io request timeout is smaller than current (but not 0). */ - if (timeout && (serial->select_timeout == 0 || timeout < serial->select_timeout)) - { - serial->select_timeout = timeout; - serial->tv.tv_sec = serial->select_timeout / 1000; - serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; - serial->timeout_id = tty->id; - } - if (itv_timeout && (serial->select_timeout == 0 || itv_timeout < serial->select_timeout)) - { - serial->select_timeout = itv_timeout; - serial->tv.tv_sec = serial->select_timeout / 1000; - serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; - serial->timeout_id = tty->id; - } - DEBUG_SVC("select_timeout %u, tv_sec %lu tv_usec %lu, timeout_id %u", - serial->select_timeout, serial->tv.tv_sec, serial->tv.tv_usec, serial->timeout_id); - break; + /* Check if io request timeout is smaller than current (but not 0). */ + if (timeout && (serial->select_timeout == 0 || timeout < serial->select_timeout)) + { + serial->select_timeout = timeout; + serial->tv.tv_sec = serial->select_timeout / 1000; + serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; + serial->timeout_id = tty->id; + } + if (itv_timeout && (serial->select_timeout == 0 || itv_timeout < serial->select_timeout)) + { + serial->select_timeout = itv_timeout; + serial->tv.tv_sec = serial->select_timeout / 1000; + serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; + serial->timeout_id = tty->id; + } + DEBUG_SVC("select_timeout %u, tv_sec %lu tv_usec %lu, timeout_id %u", + serial->select_timeout, serial->tv.tv_sec, serial->tv.tv_usec, serial->timeout_id); + break; - default: - DEBUG_SVC("no need to handle %d", irp->MajorFunction); - return; + default: + DEBUG_SVC("no need to handle %d", irp->MajorFunction); + return; } irp->IoStatus = STATUS_PENDING; @@ -604,6 +610,7 @@ static void __serial_check_fds(SERIAL_DEVICE* serial) /* scan every pending */ irp = list_peek(serial->pending_irps); + while (irp) { DEBUG_SVC("MajorFunction %u", irp->MajorFunction); @@ -643,7 +650,8 @@ static void __serial_check_fds(SERIAL_DEVICE* serial) } prev = irp; - irp = (IRP*)list_next(serial->pending_irps, irp); + irp = (IRP*) list_next(serial->pending_irps, irp); + if (prev->IoStatus == STATUS_SUCCESS) { list_remove(serial->pending_irps, prev); @@ -654,14 +662,15 @@ static void __serial_check_fds(SERIAL_DEVICE* serial) static void serial_set_fds(SERIAL_DEVICE* serial) { - fd_set* fds; IRP* irp; + fd_set* fds; SERIAL_TTY* tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; - irp = (IRP*)list_peek(serial->pending_irps); + irp = (IRP*) list_peek(serial->pending_irps); + while (irp) { fds = NULL; @@ -682,7 +691,8 @@ static void serial_set_fds(SERIAL_DEVICE* serial) FD_SET(tty->fd, fds); serial->nfds = MAX(serial->nfds, tty->fd); } - irp = (IRP*)list_next(serial->pending_irps, irp); + + irp = (IRP*) list_next(serial->pending_irps, irp); } } diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c index 19c3ecab6..de66f56fd 100644 --- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c +++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c @@ -58,51 +58,55 @@ struct rdpsnd_alsa_plugin static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa) { + int status; snd_pcm_hw_params_t* hw_params; snd_pcm_sw_params_t* sw_params; - int error; snd_pcm_uframes_t frames; snd_pcm_uframes_t start_threshold; snd_pcm_drop(alsa->out_handle); - error = snd_pcm_hw_params_malloc(&hw_params); - if (error < 0) + status = snd_pcm_hw_params_malloc(&hw_params); + + if (status < 0) { DEBUG_WARN("snd_pcm_hw_params_malloc failed"); return; } + snd_pcm_hw_params_any(alsa->out_handle, hw_params); - snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, - SND_PCM_ACCESS_RW_INTERLEAVED); - snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, - alsa->format); - snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, - &alsa->actual_rate, NULL); - snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, - &alsa->actual_channels); + snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, alsa->format); + snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); + snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); + if (alsa->latency < 0) frames = alsa->actual_rate * 4 / 10; /* Default to 400ms buffer */ else frames = alsa->latency * alsa->actual_rate * 2 / 1000; /* Double of the latency */ + if (frames < alsa->actual_rate / 2) frames = alsa->actual_rate / 2; /* Minimum 0.5-second buffer */ - snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, - &frames); + + snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); - error = snd_pcm_sw_params_malloc(&sw_params); - if (error < 0) + status = snd_pcm_sw_params_malloc(&sw_params); + + if (status < 0) { DEBUG_WARN("snd_pcm_sw_params_malloc failed"); return; } + snd_pcm_sw_params_current(alsa->out_handle, sw_params); + if (alsa->latency == 0) start_threshold = 0; else start_threshold = frames / 2; + snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, start_threshold); snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); @@ -110,9 +114,9 @@ static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa) snd_pcm_prepare(alsa->out_handle); DEBUG_SVC("hardware buffer %d frames, playback buffer %.2g seconds", - (int)frames, (double)frames / 2.0 / (double)alsa->actual_rate); - if ((alsa->actual_rate != alsa->source_rate) || - (alsa->actual_channels != alsa->source_channels)) + (int) frames, (double) frames / 2.0 / (double) alsa->actual_rate); + + if ((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) { DEBUG_SVC("actual rate %d / channel %d is different from source rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); @@ -129,6 +133,7 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for alsa->actual_rate = format->nSamplesPerSec; alsa->source_channels = format->nChannels; alsa->actual_channels = format->nChannels; + switch (format->wFormatTag) { case 1: /* PCM */ @@ -151,6 +156,7 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for alsa->bytes_per_channel = 2; break; } + alsa->wformat = format->wFormatTag; alsa->block_size = format->nBlockAlign; } @@ -162,31 +168,38 @@ static void rdpsnd_alsa_set_format(rdpsndDevicePlugin* device, rdpsndFormat* for static void rdpsnd_alsa_open_mixer(rdpsndAlsaPlugin* alsa) { - int error; + int status; snd_mixer_t* handle; - error = snd_mixer_open(&handle, 0); - if (error < 0) + status = snd_mixer_open(&handle, 0); + + if (status < 0) { DEBUG_WARN("snd_mixer_open failed"); return; } - error = snd_mixer_attach(handle, alsa->device_name); - if (error < 0) + + status = snd_mixer_attach(handle, alsa->device_name); + + if (status < 0) { DEBUG_WARN("snd_mixer_attach failed"); snd_mixer_close(handle); return; } - error = snd_mixer_selem_register(handle, NULL, NULL); - if (error < 0) + + status = snd_mixer_selem_register(handle, NULL, NULL); + + if (status < 0) { DEBUG_WARN("snd_mixer_selem_register failed"); snd_mixer_close(handle); return; } - error = snd_mixer_load(handle); - if (error < 0) + + status = snd_mixer_load(handle); + + if (status < 0) { DEBUG_WARN("snd_mixer_load failed"); snd_mixer_close(handle); @@ -198,17 +211,17 @@ static void rdpsnd_alsa_open_mixer(rdpsndAlsaPlugin* alsa) static void rdpsnd_alsa_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; - int error; + int status; + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; if (alsa->out_handle != 0) return; DEBUG_SVC("opening"); - error = snd_pcm_open(&alsa->out_handle, alsa->device_name, - SND_PCM_STREAM_PLAYBACK, 0); - if (error < 0) + status = snd_pcm_open(&alsa->out_handle, alsa->device_name, SND_PCM_STREAM_PLAYBACK, 0); + + if (status < 0) { DEBUG_WARN("snd_pcm_open failed"); } @@ -231,6 +244,7 @@ static void rdpsnd_alsa_close(rdpsndDevicePlugin* device) snd_pcm_close(alsa->out_handle); alsa->out_handle = 0; } + if (alsa->mixer_handle) { snd_mixer_close(alsa->mixer_handle); @@ -277,7 +291,6 @@ static boolean rdpsnd_alsa_format_supported(rdpsndDevicePlugin* device, rdpsndFo static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, uint32 value) { - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; long left; long right; long volume_min; @@ -285,6 +298,7 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, uint32 value) long volume_left; long volume_right; snd_mixer_elem_t* elem; + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; if (!alsa->mixer_handle) return; @@ -307,15 +321,15 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, uint32 value) static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size) { - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; uint8* src; int len; - int error; + int status; int frames; int rbytes_per_frame; int sbytes_per_frame; uint8* pindex; uint8* end; + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; if (alsa->out_handle == 0) return; @@ -341,14 +355,14 @@ static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size) sbytes_per_frame = alsa->source_channels * alsa->bytes_per_channel; rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel; + if ((size % sbytes_per_frame) != 0) { DEBUG_WARN("error len mod"); return; } - if ((alsa->source_rate == alsa->actual_rate) && - (alsa->source_channels == alsa->actual_channels)) + if ((alsa->source_rate == alsa->actual_rate) && (alsa->source_channels == alsa->actual_channels)) { } else @@ -365,31 +379,34 @@ static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size) pindex = src; end = pindex + size; + while (pindex < end) { len = end - pindex; frames = len / rbytes_per_frame; - error = snd_pcm_writei(alsa->out_handle, pindex, frames); - if (error == -EPIPE) + status = snd_pcm_writei(alsa->out_handle, pindex, frames); + + if (status == -EPIPE) { - snd_pcm_recover(alsa->out_handle, error, 0); - error = 0; + snd_pcm_recover(alsa->out_handle, status, 0); + status = 0; } - else if (error < 0) + else if (status < 0) { - DEBUG_WARN("error %d", error); + DEBUG_WARN("status %d", status); snd_pcm_close(alsa->out_handle); alsa->out_handle = 0; rdpsnd_alsa_open(device, NULL, alsa->latency); break; } - pindex += error * rbytes_per_frame; + + pindex += status * rbytes_per_frame; } } static void rdpsnd_alsa_start(rdpsndDevicePlugin* device) { - rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device; + rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device; if (alsa->out_handle == 0) return; @@ -414,14 +431,17 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) alsa->device.Free = rdpsnd_alsa_free; data = pEntryPoints->plugin_data; - if (data && strcmp((char*)data->data[0], "alsa") == 0) + + if (data && strcmp((char*) data->data[0], "alsa") == 0) { - alsa->device_name = xstrdup((char*)data->data[1]); + alsa->device_name = xstrdup((char*) data->data[1]); } + if (alsa->device_name == NULL) { alsa->device_name = xstrdup("default"); } + alsa->out_handle = 0; alsa->source_rate = 22050; alsa->actual_rate = 22050; @@ -432,7 +452,7 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) alsa->dsp_context = freerdp_dsp_context_new(); - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)alsa); + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) alsa); return 0; } diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index 3fe645ba2..ee9fa1bac 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -34,6 +34,7 @@ #include "rdpsnd_main.h" typedef struct rdpsnd_pulse_plugin rdpsndPulsePlugin; + struct rdpsnd_pulse_plugin { rdpsndDevicePlugin device; @@ -52,10 +53,11 @@ struct rdpsnd_pulse_plugin static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userdata) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; pa_context_state_t state; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) userdata; state = pa_context_get_state(context); + switch (state) { case PA_CONTEXT_READY: @@ -77,8 +79,8 @@ static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userd static boolean rdpsnd_pulse_connect(rdpsndDevicePlugin* device) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_context_state_t state; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse->context) return false; @@ -88,13 +90,16 @@ static boolean rdpsnd_pulse_connect(rdpsndDevicePlugin* device) DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return false; } + pa_threaded_mainloop_lock(pulse->mainloop); + if (pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return false; } + for (;;) { state = pa_context_get_state(pulse->context); @@ -107,7 +112,9 @@ static boolean rdpsnd_pulse_connect(rdpsndDevicePlugin* device) } pa_threaded_mainloop_wait(pulse->mainloop); } + pa_threaded_mainloop_unlock(pulse->mainloop); + if (state == PA_CONTEXT_READY) { DEBUG_SVC("connected"); @@ -122,7 +129,7 @@ static boolean rdpsnd_pulse_connect(rdpsndDevicePlugin* device) static void rdpsnd_pulse_stream_success_callback(pa_stream* stream, int success, void* userdata) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) userdata; pa_threaded_mainloop_signal(pulse->mainloop, 0); } @@ -131,19 +138,22 @@ static void rdpsnd_pulse_wait_for_operation(rdpsndPulsePlugin* pulse, pa_operati { if (operation == NULL) return; + while (pa_operation_get_state(operation) == PA_OPERATION_RUNNING) { pa_threaded_mainloop_wait(pulse->mainloop); } + pa_operation_unref(operation); } static void rdpsnd_pulse_stream_state_callback(pa_stream* stream, void* userdata) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; pa_stream_state_t state; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) userdata; state = pa_stream_get_state(stream); + switch (state) { case PA_STREAM_READY: @@ -165,24 +175,25 @@ static void rdpsnd_pulse_stream_state_callback(pa_stream* stream, void* userdata static void rdpsnd_pulse_stream_request_callback(pa_stream* stream, size_t length, void* userdata) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)userdata; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) userdata; pa_threaded_mainloop_signal(pulse->mainloop, 0); } static void rdpsnd_pulse_close(rdpsndDevicePlugin* device) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse->context || !pulse->stream) return; pa_threaded_mainloop_lock(pulse->mainloop); - rdpsnd_pulse_wait_for_operation(pulse, - pa_stream_drain(pulse->stream, rdpsnd_pulse_stream_success_callback, pulse)); + + rdpsnd_pulse_wait_for_operation(pulse, pa_stream_drain(pulse->stream, rdpsnd_pulse_stream_success_callback, pulse)); pa_stream_disconnect(pulse->stream); pa_stream_unref(pulse->stream); pulse->stream = NULL; + pa_threaded_mainloop_unlock(pulse->mainloop); } @@ -195,6 +206,7 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat* sample_spec.rate = format->nSamplesPerSec; sample_spec.channels = format->nChannels; + switch (format->wFormatTag) { case 1: /* PCM */ @@ -230,11 +242,11 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, rdpsndFormat* static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_stream_state_t state; pa_stream_flags_t flags; pa_buffer_attr buffer_attr = { 0 }; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse->context || pulse->stream) { @@ -253,23 +265,22 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, } pa_threaded_mainloop_lock(pulse->mainloop); - pulse->stream = pa_stream_new(pulse->context, "freerdp", - &pulse->sample_spec, NULL); + + pulse->stream = pa_stream_new(pulse->context, "freerdp", &pulse->sample_spec, NULL); + if (!pulse->stream) { pa_threaded_mainloop_unlock(pulse->mainloop); - DEBUG_WARN("pa_stream_new failed (%d)", - pa_context_errno(pulse->context)); + DEBUG_WARN("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); return; } /* install essential callbacks */ - pa_stream_set_state_callback(pulse->stream, - rdpsnd_pulse_stream_state_callback, pulse); - pa_stream_set_write_callback(pulse->stream, - rdpsnd_pulse_stream_request_callback, pulse); + pa_stream_set_state_callback(pulse->stream, rdpsnd_pulse_stream_state_callback, pulse); + pa_stream_set_write_callback(pulse->stream, rdpsnd_pulse_stream_request_callback, pulse); flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE; + if (pulse->latency > 0) { buffer_attr.maxlength = pa_usec_to_bytes(pulse->latency * 2 * 1000, &pulse->sample_spec); @@ -279,6 +290,7 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, buffer_attr.fragsize = (uint32_t) -1; flags |= PA_STREAM_ADJUST_LATENCY; } + if (pa_stream_connect_playback(pulse->stream, pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0) { @@ -291,17 +303,22 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, for (;;) { state = pa_stream_get_state(pulse->stream); + if (state == PA_STREAM_READY) break; + if (!PA_STREAM_IS_GOOD(state)) { DEBUG_WARN("bad stream state (%d)", pa_context_errno(pulse->context)); break; } + pa_threaded_mainloop_wait(pulse->mainloop); } + pa_threaded_mainloop_unlock(pulse->mainloop); + if (state == PA_STREAM_READY) { freerdp_dsp_context_reset_adpcm(pulse->dsp_context); @@ -315,26 +332,31 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format, static void rdpsnd_pulse_free(rdpsndDevicePlugin* device) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse) return; + rdpsnd_pulse_close(device); + if (pulse->mainloop) { pa_threaded_mainloop_stop(pulse->mainloop); } + if (pulse->context) { pa_context_disconnect(pulse->context); pa_context_unref(pulse->context); pulse->context = NULL; } + if (pulse->mainloop) { pa_threaded_mainloop_free(pulse->mainloop); pulse->mainloop = NULL; } + xfree(pulse->device_name); freerdp_dsp_context_free(pulse->dsp_context); xfree(pulse); @@ -385,7 +407,7 @@ static boolean rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, rdpsndF static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (pulse->stream) { @@ -395,16 +417,17 @@ static void rdpsnd_pulse_set_format(rdpsndDevicePlugin* device, rdpsndFormat* fo pulse->stream = NULL; pa_threaded_mainloop_unlock(pulse->mainloop); } + rdpsnd_pulse_open(device, format, latency); } static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, uint32 value) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_cvolume cv; pa_volume_t left; pa_volume_t right; pa_operation* operation; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse->context || !pulse->stream) return; @@ -418,18 +441,21 @@ static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, uint32 value) cv.values[1] = PA_VOLUME_MUTED + (right * (PA_VOLUME_NORM - PA_VOLUME_MUTED)) / 0xFFFF; pa_threaded_mainloop_lock(pulse->mainloop); + operation = pa_context_set_sink_input_volume(pulse->context, pa_stream_get_index(pulse->stream), &cv, NULL, NULL); - if(operation) + + if (operation) pa_operation_unref(operation); + pa_threaded_mainloop_unlock(pulse->mainloop); } static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; int len; int ret; uint8* src; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse->stream) return; @@ -454,32 +480,39 @@ static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, uint8* data, int size) } pa_threaded_mainloop_lock(pulse->mainloop); + while (size > 0) { while ((len = pa_stream_writable_size(pulse->stream)) == 0) { pa_threaded_mainloop_wait(pulse->mainloop); } + if (len < 0) break; + if (len > size) len = size; + ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE); + if (ret < 0) { DEBUG_WARN("pa_stream_write failed (%d)", pa_context_errno(pulse->context)); break; } + src += len; size -= len; } + pa_threaded_mainloop_unlock(pulse->mainloop); } static void rdpsnd_pulse_start(rdpsndDevicePlugin* device) { - rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse->stream) return; @@ -504,6 +537,7 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) pulse->device.Free = rdpsnd_pulse_free; data = pEntryPoints->plugin_data; + if (data && strcmp((char*)data->data[0], "pulse") == 0) { if(data->data[1] && strlen((char*)data->data[1]) > 0) @@ -515,20 +549,25 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) pulse->dsp_context = freerdp_dsp_context_new(); pulse->mainloop = pa_threaded_mainloop_new(); + if (!pulse->mainloop) { DEBUG_WARN("pa_threaded_mainloop_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } + pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp"); + if (!pulse->context) { DEBUG_WARN("pa_context_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } + pa_context_set_state_callback(pulse->context, rdpsnd_pulse_context_state_callback, pulse); + if (!rdpsnd_pulse_connect((rdpsndDevicePlugin*)pulse)) { DEBUG_WARN("rdpsnd_pulse_connect failed"); @@ -536,8 +575,7 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) return 1; } - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)pulse); + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) pulse); return 0; } - diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 6fa9d94f4..cdee38187 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -93,12 +93,14 @@ static void rdpsnd_process_interval(rdpSvcPlugin* plugin) while (list_size(rdpsnd->data_out_list) > 0) { - item = (struct data_out_item*)list_peek(rdpsnd->data_out_list) ; + item = (struct data_out_item*) list_peek(rdpsnd->data_out_list); + cur_time = get_mstime(); + if (!item || cur_time <= item->out_timestamp) break; - item = (struct data_out_item*)list_dequeue(rdpsnd->data_out_list); + item = (struct data_out_item*) list_dequeue(rdpsnd->data_out_list); svc_plugin_send(plugin, item->data_out); xfree(item); @@ -108,6 +110,7 @@ static void rdpsnd_process_interval(rdpSvcPlugin* plugin) if (rdpsnd->is_open && rdpsnd->close_timestamp > 0) { cur_time = get_mstime(); + if (cur_time > rdpsnd->close_timestamp) { if (rdpsnd->device) @@ -493,7 +496,7 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin) rdpsnd->data_out_list = list_new(); rdpsnd->latency = -1; - data = (RDP_PLUGIN_DATA*)plugin->channel_entry_points.pExtendedData; + data = (RDP_PLUGIN_DATA*) plugin->channel_entry_points.pExtendedData; while (data && data->size > 0) { @@ -506,6 +509,7 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin) default_data[0].size = sizeof(RDP_PLUGIN_DATA); default_data[0].data[0] = "pulse"; default_data[0].data[1] = ""; + if (!rdpsnd_load_device_plugin(rdpsnd, "pulse", default_data)) { default_data[0].data[0] = "alsa"; @@ -541,8 +545,8 @@ static void rdpsnd_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event) static void rdpsnd_process_terminate(rdpSvcPlugin* plugin) { - rdpsndPlugin* rdpsnd = (rdpsndPlugin*)plugin; struct data_out_item* item; + rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin; if (rdpsnd->device) IFCALL(rdpsnd->device->Free, rdpsnd->device);