static void rdpsnd_pulse_free(rdpsndDevicePlugin* 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); }
static void rdpsnd_pulse_free(rdpsndDevicePlugin * devplugin) { struct pulse_device_data * pulse_data; pulse_data = (struct pulse_device_data *) devplugin->device_data; LLOGLN(10, ("rdpsnd_pulse_free:")); if (!pulse_data) return; rdpsnd_pulse_close(devplugin); if (pulse_data->mainloop) { pa_threaded_mainloop_stop(pulse_data->mainloop); } if (pulse_data->context) { pa_context_disconnect(pulse_data->context); pa_context_unref(pulse_data->context); pulse_data->context = NULL; } if (pulse_data->mainloop) { pa_threaded_mainloop_free(pulse_data->mainloop); pulse_data->mainloop = NULL; } free(pulse_data); devplugin->device_data = NULL; }
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]; if (!pulse->context || pulse->stream) { DEBUG_WARN("pulse stream has been created."); return; } rdpsnd_pulse_set_format_spec(pulse, format); pulse->latency = latency; if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec); DEBUG_WARN("Invalid sample spec %s", ss); return; } pa_threaded_mainloop_lock(pulse->mainloop); 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)); 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); 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); buffer_attr.tlength = pa_usec_to_bytes(pulse->latency * 1000, &pulse->sample_spec); buffer_attr.prebuf = (uint32_t) -1; buffer_attr.minreq = (uint32_t) -1; 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) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_connect_playback failed (%d)", pa_context_errno(pulse->context)); return; } 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); DEBUG_SVC("connected"); } else { rdpsnd_pulse_close(device); } }
static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, rdpsndFormat* format) { rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*)device; pa_stream_state_t state; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX]; if (!pulse->context || pulse->stream) { DEBUG_WARN("pulse stream has been created."); return; } rdpsnd_pulse_set_format_spec(pulse, format); if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec); DEBUG_WARN("Invalid sample spec %s", ss); return; } pa_threaded_mainloop_lock(pulse->mainloop); 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)); 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); if (pa_stream_connect_playback(pulse->stream, pulse->device_name, NULL, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); DEBUG_WARN("pa_stream_connect_playback failed (%d)", pa_context_errno(pulse->context)); return; } 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) { memset(&pulse->adpcm, 0, sizeof(ADPCM)); DEBUG_SVC("connected"); } else { rdpsnd_pulse_close(device); } }
static int rdpsnd_pulse_open(rdpsndDevicePlugin * devplugin) { struct pulse_device_data * pulse_data; pa_stream_state_t state; pa_buffer_attr buffer_attr = { 0 }; pulse_data = (struct pulse_device_data *) devplugin->device_data; if (!pulse_data->context) return 1; /* Since rdpsnd_main calls set_format() after open(), but we need the format spec to open the stream, we will defer the open request if initial set_format request is not yet received */ if (!pulse_data->sample_spec.rate || pulse_data->stream) return 0; LLOGLN(10, ("rdpsnd_pulse_open:")); pa_threaded_mainloop_lock(pulse_data->mainloop); pulse_data->stream = pa_stream_new(pulse_data->context, "freerdp", &pulse_data->sample_spec, NULL); if (!pulse_data->stream) { pa_threaded_mainloop_unlock(pulse_data->mainloop); LLOGLN(0, ("rdpsnd_pulse_open: pa_stream_new failed (%d)", pa_context_errno(pulse_data->context))); return 1; } pa_stream_set_state_callback(pulse_data->stream, rdpsnd_pulse_stream_state_callback, devplugin); pa_stream_set_write_callback(pulse_data->stream, rdpsnd_pulse_stream_request_callback, devplugin); buffer_attr.maxlength = (uint32_t) -1; buffer_attr.tlength = (uint32_t) -1;//pa_usec_to_bytes(2000000, &pulse_data->sample_spec); buffer_attr.prebuf = (uint32_t) -1; buffer_attr.minreq = (uint32_t) -1; buffer_attr.fragsize = (uint32_t) -1; if (pa_stream_connect_playback(pulse_data->stream, pulse_data->device_name[0] ? pulse_data->device_name : NULL, &buffer_attr, 0, NULL, NULL) < 0) { pa_threaded_mainloop_unlock(pulse_data->mainloop); LLOGLN(0, ("rdpsnd_pulse_open: pa_stream_connect_playback failed (%d)", pa_context_errno(pulse_data->context))); return 1; } for (;;) { state = pa_stream_get_state(pulse_data->stream); if (state == PA_STREAM_READY) break; if (!PA_STREAM_IS_GOOD(state)) { LLOGLN(0, ("rdpsnd_pulse_open: bad stream state (%d)", pa_context_errno(pulse_data->context))); break; } pa_threaded_mainloop_wait(pulse_data->mainloop); } pa_threaded_mainloop_unlock(pulse_data->mainloop); if (state == PA_STREAM_READY) { memset(&pulse_data->adpcm, 0, sizeof(rdpsndDspAdpcm)); LLOGLN(0, ("rdpsnd_pulse_open: connected")); return 0; } else { rdpsnd_pulse_close(devplugin); return 1; } }