Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/winepulse.drv/mmdevdrv.c | 8 +-- dlls/winepulse.drv/pulse.c | 122 ++++++++++++++++++++++++++++------ dlls/winepulse.drv/unixlib.h | 40 ++++++----- 3 files changed, 125 insertions(+), 45 deletions(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 7b5ef7cfe39..96b8b28d1b5 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -156,7 +156,7 @@ struct ACImpl { UINT32 channel_count; HANDLE timer;
- struct pulse_stream *pulse_stream; + unsigned int pulse_stream;
AudioSession *session; AudioSessionWrapper *session_wrapper; @@ -228,7 +228,7 @@ static void pulse_call(enum unix_funcs code, void *params) assert(!status); }
-static void pulse_release_stream(struct pulse_stream *stream, HANDLE timer) +static void pulse_release_stream(unsigned int stream, HANDLE timer) { struct release_stream_params params; params.stream = stream; @@ -668,7 +668,7 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface) if (!ref) { if (This->pulse_stream) { pulse_release_stream(This->pulse_stream, This->timer); - This->pulse_stream = NULL; + This->pulse_stream = 0; EnterCriticalSection(&session_cs); list_remove(&This->entry); LeaveCriticalSection(&session_cs); @@ -822,7 +822,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, ACImpl *This = impl_from_IAudioClient3(iface); struct create_stream_params params; unsigned int i, channel_count; - struct pulse_stream *stream; + unsigned int stream; char *name; HRESULT hr;
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 901e054f6d0..5e3ddcc9b6e 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -108,6 +108,18 @@ static const REFERENCE_TIME DefaultPeriod = 100000; static pthread_mutex_t pulse_mutex; static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER;
+struct stream_entry +{ + union + { + struct pulse_stream *stream; + unsigned int next_free; + }; +}; +static struct stream_entry *handles; +static unsigned int next_free = ~0u, next_unused, num_handles; +static pthread_mutex_t handle_lock = PTHREAD_MUTEX_INITIALIZER; + UINT8 mult_alaw_sample(UINT8, float); UINT8 mult_ulaw_sample(UINT8, float);
@@ -131,6 +143,73 @@ static void pulse_broadcast(void) pthread_cond_broadcast(&pulse_cond); }
+static unsigned int handle_alloc(struct pulse_stream *stream) +{ + unsigned int index, count; + struct stream_entry *new_handles; + + pthread_mutex_lock(&handle_lock); + + index = next_free; + if(index != ~0u) next_free = handles[index].next_free; + else if(next_unused < num_handles) index = next_unused++; + else{ + count = max(num_handles * 2, 256); + new_handles = realloc(handles, count); + if(!new_handles){ + pthread_mutex_unlock(&handle_lock); + return 0; + } + handles = new_handles; + num_handles = count; + index = next_unused++; + } + handles[index].stream = stream; + + pthread_mutex_unlock(&handle_lock); + + return index + 1; +} + +static struct stream_entry *handle_entry(unsigned int h) +{ + if(!h || h > num_handles){ + ERR("Invalid handle %08x\n", h); + return NULL; + } + return handles + h - 1; +} + +static void handle_free(unsigned int h) +{ + struct stream_entry *entry; + + pthread_mutex_lock(&handle_lock); + + entry = handle_entry(h); + if(entry){ + entry->next_free = next_free; + next_free = h - 1; + } + + pthread_mutex_unlock(&handle_lock); +} + +static struct pulse_stream *handle_get_stream(unsigned int h) +{ + struct stream_entry *entry; + struct pulse_stream *stream = NULL; + + pthread_mutex_lock(&handle_lock); + + entry = handle_entry(h); + if(entry) stream = entry->stream; + + pthread_mutex_unlock(&handle_lock); + + return stream; +} + static void dump_attr(const pa_buffer_attr *attr) { TRACE("maxlength: %u\n", attr->maxlength); @@ -1067,7 +1146,8 @@ static NTSTATUS pulse_create_stream(void *args) }
*params->channel_count = stream->ss.channels; - *params->stream = stream; + *params->stream = handle_alloc(stream); + if (!*params->stream) params->result = E_OUTOFMEMORY;
exit: if (FAILED(params->result = hr)) { @@ -1086,7 +1166,7 @@ exit: static NTSTATUS pulse_release_stream(void *args) { struct release_stream_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); SIZE_T size;
if(params->timer) { @@ -1114,6 +1194,7 @@ static NTSTATUS pulse_release_stream(void *args) NtFreeVirtualMemory(GetCurrentProcess(), (void **)&stream->local_buffer, &size, MEM_RELEASE); } + handle_free(params->stream); free(stream->peek_buffer); free(stream); return STATUS_SUCCESS; @@ -1407,7 +1488,7 @@ static void pulse_read(struct pulse_stream *stream) static NTSTATUS pulse_timer_loop(void *args) { struct timer_loop_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); LARGE_INTEGER delay; pa_usec_t last_time; UINT32 adv_bytes; @@ -1515,7 +1596,7 @@ static NTSTATUS pulse_timer_loop(void *args) static NTSTATUS pulse_start(void *args) { struct start_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); int success; pa_operation *o;
@@ -1571,7 +1652,7 @@ static NTSTATUS pulse_start(void *args) static NTSTATUS pulse_stop(void *args) { struct stop_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); pa_operation *o; int success;
@@ -1614,7 +1695,7 @@ static NTSTATUS pulse_stop(void *args) static NTSTATUS pulse_reset(void *args) { struct reset_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream);
pulse_lock(); if (!pulse_stream_valid(stream)) @@ -1720,7 +1801,7 @@ static UINT32 pulse_capture_padding(struct pulse_stream *stream) static NTSTATUS pulse_get_render_buffer(void *args) { struct get_render_buffer_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); size_t bytes; UINT32 wri_offs_bytes;
@@ -1799,7 +1880,7 @@ static void pulse_wrap_buffer(struct pulse_stream *stream, BYTE *buffer, UINT32 static NTSTATUS pulse_release_render_buffer(void *args) { struct release_render_buffer_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); UINT32 written_bytes; BYTE *buffer;
@@ -1856,7 +1937,7 @@ static NTSTATUS pulse_release_render_buffer(void *args) static NTSTATUS pulse_get_capture_buffer(void *args) { struct get_capture_buffer_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); ACPacket *packet;
pulse_lock(); @@ -1902,7 +1983,7 @@ static NTSTATUS pulse_get_capture_buffer(void *args) static NTSTATUS pulse_release_capture_buffer(void *args) { struct release_capture_buffer_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream);
pulse_lock(); if (!stream->locked && params->done) @@ -1937,14 +2018,15 @@ static NTSTATUS pulse_release_capture_buffer(void *args) static NTSTATUS pulse_get_buffer_size(void *args) { struct get_buffer_size_params *params = args; + struct pulse_stream *stream = handle_get_stream(params->stream);
params->result = S_OK;
pulse_lock(); - if (!pulse_stream_valid(params->stream)) + if (!pulse_stream_valid(stream)) params->result = AUDCLNT_E_DEVICE_INVALIDATED; else - *params->size = params->stream->bufsize_frames; + *params->size = stream->bufsize_frames; pulse_unlock();
return STATUS_SUCCESS; @@ -1953,7 +2035,7 @@ static NTSTATUS pulse_get_buffer_size(void *args) static NTSTATUS pulse_get_latency(void *args) { struct get_latency_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); const pa_buffer_attr *attr; REFERENCE_TIME lat;
@@ -1978,7 +2060,7 @@ static NTSTATUS pulse_get_latency(void *args) static NTSTATUS pulse_get_current_padding(void *args) { struct get_current_padding_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream);
pulse_lock(); if (!pulse_stream_valid(stream)) @@ -2003,7 +2085,7 @@ static NTSTATUS pulse_get_current_padding(void *args) static NTSTATUS pulse_get_next_packet_size(void *args) { struct get_next_packet_size_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream);
pulse_lock(); pulse_capture_padding(stream); @@ -2020,7 +2102,7 @@ static NTSTATUS pulse_get_next_packet_size(void *args) static NTSTATUS pulse_get_frequency(void *args) { struct get_frequency_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream);
pulse_lock(); if (!pulse_stream_valid(stream)) @@ -2041,7 +2123,7 @@ static NTSTATUS pulse_get_frequency(void *args) static NTSTATUS pulse_get_position(void *args) { struct get_position_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream);
pulse_lock(); if (!pulse_stream_valid(stream)) @@ -2079,7 +2161,7 @@ static NTSTATUS pulse_get_position(void *args) static NTSTATUS pulse_set_volumes(void *args) { struct set_volumes_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); unsigned int i;
for (i = 0; i < stream->ss.channels; i++) @@ -2091,7 +2173,7 @@ static NTSTATUS pulse_set_volumes(void *args) static NTSTATUS pulse_set_event_handle(void *args) { struct set_event_handle_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream); HRESULT hr = S_OK;
pulse_lock(); @@ -2112,7 +2194,7 @@ static NTSTATUS pulse_set_event_handle(void *args) static NTSTATUS pulse_is_started(void *args) { struct is_started_params *params = args; - struct pulse_stream *stream = params->stream; + struct pulse_stream *stream = handle_get_stream(params->stream);
pulse_lock(); params->started = pulse_stream_valid(stream) && stream->started; diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h index 9089e2829fc..e09362f0751 100644 --- a/dlls/winepulse.drv/unixlib.h +++ b/dlls/winepulse.drv/unixlib.h @@ -21,8 +21,6 @@
#define MAX_PULSE_NAME_LEN 256
-struct pulse_stream; - enum phys_device_bus_type { phys_device_bus_invalid = -1, phys_device_bus_pci, @@ -71,42 +69,42 @@ struct create_stream_params const WAVEFORMATEX *fmt; HRESULT result; UINT32 *channel_count; - struct pulse_stream **stream; + unsigned int *stream; };
struct release_stream_params { - struct pulse_stream *stream; + unsigned int stream; HANDLE timer; HRESULT result; };
struct start_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; };
struct stop_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; };
struct reset_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; };
struct timer_loop_params { - struct pulse_stream *stream; + unsigned int stream; };
struct get_render_buffer_params { - struct pulse_stream *stream; + unsigned int stream; UINT32 frames; HRESULT result; BYTE **data; @@ -114,7 +112,7 @@ struct get_render_buffer_params
struct release_render_buffer_params { - struct pulse_stream *stream; + unsigned int stream; UINT32 written_frames; DWORD flags; HRESULT result; @@ -122,7 +120,7 @@ struct release_render_buffer_params
struct get_capture_buffer_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; BYTE **data; UINT32 *frames; @@ -133,49 +131,49 @@ struct get_capture_buffer_params
struct release_capture_buffer_params { - struct pulse_stream *stream; + unsigned int stream; BOOL done; HRESULT result; };
struct get_buffer_size_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; UINT32 *size; };
struct get_latency_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; REFERENCE_TIME *latency; };
struct get_current_padding_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; UINT32 *padding; };
struct get_next_packet_size_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; UINT32 *frames; };
struct get_frequency_params { - struct pulse_stream *stream; + unsigned int stream; HRESULT result; UINT64 *freq; };
struct get_position_params { - struct pulse_stream *stream; + unsigned int stream; BOOL device; HRESULT result; UINT64 *pos; @@ -184,7 +182,7 @@ struct get_position_params
struct set_volumes_params { - struct pulse_stream *stream; + unsigned int stream; float master_volume; const float *volumes; const float *session_volumes; @@ -192,7 +190,7 @@ struct set_volumes_params
struct set_event_handle_params { - struct pulse_stream *stream; + unsigned int stream; HANDLE event; HRESULT result; }; @@ -206,7 +204,7 @@ struct test_connect_params
struct is_started_params { - struct pulse_stream *stream; + unsigned int stream; BOOL started; };