diff --git a/.gitignore b/.gitignore index 764ba8b..42cb21b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ /wine-1.3.24.tar.bz2.sign /wine-1.3.25.tar.bz2 /wine-1.3.25.tar.bz2.sign +/wine-1.3.26.tar.bz2 +/wine-1.3.26.tar.bz2.sign diff --git a/dlls_winepulse.drv_Makefile.in b/dlls_winepulse.drv_Makefile.in deleted file mode 100644 index 0f595f1..0000000 --- a/dlls_winepulse.drv_Makefile.in +++ /dev/null @@ -1,9 +0,0 @@ -MODULE = winepulse.drv -IMPORTS = dxguid uuid winmm user32 advapi32 ole32 -EXTRALIBS = @PULSELIBS@ @LIBPTHREAD@ -EXTRAINCL = @PULSEINCL@ - -C_SRCS = \ - mmdevdrv.c - -@MAKE_DLL_RULES@ diff --git a/dlls_winepulse.drv_mmdevdrv.c b/dlls_winepulse.drv_mmdevdrv.c deleted file mode 100644 index 8ba2a92..0000000 --- a/dlls_winepulse.drv_mmdevdrv.c +++ /dev/null @@ -1,2096 +0,0 @@ -/* - * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers - * Copyright 2011 Andrew Eikum for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * Pulseaudio driver support.. hell froze over - */ - -#define NONAMELESSUNION -#define COBJMACROS -#include "config.h" -#include -#include - -#include -#include -#include -#include - -#include - -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winreg.h" -#include "wine/debug.h" -#include "wine/unicode.h" -#include "wine/list.h" - -#include "ole2.h" -#include "dshow.h" -#include "dsound.h" -#include "propsys.h" - -#include "initguid.h" -#include "ks.h" -#include "ksmedia.h" -#include "mmdeviceapi.h" -#include "audioclient.h" -#include "endpointvolume.h" -#include "audiopolicy.h" - -#include "wine/list.h" - -WINE_DEFAULT_DEBUG_CHANNEL(pulse); - -static const REFERENCE_TIME MinimumPeriod = 100000; - -static pa_context *pulse_ctx; -static pa_mainloop *pulse_ml; - -static HANDLE pulse_thread; -static pthread_mutex_t pulse_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER; - -static struct list session_list = LIST_INIT( session_list ); - -typedef struct _AudioSession { - GUID guid; - - EDataFlow dataflow; - - float master_vol; - UINT32 channel_count; - float *channel_vols; - - struct list entry; -} AudioSession; - -typedef struct ACImpl { - IAudioClient IAudioClient_iface; - IAudioRenderClient IAudioRenderClient_iface; - IAudioCaptureClient IAudioCaptureClient_iface; - IAudioSessionControl2 IAudioSessionControl2_iface; - ISimpleAudioVolume ISimpleAudioVolume_iface; - IAudioClock IAudioClock_iface; - IAudioClock2 IAudioClock2_iface; - - LONG ref; - - IMMDevice *parent; - - EDataFlow dataflow; - DWORD flags; - AUDCLNT_SHAREMODE share; - HANDLE event; - - BOOL initted, started; - UINT32 bufsize_frames; - BYTE *locked_ptr, *tmp_buffer; - UINT32 locked, peeked, extra_buffered; - UINT64 play_ofs; - - pa_stream *stream; - pa_sample_spec ss; - pa_channel_map map; - - /* Mixer format + period times */ - pa_sample_spec mix_ss; - pa_channel_map mix_map; - REFERENCE_TIME min_period, def_period; -} ACImpl; - -static const WCHAR defaultW[] = {'P','u','l','s','e','a','u','d','i','o',0}; - -static const IAudioClientVtbl AudioClient_Vtbl; -static const IAudioRenderClientVtbl AudioRenderClient_Vtbl; -static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl; -static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl; -static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl; -static const IAudioClockVtbl AudioClock_Vtbl; -static const IAudioClock2Vtbl AudioClock2_Vtbl; - -static inline ACImpl *impl_from_IAudioClient(IAudioClient *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioClient_iface); -} - -static inline ACImpl *impl_from_IAudioRenderClient(IAudioRenderClient *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioRenderClient_iface); -} - -static inline ACImpl *impl_from_IAudioCaptureClient(IAudioCaptureClient *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioCaptureClient_iface); -} - -static inline ACImpl *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioSessionControl2_iface); -} - -static inline ACImpl *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, ISimpleAudioVolume_iface); -} - -static inline ACImpl *impl_from_IAudioClock(IAudioClock *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioClock_iface); -} - -static inline ACImpl *impl_from_IAudioClock2(IAudioClock2 *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioClock2_iface); -} - -/* Following pulseaudio design here, mainloop has the lock taken whenever - * it is handling something for pulse, and the lock is required whenever - * doing any pa_* call that can affect the state in any way - * - * pa_cond_wait is used when waiting on results, because the mainloop needs - * the same lock taken to affect the state - * - * This is basically the same as the pa_threaded_mainloop implementation, - * but that cannot be used because it uses pthread_create directly - * - * pa_threaded_mainloop_(un)lock -> pthread_mutex_(un)lock - * pa_threaded_mainloop_signal -> pthread_cond_signal - * pa_threaded_mainloop_wait -> pthread_cond_wait - */ - -static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) { - int r; - pthread_mutex_unlock(&pulse_lock); - r = poll(ufds, nfds, timeout); - pthread_mutex_lock(&pulse_lock); - return r; -} - -static DWORD CALLBACK pulse_mainloop_thread(void *tmp) { - int ret; - pulse_ml = pa_mainloop_new(); - pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL); - pthread_mutex_lock(&pulse_lock); - pthread_cond_signal(&pulse_cond); - pa_mainloop_run(pulse_ml, &ret); - pthread_mutex_unlock(&pulse_lock); - pa_mainloop_free(pulse_ml); - CloseHandle(pulse_thread); - return ret; -} - -static void pulse_contextcallback(pa_context *c, void *userdata); - -static HRESULT pulse_connect(void) -{ - int len; - WCHAR path[PATH_MAX], *name; - char *str; - - if (!pulse_thread) - { - if (!(pulse_thread = CreateThread(NULL, 0, pulse_mainloop_thread, NULL, 0, NULL))) - { - ERR("Failed to create mainloop thread."); - return E_FAIL; - } - pthread_cond_wait(&pulse_cond, &pulse_lock); - } - - if (pulse_ctx && PA_CONTEXT_IS_GOOD(pa_context_get_state(pulse_ctx))) - return S_OK; - if (pulse_ctx) - pa_context_unref(pulse_ctx); - - GetModuleFileNameW(NULL, path, sizeof(path)/sizeof(*path)); - name = strrchrW(path, '\\'); - if (!name) - name = path; - else - name++; - len = WideCharToMultiByte(CP_UNIXCP, 0, name, -1, NULL, 0, NULL, NULL); - str = pa_xmalloc(len); - WideCharToMultiByte(CP_UNIXCP, 0, name, -1, str, len, NULL, NULL); - TRACE("Name: %s\n", str); - pulse_ctx = pa_context_new(pa_mainloop_get_api(pulse_ml), str); - pa_xfree(str); - if (!pulse_ctx) { - ERR("Failed to create context\n"); - return E_FAIL; - } - - pa_context_set_state_callback(pulse_ctx, pulse_contextcallback, NULL); - - TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx), PA_API_VERSION); - if (pa_context_connect(pulse_ctx, NULL, 0, NULL) < 0) - goto fail; - - /* Wait for connection */ - while (pthread_cond_wait(&pulse_cond, &pulse_lock)) { - pa_context_state_t state = pa_context_get_state(pulse_ctx); - - if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED) - goto fail; - - if (state == PA_CONTEXT_READY) - break; - } - - TRACE("Connected to server %s with protocol version: %i.\n", - pa_context_get_server(pulse_ctx), - pa_context_get_server_protocol_version(pulse_ctx)); - return S_OK; - -fail: - pa_context_unref(pulse_ctx); - pulse_ctx = NULL; - return E_FAIL; -} - -static void pulse_contextcallback(pa_context *c, void *userdata) { - switch (pa_context_get_state(c)) { - default: - FIXME("Unhandled state: %i\n", pa_context_get_state(c)); - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - TRACE("State change to %i\n", pa_context_get_state(c)); - return; - - case PA_CONTEXT_READY: - TRACE("Ready\n"); - break; - - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - ERR("Context failed: %s\n", pa_strerror(pa_context_errno(c))); - } - pthread_cond_signal(&pulse_cond); -} - -static void pulse_stream_state(pa_stream *s, void *user); - -static HRESULT pulse_stream_valid(ACImpl *This) { - if (!This->initted) - return AUDCLNT_E_NOT_INITIALIZED; - if (!This->stream || pa_stream_get_state(This->stream) != PA_STREAM_READY) - return AUDCLNT_E_DEVICE_INVALIDATED; - return S_OK; -} - -static void dump_attr(const pa_buffer_attr *attr) { - TRACE("maxlength: %u\n", attr->maxlength); - TRACE("minreq: %u\n", attr->minreq); - TRACE("fragsize: %u\n", attr->fragsize); - TRACE("tlength: %u\n", attr->tlength); - TRACE("prebuf: %u\n", attr->prebuf); -} - -static void pulse_op_cb(pa_stream *s, int success, void *user) { - TRACE("Success: %i\n", success); - *(int*)user = success; - pthread_cond_signal(&pulse_cond); -} - -static void pulse_attr_update(pa_stream *s, void *user) { - const pa_buffer_attr *attr = pa_stream_get_buffer_attr(s); - TRACE("New attributes or device moved:\n"); - dump_attr(attr); -} - -static HRESULT pulse_stream_connect(ACImpl *This, REFERENCE_TIME period) { - int ret; - char buffer[64]; - static LONG number; - pa_buffer_attr attr; - if (This->stream) { - pa_stream_disconnect(This->stream); - while (pa_stream_get_state(This->stream) == PA_STREAM_READY) - pthread_cond_wait(&pulse_cond, &pulse_lock); - pa_stream_unref(This->stream); - } - ret = InterlockedIncrement(&number); - sprintf(buffer, "audio stream #%i", ret); - This->stream = pa_stream_new(pulse_ctx, buffer, &This->ss, &This->map); - pa_stream_set_state_callback(This->stream, pulse_stream_state, This); - pa_stream_set_buffer_attr_callback(This->stream, pulse_attr_update, This); - pa_stream_set_moved_callback(This->stream, pulse_attr_update, This); - - attr.maxlength = -1; - attr.tlength = This->bufsize_frames * pa_frame_size(&This->ss); - if (This->def_period > period) - period = This->def_period; - attr.minreq = attr.fragsize = pa_usec_to_bytes(period/10, &This->ss); - attr.prebuf = 0; - dump_attr(&attr); - if (This->dataflow == eRender) - ret = pa_stream_connect_playback(This->stream, NULL, &attr, - PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_EARLY_REQUESTS, NULL, NULL); - else - ret = pa_stream_connect_record(This->stream, NULL, &attr, - PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_EARLY_REQUESTS); - if (ret < 0) { - WARN("Returns %i\n", ret); - return AUDCLNT_E_ENDPOINT_CREATE_FAILED; - } - while (pa_stream_get_state(This->stream) == PA_STREAM_CREATING) - pthread_cond_wait(&pulse_cond, &pulse_lock); - if (pa_stream_get_state(This->stream) != PA_STREAM_READY) - return AUDCLNT_E_ENDPOINT_CREATE_FAILED; - return S_OK; -} - -static void pulse_stream_state(pa_stream *s, void *user) -{ - pa_stream_state_t state = pa_stream_get_state(s); - TRACE("Stream state changed to %i\n", state); - pthread_cond_signal(&pulse_cond); -} - -HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, void ***keys, - UINT *num, UINT *def_index) -{ - HRESULT hr = S_OK; - TRACE("%d %p %p %p\n", flow, ids, num, def_index); - - pthread_mutex_lock(&pulse_lock); - hr = pulse_connect(); - pthread_mutex_unlock(&pulse_lock); - if (FAILED(hr)) - return hr; - *num = 1; - *def_index = 0; - - *ids = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *)); - if(!*ids) - return E_OUTOFMEMORY; - - (*ids)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(defaultW)); - if(!(*ids)[0]){ - HeapFree(GetProcessHeap(), 0, *ids); - return E_OUTOFMEMORY; - } - - lstrcpyW((*ids)[0], defaultW); - - *keys = HeapAlloc(GetProcessHeap(), 0, sizeof(void *)); - (*keys)[0] = NULL; - - return S_OK; -} - -HRESULT WINAPI AUDDRV_GetAudioEndpoint(void *key, IMMDevice *dev, - EDataFlow dataflow, IAudioClient **out) -{ - HRESULT hr; - ACImpl *This; - - TRACE("%p %p %d %p\n", key, dev, dataflow, out); - - *out = NULL; - pthread_mutex_lock(&pulse_lock); - hr = pulse_connect(); - pthread_mutex_unlock(&pulse_lock); - if (FAILED(hr)) - return hr; - - This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl)); - if(!This) - return E_OUTOFMEMORY; - - This->IAudioClient_iface.lpVtbl = &AudioClient_Vtbl; - This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl; - This->IAudioCaptureClient_iface.lpVtbl = &AudioCaptureClient_Vtbl; - This->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl; - This->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl; - This->IAudioClock_iface.lpVtbl = &AudioClock_Vtbl; - This->IAudioClock2_iface.lpVtbl = &AudioClock2_Vtbl; - - This->dataflow = dataflow; - - if(dataflow != eRender && dataflow != eCapture) { - HeapFree(GetProcessHeap(), 0, This); - return E_UNEXPECTED; - } - - This->parent = dev; - IMMDevice_AddRef(This->parent); - - *out = &This->IAudioClient_iface; - IAudioClient_AddRef(&This->IAudioClient_iface); - - return S_OK; -} - -static HRESULT WINAPI AudioClient_QueryInterface(IAudioClient *iface, - REFIID riid, void **ppv) -{ - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClient)) - *ppv = iface; - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI AudioClient_AddRef(IAudioClient *iface) -{ - ACImpl *This = impl_from_IAudioClient(iface); - ULONG ref; - ref = InterlockedIncrement(&This->ref); - TRACE("(%p) Refcount now %u\n", This, ref); - return ref; -} - -static ULONG WINAPI AudioClient_Release(IAudioClient *iface) -{ - ACImpl *This = impl_from_IAudioClient(iface); - ULONG ref; - ref = InterlockedDecrement(&This->ref); - TRACE("(%p) Refcount now %u\n", This, ref); - if(!ref){ - IAudioClient_Stop(iface); - if (This->stream) { - pthread_mutex_lock(&pulse_lock); - if (pa_stream_get_state(This->stream) == PA_STREAM_READY) - pa_stream_disconnect(This->stream); - pa_stream_unref(This->stream); - pthread_mutex_unlock(&pulse_lock); - } - IMMDevice_Release(This->parent); - HeapFree(GetProcessHeap(), 0, This); - } - return ref; -} - -static void dump_fmt(const WAVEFORMATEX *fmt) -{ - TRACE("wFormatTag: 0x%x (", fmt->wFormatTag); - switch(fmt->wFormatTag){ - case WAVE_FORMAT_PCM: - TRACE("WAVE_FORMAT_PCM"); - break; - case WAVE_FORMAT_IEEE_FLOAT: - TRACE("WAVE_FORMAT_IEEE_FLOAT"); - break; - case WAVE_FORMAT_EXTENSIBLE: - TRACE("WAVE_FORMAT_EXTENSIBLE"); - break; - default: - TRACE("Unknown"); - break; - } - TRACE(")\n"); - - TRACE("nChannels: %u\n", fmt->nChannels); - TRACE("nSamplesPerSec: %u\n", fmt->nSamplesPerSec); - TRACE("nAvgBytesPerSec: %u\n", fmt->nAvgBytesPerSec); - TRACE("nBlockAlign: %u\n", fmt->nBlockAlign); - TRACE("wBitsPerSample: %u\n", fmt->wBitsPerSample); - TRACE("cbSize: %u\n", fmt->cbSize); - - if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){ - WAVEFORMATEXTENSIBLE *fmtex = (void*)fmt; - TRACE("dwChannelMask: %08x\n", fmtex->dwChannelMask); - TRACE("Samples: %04x\n", fmtex->Samples.wReserved); - TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat)); - } -} - -static WAVEFORMATEX *clone_format(const WAVEFORMATEX *fmt) -{ - WAVEFORMATEX *ret; - size_t size; - - if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) - size = sizeof(WAVEFORMATEXTENSIBLE); - else - size = sizeof(WAVEFORMATEX); - - ret = HeapAlloc(GetProcessHeap(), 0, size); - if(!ret) - return NULL; - - memcpy(ret, fmt, size); - - ret->cbSize = size - sizeof(WAVEFORMATEX); - - return ret; -} - -static DWORD get_channel_mask(unsigned int channels) -{ - switch(channels){ - case 0: - return 0; - case 1: - return SPEAKER_FRONT_CENTER; - case 2: - return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; - case 3: - return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | - SPEAKER_LOW_FREQUENCY; - case 4: - return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - case 5: - return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY; - case 6: - return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER; - case 7: - return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER | - SPEAKER_BACK_CENTER; - case 8: - return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER | - SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; - } - FIXME("Unknown speaker configuration: %u\n", channels); - return 0; -} - -static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, - AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration, - REFERENCE_TIME period, const WAVEFORMATEX *fmt, - const GUID *sessionguid) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr = S_OK; - - TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags, - wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid)); - - if(!fmt) - return E_POINTER; - - if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) - return AUDCLNT_E_NOT_INITIALIZED; - - if(flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS | - AUDCLNT_STREAMFLAGS_LOOPBACK | - AUDCLNT_STREAMFLAGS_EVENTCALLBACK | - AUDCLNT_STREAMFLAGS_NOPERSIST | - AUDCLNT_STREAMFLAGS_RATEADJUST | - AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED | - AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE | - AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED)){ - TRACE("Unknown flags: %08x\n", flags); - return E_INVALIDARG; - } - - pthread_mutex_lock(&pulse_lock); - if(This->initted){ - pthread_mutex_unlock(&pulse_lock); - return AUDCLNT_E_ALREADY_INITIALIZED; - } - pa_channel_map_init(&This->map); - This->ss.rate = fmt->nSamplesPerSec; - This->ss.format = PA_SAMPLE_INVALID; - switch(fmt->wFormatTag){ - case WAVE_FORMAT_PCM: - if(fmt->wBitsPerSample == 8) - This->ss.format = PA_SAMPLE_U8; - else if(fmt->wBitsPerSample == 16) - This->ss.format = PA_SAMPLE_S16LE; - if (fmt->nChannels == 1 || fmt->nChannels == 2) - pa_channel_map_init_auto(&This->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA); - break; - case WAVE_FORMAT_IEEE_FLOAT: - This->ss.format = PA_SAMPLE_FLOAT32LE; - if (fmt->nChannels == 1 || fmt->nChannels == 2) - pa_channel_map_init_auto(&This->map, fmt->nChannels, PA_CHANNEL_MAP_ALSA); - break; - case WAVE_FORMAT_EXTENSIBLE: { - WAVEFORMATEXTENSIBLE *wfe = (WAVEFORMATEXTENSIBLE*)fmt; - DWORD mask = wfe->dwChannelMask; - DWORD i = 0; - if (fmt->cbSize != (sizeof(*wfe) - sizeof(*fmt)) && fmt->cbSize != sizeof(*wfe)) - break; - if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) - This->ss.format = PA_SAMPLE_FLOAT32LE; - else if (IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) - { - DWORD valid = wfe->Samples.wValidBitsPerSample; - if (!valid) - valid = fmt->wBitsPerSample; - if (!valid || valid > fmt->wBitsPerSample) - break; - switch (fmt->wBitsPerSample) { - case 8: - if (valid == 8) - This->ss.format = PA_SAMPLE_U8; - break; - case 16: - if (valid == 16) - This->ss.format = PA_SAMPLE_S16LE; - break; - case 24: - if (valid == 24) - This->ss.format = PA_SAMPLE_S24LE; - break; - case 32: - if (valid == 24) - This->ss.format = PA_SAMPLE_S24_32LE; - else if (valid == 32) - This->ss.format = PA_SAMPLE_S32LE; - default: - break; - } - } - This->map.channels = fmt->nChannels; - if (!mask) - mask = get_channel_mask(fmt->nChannels); - if (mask & SPEAKER_FRONT_LEFT) This->map.map[i++] = PA_CHANNEL_POSITION_FRONT_LEFT; - if (mask & SPEAKER_FRONT_RIGHT) This->map.map[i++] = PA_CHANNEL_POSITION_FRONT_RIGHT; - if (mask & SPEAKER_FRONT_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_FRONT_CENTER; - if (mask & SPEAKER_LOW_FREQUENCY) This->map.map[i++] = PA_CHANNEL_POSITION_SUBWOOFER; - if (mask & SPEAKER_BACK_LEFT) This->map.map[i++] = PA_CHANNEL_POSITION_REAR_LEFT; - if (mask & SPEAKER_BACK_RIGHT) This->map.map[i++] = PA_CHANNEL_POSITION_REAR_RIGHT; - if (mask & SPEAKER_BACK_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_REAR_CENTER; - if (mask & SPEAKER_FRONT_LEFT_OF_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; - if (mask & SPEAKER_FRONT_RIGHT_OF_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; - if (mask & SPEAKER_BACK_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_REAR_CENTER; - if (mask & SPEAKER_SIDE_LEFT) This->map.map[i++] = PA_CHANNEL_POSITION_SIDE_LEFT; - if (mask & SPEAKER_SIDE_RIGHT) This->map.map[i++] = PA_CHANNEL_POSITION_SIDE_RIGHT; - if (mask & SPEAKER_TOP_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_TOP_CENTER; - if (mask & SPEAKER_TOP_FRONT_LEFT) This->map.map[i++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT; - if (mask & SPEAKER_TOP_FRONT_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER; - if (mask & SPEAKER_TOP_FRONT_RIGHT) This->map.map[i++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; - if (mask & SPEAKER_TOP_BACK_LEFT) This->map.map[i++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT; - if (mask & SPEAKER_TOP_BACK_CENTER) This->map.map[i++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER; - if (mask & SPEAKER_TOP_BACK_RIGHT) This->map.map[i++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT; - if (mask & SPEAKER_ALL) { - This->map.map[i++] = PA_CHANNEL_POSITION_MONO; - FIXME("Is the 'all' channel mapped correctly?\n"); - } - if (i != fmt->nChannels || mask & SPEAKER_RESERVED) { - This->map.channels = 0; - FIXME("Invalid channel mask: %i/%i and %x\n", i, fmt->nChannels, mask); - break; - } - /* Special case for mono since pulse appears to map it differently */ - if (mask == SPEAKER_FRONT_CENTER) - This->map.map[0] = PA_CHANNEL_POSITION_MONO; - break; - } - default: FIXME("Unhandled tag %x\n", fmt->wFormatTag); - } - This->ss.channels = This->map.channels; - hr = AUDCLNT_E_UNSUPPORTED_FORMAT; - if (!pa_channel_map_valid(&This->map) || This->ss.format == PA_SAMPLE_INVALID) { - WARN("Invalid format! Channel spec valid: %i, format: %i\n", pa_channel_map_valid(&This->map), This->ss.format); - dump_fmt(fmt); - goto exit; - } - if (duration < 5000000) - This->bufsize_frames = fmt->nSamplesPerSec/2; - else if (duration < 20000000) - This->bufsize_frames = ceil((duration / 10000000.) * fmt->nSamplesPerSec); - else - This->bufsize_frames = 2 * fmt->nSamplesPerSec; - - hr = pulse_stream_connect(This, period); - if (SUCCEEDED(hr)) { - /* Update frames according to new size */ - This->bufsize_frames = pa_stream_get_buffer_attr(This->stream)->tlength / pa_frame_size(&This->ss); - //hr = AudioSession_CreateSession(This, sessionguid ? sessionguid : &GUID_NULL); - if (SUCCEEDED(hr)) - This->initted = TRUE; - } - This->share = mode; - This->flags = flags; - -exit: - if(FAILED(hr)) { - if (This->stream) { - pa_stream_disconnect(This->stream); - pa_stream_unref(This->stream); - This->stream = NULL; - } - } - pthread_mutex_unlock(&pulse_lock); - return hr; -} - -static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient *iface, - UINT32 *out) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr; - - TRACE("(%p)->(%p)\n", This, out); - - if(!out) - return E_POINTER; - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if (SUCCEEDED(hr)) - *out = This->bufsize_frames; - pthread_mutex_unlock(&pulse_lock); - - return hr; -} - -static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface, - REFERENCE_TIME *latency) -{ - ACImpl *This = impl_from_IAudioClient(iface); - const pa_buffer_attr *attr; - REFERENCE_TIME lat; - HRESULT hr; - - TRACE("(%p)->(%p)\n", This, latency); - - if(!latency) - return E_POINTER; - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if (FAILED(hr)) { - pthread_mutex_unlock(&pulse_lock); - return hr; - } - attr = pa_stream_get_buffer_attr(This->stream); - if (This->dataflow == eCapture) - lat = attr->fragsize / pa_frame_size(&This->ss); - else - lat = attr->minreq / pa_frame_size(&This->ss); - *latency = 10000000; - *latency *= lat; - *latency /= This->ss.rate; - pthread_mutex_unlock(&pulse_lock); - TRACE("Latency: %u ms\n", (DWORD)(*latency / 10000)); - return S_OK; -} - -static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface, - UINT32 *out) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr; - - TRACE("(%p)->(%p)\n", This, out); - - if(!out) - return E_POINTER; - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if (FAILED(hr)) { - pthread_mutex_unlock(&pulse_lock); - return hr; - } - - if(This->dataflow == eRender){ - UINT32 avail = pa_stream_writable_size(This->stream) / pa_frame_size(&This->ss); - if (avail + This->extra_buffered >= This->bufsize_frames) - *out = 0; - else - *out = This->bufsize_frames - avail - This->extra_buffered; - }else if(This->dataflow == eCapture){ - if (!This->peeked) { - DWORD frag, readable = pa_stream_readable_size(This->stream); - pa_stream_peek(This->stream, (const void**)&This->locked_ptr, &frag); - if (frag != readable) { - DWORD done = frag; - This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, readable); - memcpy(This->tmp_buffer, This->locked_ptr, frag); - pa_stream_drop(This->stream); - while (done < readable) { - pa_stream_peek(This->stream, (const void **)&This->locked_ptr, &frag); - memcpy(This->tmp_buffer + done, This->locked_ptr, frag); - pa_stream_drop(This->stream); - done += frag; - } - if (done > readable) - ERR("Read %u instead of %u\n", done, This->peeked); - This->locked_ptr = NULL; - } - This->peeked = readable; - } - *out = This->peeked / pa_frame_size(&This->ss); - }else{ - pthread_mutex_unlock(&pulse_lock); - return E_UNEXPECTED; - } - pthread_mutex_unlock(&pulse_lock); - - TRACE("Pad: %u\n", *out); - - return S_OK; -} - -static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface, - AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *fmt, - WAVEFORMATEX **out) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr = S_OK; - WAVEFORMATEX *closest = NULL; - WAVEFORMATEXTENSIBLE *wfe; - - TRACE("(%p)->(%x, %p, %p)\n", This, mode, fmt, out); - - if(!fmt || (mode == AUDCLNT_SHAREMODE_SHARED && !out)) - return E_POINTER; - - if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) - return E_INVALIDARG; - - if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE && - fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) - return E_INVALIDARG; - - dump_fmt(fmt); - - closest = clone_format(fmt); - if(!closest){ - hr = E_OUTOFMEMORY; - goto exit; - } - wfe = (WAVEFORMATEXTENSIBLE*)closest; - if (closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE && !wfe->dwChannelMask) { - wfe->dwChannelMask = get_channel_mask(closest->nChannels); - hr = S_FALSE; - WARN("Fixed up channel mask %p -> %p\n", fmt, closest); - } - -exit: - if(hr == S_OK || !out){ - HeapFree(GetProcessHeap(), 0, closest); - if(out) - *out = NULL; - }else if(closest){ - closest->nBlockAlign = - closest->nChannels * closest->wBitsPerSample / 8; - closest->nAvgBytesPerSec = - closest->nBlockAlign * closest->nSamplesPerSec; - *out = closest; - } - - TRACE("returning: %08x %p\n", hr, out ? *out : NULL); - return hr; -} - -static void pulse_probe_settings(ACImpl *This) { - pa_stream *stream; - pa_channel_map map; - pa_sample_spec ss; - pa_buffer_attr attr; - int ret; - unsigned int length = 0; - - if (This->mix_ss.rate) - return; - - pa_channel_map_init_auto(&map, 2, PA_CHANNEL_MAP_ALSA); - ss.rate = 48000; - ss.format = PA_SAMPLE_FLOAT32LE; - ss.channels = map.channels; - - attr.maxlength = -1; - attr.tlength = -1; - attr.minreq = attr.fragsize = pa_frame_size(&ss); - attr.prebuf = 0; - - stream = pa_stream_new(pulse_ctx, "format test stream", &ss, &map); - if (stream) - pa_stream_set_state_callback(stream, pulse_stream_state, NULL); - if (!stream) - ret = -1; - else if (This->dataflow == eRender) - ret = pa_stream_connect_playback(stream, NULL, &attr, - PA_STREAM_START_CORKED|PA_STREAM_FIX_RATE|PA_STREAM_FIX_FORMAT|PA_STREAM_FIX_CHANNELS|PA_STREAM_EARLY_REQUESTS, NULL, NULL); - else - ret = pa_stream_connect_record(stream, NULL, &attr, - PA_STREAM_START_CORKED|PA_STREAM_FIX_RATE|PA_STREAM_FIX_FORMAT|PA_STREAM_FIX_CHANNELS|PA_STREAM_EARLY_REQUESTS); - if (ret >= 0) { - while (pa_stream_get_state(stream) == PA_STREAM_CREATING) - pthread_cond_wait(&pulse_cond, &pulse_lock); - if (pa_stream_get_state(stream) == PA_STREAM_READY) { - ss = *pa_stream_get_sample_spec(stream); - map = *pa_stream_get_channel_map(stream); - if (This->dataflow == eRender) - length = pa_stream_get_buffer_attr(stream)->minreq; - else - length = pa_stream_get_buffer_attr(stream)->fragsize; - pa_stream_disconnect(stream); - while (pa_stream_get_state(stream) == PA_STREAM_READY) - pthread_cond_wait(&pulse_cond, &pulse_lock); - } - } - if (stream) - pa_stream_unref(stream); - This->mix_ss = ss; - This->mix_map = map; - if (length) - This->def_period = This->min_period = pa_bytes_to_usec(10 * length, &This->mix_ss); - else - This->min_period = MinimumPeriod; - if (This->def_period <= MinimumPeriod) - This->def_period = MinimumPeriod; -} - -static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient *iface, - WAVEFORMATEX **pwfx) -{ - ACImpl *This = impl_from_IAudioClient(iface); - WAVEFORMATEXTENSIBLE *fmt; - HRESULT hr = S_OK; - int i; - - TRACE("(%p)->(%p)\n", This, pwfx); - - if(!pwfx) - return E_POINTER; - - *pwfx = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE)); - if(!*pwfx) - return E_OUTOFMEMORY; - - fmt = (WAVEFORMATEXTENSIBLE*)*pwfx; - - pthread_mutex_lock(&pulse_lock); - pulse_probe_settings(This); - pthread_mutex_unlock(&pulse_lock); - - (*pwfx)->wFormatTag = WAVE_FORMAT_EXTENSIBLE; - (*pwfx)->cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); - (*pwfx)->nChannels = This->mix_ss.channels; - (*pwfx)->wBitsPerSample = 8 * pa_sample_size_of_format(This->mix_ss.format); - (*pwfx)->nSamplesPerSec = This->mix_ss.rate; - (*pwfx)->nBlockAlign = (*pwfx)->nChannels * (*pwfx)->wBitsPerSample / 8; - (*pwfx)->nAvgBytesPerSec = (*pwfx)->nSamplesPerSec * (*pwfx)->nBlockAlign; - if (This->mix_ss.format != PA_SAMPLE_S24_32LE) - fmt->Samples.wValidBitsPerSample = (*pwfx)->wBitsPerSample; - else - fmt->Samples.wValidBitsPerSample = 24; - if (This->mix_ss.format == PA_SAMPLE_FLOAT32LE) - fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - else - fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - - fmt->dwChannelMask = 0; - for (i = 0; i < This->mix_map.channels; ++i) - switch (This->mix_map.map[i]) { - default: FIXME("Unhandled channel %s\n", pa_channel_position_to_string(This->mix_map.map[i])); break; - case PA_CHANNEL_POSITION_FRONT_LEFT: fmt->dwChannelMask |= SPEAKER_FRONT_LEFT; break; - case PA_CHANNEL_POSITION_FRONT_RIGHT: fmt->dwChannelMask |= SPEAKER_FRONT_RIGHT; break; - case PA_CHANNEL_POSITION_MONO: - case PA_CHANNEL_POSITION_FRONT_CENTER: fmt->dwChannelMask |= SPEAKER_FRONT_CENTER; break; - case PA_CHANNEL_POSITION_REAR_LEFT: fmt->dwChannelMask |= SPEAKER_BACK_LEFT; break; - case PA_CHANNEL_POSITION_REAR_RIGHT: fmt->dwChannelMask |= SPEAKER_BACK_RIGHT; break; - case PA_CHANNEL_POSITION_SUBWOOFER: fmt->dwChannelMask |= SPEAKER_LOW_FREQUENCY; break; - case PA_CHANNEL_POSITION_SIDE_LEFT: fmt->dwChannelMask |= SPEAKER_SIDE_LEFT; break; - case PA_CHANNEL_POSITION_SIDE_RIGHT: fmt->dwChannelMask |= SPEAKER_SIDE_RIGHT; break; - } - dump_fmt((WAVEFORMATEX*)fmt); - if(FAILED(hr)) { - CoTaskMemFree(*pwfx); - *pwfx = NULL; - } - - return hr; -} - -static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface, - REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod) -{ - ACImpl *This = impl_from_IAudioClient(iface); - - TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod); - - if(!defperiod && !minperiod) - return E_POINTER; - - pthread_mutex_lock(&pulse_lock); - pulse_probe_settings(This); - if(defperiod) - *defperiod = This->def_period; - if(minperiod) - *minperiod = This->min_period; - pthread_mutex_unlock(&pulse_lock); - - return S_OK; -} - -static HRESULT WINAPI AudioClient_Start(IAudioClient *iface) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr = S_OK; - int success; - pa_operation *o; - - TRACE("(%p)\n", This); - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if (FAILED(hr)) { - pthread_mutex_unlock(&pulse_lock); - return hr; - } - - if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){ - pthread_mutex_unlock(&pulse_lock); - return AUDCLNT_E_EVENTHANDLE_NOT_SET; - } - - if(This->started){ - pthread_mutex_unlock(&pulse_lock); - return AUDCLNT_E_NOT_STOPPED; - } - - o = pa_stream_cork(This->stream, 0, pulse_op_cb, &success); - if (o) { - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pthread_cond_wait(&pulse_cond, &pulse_lock); - pa_operation_unref(o); - } else - success = 0; - if (!success) - hr = E_FAIL; - if (SUCCEEDED(hr)) - This->started = TRUE; - if (This->event) - SetEvent(This->event); - pthread_mutex_unlock(&pulse_lock); - return hr; -} - -static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr = S_OK; - pa_operation *o; - int success; - - TRACE("(%p)\n", This); - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if (FAILED(hr)) { - pthread_mutex_unlock(&pulse_lock); - return hr; - } - - if(!This->started){ - pthread_mutex_unlock(&pulse_lock); - return S_FALSE; - } - - o = pa_stream_cork(This->stream, 1, pulse_op_cb, &success); - if (o) { - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pthread_cond_wait(&pulse_cond, &pulse_lock); - pa_operation_unref(o); - } else - success = 0; - if (!success) - hr = E_FAIL; - if (SUCCEEDED(hr)) - This->started = FALSE; - pthread_mutex_unlock(&pulse_lock); - return hr; -} - -static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface) -{ - ACImpl *This = impl_from_IAudioClient(iface); - pa_usec_t time; - pa_operation *o; - int success; - HRESULT hr = S_OK; - - TRACE("(%p)\n", This); - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if (FAILED(hr)) { - pthread_mutex_unlock(&pulse_lock); - return hr; - } - - if(This->started){ - pthread_mutex_unlock(&pulse_lock); - return AUDCLNT_E_NOT_STOPPED; - } - - if (pa_stream_get_time(This->stream, &time) >= 0) - This->play_ofs += time * This->ss.rate / 1000000; - - o = pa_stream_flush(This->stream, pulse_op_cb, &success); - if (o) { - while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) - pthread_cond_wait(&pulse_cond, &pulse_lock); - pa_operation_unref(o); - } else - success = 0; - if (!success) - hr = S_FALSE; - pthread_mutex_unlock(&pulse_lock); - - return hr; -} - -static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient *iface, - HANDLE event) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr; - - TRACE("(%p)->(%p)\n", This, event); - - if(!event) - return E_INVALIDARG; - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if (FAILED(hr)) { - pthread_mutex_unlock(&pulse_lock); - return hr; - } - - if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){ - pthread_mutex_unlock(&pulse_lock); - return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED; - } - This->event = event; - pthread_mutex_unlock(&pulse_lock); - return S_OK; -} - -static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid, - void **ppv) -{ - ACImpl *This = impl_from_IAudioClient(iface); - HRESULT hr; - - TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - pthread_mutex_unlock(&pulse_lock); - if (FAILED(hr)) - return hr; - - if(IsEqualIID(riid, &IID_IAudioRenderClient)){ - if(This->dataflow != eRender) - return AUDCLNT_E_WRONG_ENDPOINT_TYPE; - *ppv = &This->IAudioRenderClient_iface; - }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){ - if(This->dataflow != eCapture) - return AUDCLNT_E_WRONG_ENDPOINT_TYPE; - *ppv = &This->IAudioCaptureClient_iface; - }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){ - *ppv = &This->IAudioSessionControl2_iface; - }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){ - *ppv = &This->ISimpleAudioVolume_iface; - }else if(IsEqualIID(riid, &IID_IAudioClock)){ - *ppv = &This->IAudioClock_iface; - } - - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - FIXME("stub %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static const IAudioClientVtbl AudioClient_Vtbl = -{ - AudioClient_QueryInterface, - AudioClient_AddRef, - AudioClient_Release, - AudioClient_Initialize, - AudioClient_GetBufferSize, - AudioClient_GetStreamLatency, - AudioClient_GetCurrentPadding, - AudioClient_IsFormatSupported, - AudioClient_GetMixFormat, - AudioClient_GetDevicePeriod, - AudioClient_Start, - AudioClient_Stop, - AudioClient_Reset, - AudioClient_SetEventHandle, - AudioClient_GetService -}; - -static HRESULT WINAPI AudioRenderClient_QueryInterface( - IAudioRenderClient *iface, REFIID riid, void **ppv) -{ - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IAudioRenderClient)) - *ppv = iface; - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface) -{ - ACImpl *This = impl_from_IAudioRenderClient(iface); - return AudioClient_AddRef(&This->IAudioClient_iface); -} - -static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface) -{ - ACImpl *This = impl_from_IAudioRenderClient(iface); - return AudioClient_Release(&This->IAudioClient_iface); -} - -static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface, - UINT32 frames, BYTE **data) -{ - ACImpl *This = impl_from_IAudioRenderClient(iface); - UINT32 requested, avail; - HRESULT hr = S_OK; - - TRACE("(%p)->(%u, %p)\n", This, frames, data); - - if(!data) - return E_POINTER; - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if(FAILED(hr) || This->locked){ - pthread_mutex_unlock(&pulse_lock); - return FAILED(hr) ? hr : AUDCLNT_E_OUT_OF_ORDER; - } - avail = pa_stream_writable_size(This->stream) / pa_frame_size(&This->ss); - if (avail < frames){ - pthread_mutex_unlock(&pulse_lock); - WARN("Wanted to write %u, but only %u available\n", frames, avail); - return AUDCLNT_E_BUFFER_TOO_LARGE; - } - - requested = frames * pa_frame_size(&This->ss); - pa_stream_begin_write(This->stream, (void**)data, &requested); - This->locked = frames; - if (requested / pa_frame_size(&This->ss) < frames) { - pa_stream_cancel_write(This->stream); - FIXME("Unable to allocate all (%u/%u) preparing our own buffer\n", requested / pa_frame_size(&This->ss), frames); - *data = This->locked_ptr = This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, frames * pa_frame_size(&This->ss)); - } else { - This->locked_ptr = *data; - } - pthread_mutex_unlock(&pulse_lock); - return hr; -} - -static void free_heap(void *p) -{ - HeapFree(GetProcessHeap(), 0, p); -} - -static HRESULT WINAPI AudioRenderClient_ReleaseBuffer( - IAudioRenderClient *iface, UINT32 written_frames, DWORD flags) -{ - ACImpl *This = impl_from_IAudioRenderClient(iface); - int written; - - TRACE("(%p)->(%u, %x)\n", This, written_frames, flags); - - pthread_mutex_lock(&pulse_lock); - if(!This->locked || !written_frames){ - if (This->tmp_buffer) { - HeapFree(GetProcessHeap(), 0, This->tmp_buffer); - This->tmp_buffer = NULL; - } else if (This->locked) - pa_stream_cancel_write(This->stream); - This->locked = 0; - pthread_mutex_unlock(&pulse_lock); - return written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK; - } - - if(flags & AUDCLNT_BUFFERFLAGS_SILENT){ - if(This->ss.format == PA_SAMPLE_U8) - memset(This->locked_ptr, 128, written_frames * pa_frame_size(&This->ss)); - else - memset(This->locked_ptr, 0, written_frames * pa_frame_size(&This->ss)); - } - - This->locked = 0; - if (!This->tmp_buffer) - written = pa_stream_write(This->stream, This->locked_ptr, written_frames * pa_frame_size(&This->ss), NULL, 0, PA_SEEK_RELATIVE); - else - written = pa_stream_write(This->stream, This->locked_ptr, written_frames * pa_frame_size(&This->ss), free_heap, 0, PA_SEEK_RELATIVE); - This->tmp_buffer = NULL; - TRACE("Released %u, wrote %i\n", written_frames * pa_frame_size(&This->ss), written); - pthread_mutex_unlock(&pulse_lock); - - return S_OK; -} - -static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = { - AudioRenderClient_QueryInterface, - AudioRenderClient_AddRef, - AudioRenderClient_Release, - AudioRenderClient_GetBuffer, - AudioRenderClient_ReleaseBuffer -}; - -static HRESULT WINAPI AudioCaptureClient_QueryInterface( - IAudioCaptureClient *iface, REFIID riid, void **ppv) -{ - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IAudioCaptureClient)) - *ppv = iface; - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface) -{ - ACImpl *This = impl_from_IAudioCaptureClient(iface); - return IAudioClient_AddRef(&This->IAudioClient_iface); -} - -static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface) -{ - ACImpl *This = impl_from_IAudioCaptureClient(iface); - return IAudioClient_Release(&This->IAudioClient_iface); -} - -static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface, - BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos, - UINT64 *qpcpos) -{ - ACImpl *This = impl_from_IAudioCaptureClient(iface); - HRESULT hr; - - TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags, - devpos, qpcpos); - - if(!data || !frames || !flags) - return E_POINTER; - - pthread_mutex_lock(&pulse_lock); - hr = pulse_stream_valid(This); - if(FAILED(hr) || This->locked){ - pthread_mutex_unlock(&pulse_lock); - return FAILED(hr) ? hr : AUDCLNT_E_OUT_OF_ORDER; - } - *data = NULL; - *flags = 0; - *frames = This->peeked / pa_frame_size(&This->ss); - if (*frames) - *data = This->locked_ptr ? This->locked_ptr : This->tmp_buffer; - This->locked = *frames; - pthread_mutex_unlock(&pulse_lock); - if(devpos || qpcpos) - IAudioClock_GetPosition(&This->IAudioClock_iface, devpos, qpcpos); - - return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY; -} - -static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer( - IAudioCaptureClient *iface, UINT32 done) -{ - ACImpl *This = impl_from_IAudioCaptureClient(iface); - - TRACE("(%p)->(%u)\n", This, done); - - pthread_mutex_lock(&pulse_lock); - if (done) { - if (This->locked_ptr) { - pa_stream_drop(This->stream); - This->locked_ptr = NULL; - } else { - HeapFree(GetProcessHeap(), 0, This->tmp_buffer); - This->tmp_buffer = NULL; - } - This->peeked = 0; - } - This->locked = 0; - pthread_mutex_unlock(&pulse_lock); - return S_OK; -} - -static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize( - IAudioCaptureClient *iface, UINT32 *frames) -{ - ACImpl *This = impl_from_IAudioCaptureClient(iface); - - TRACE("(%p)->(%p)\n", This, frames); - return AudioClient_GetCurrentPadding(&This->IAudioClient_iface, frames); -} - -static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl = -{ - AudioCaptureClient_QueryInterface, - AudioCaptureClient_AddRef, - AudioCaptureClient_Release, - AudioCaptureClient_GetBuffer, - AudioCaptureClient_ReleaseBuffer, - AudioCaptureClient_GetNextPacketSize -}; - -static HRESULT WINAPI SimpleAudioVolume_QueryInterface( - ISimpleAudioVolume *iface, REFIID riid, void **ppv) -{ - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_ISimpleAudioVolume)) - *ppv = iface; - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface) -{ - ACImpl *This = impl_from_ISimpleAudioVolume(iface); - return IAudioClient_AddRef(&This->IAudioClient_iface); -} - -static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface) -{ - ACImpl *This = impl_from_ISimpleAudioVolume(iface); - return IAudioClient_Release(&This->IAudioClient_iface); -} - -static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume( - ISimpleAudioVolume *iface, float level, const GUID *context) -{ - ACImpl *This = impl_from_ISimpleAudioVolume(iface); - - FIXME("(%p)->(%f, %p) - stub\n", This, level, context); - - return E_NOTIMPL; -} - -static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume( - ISimpleAudioVolume *iface, float *level) -{ - ACImpl *This = impl_from_ISimpleAudioVolume(iface); - - FIXME("(%p)->(%p) - stub\n", This, level); - - return E_NOTIMPL; -} - -static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface, - BOOL mute, const GUID *context) -{ - ACImpl *This = impl_from_ISimpleAudioVolume(iface); - - FIXME("(%p)->(%u, %p) - stub\n", This, mute, context); - - return E_NOTIMPL; -} - -static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface, - BOOL *mute) -{ - ACImpl *This = impl_from_ISimpleAudioVolume(iface); - - FIXME("(%p)->(%p) - stub\n", This, mute); - - return E_NOTIMPL; -} - -static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl = -{ - SimpleAudioVolume_QueryInterface, - SimpleAudioVolume_AddRef, - SimpleAudioVolume_Release, - SimpleAudioVolume_SetMasterVolume, - SimpleAudioVolume_GetMasterVolume, - SimpleAudioVolume_SetMute, - SimpleAudioVolume_GetMute -}; - -static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface, - REFIID riid, void **ppv) -{ - ACImpl *This = impl_from_IAudioClock(iface); - - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock)) - *ppv = iface; - else if(IsEqualIID(riid, &IID_IAudioClock2)) - *ppv = &This->IAudioClock2_iface; - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface) -{ - ACImpl *This = impl_from_IAudioClock(iface); - return IAudioClient_AddRef(&This->IAudioClient_iface); -} - -static ULONG WINAPI AudioClock_Release(IAudioClock *iface) -{ - ACImpl *This = impl_from_IAudioClock(iface); - return IAudioClient_Release(&This->IAudioClient_iface); -} - -static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq) -{ - ACImpl *This = impl_from_IAudioClock(iface); - - TRACE("(%p)->(%p)\n", This, freq); - - *freq = This->ss.rate; - return S_OK; -} - -static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos, - UINT64 *qpctime) -{ - ACImpl *This = impl_from_IAudioClock(iface); - pa_usec_t time; - - TRACE("(%p)->(%p, %p)\n", This, pos, qpctime); - - if(!pos) - return E_POINTER; - - pthread_mutex_lock(&pulse_lock); - if (pa_stream_get_time(This->stream, &time) >= 0) - *pos = time * This->ss.rate / 1000000 - This->play_ofs; - else - *pos = This->play_ofs; - TRACE("Position: %u\n", (unsigned)*pos); - pthread_mutex_unlock(&pulse_lock); - - if(qpctime){ - LARGE_INTEGER stamp, freq; - QueryPerformanceCounter(&stamp); - QueryPerformanceFrequency(&freq); - *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart; - } - - return S_OK; -} - -static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface, - DWORD *chars) -{ - ACImpl *This = impl_from_IAudioClock(iface); - - TRACE("(%p)->(%p)\n", This, chars); - - if(!chars) - return E_POINTER; - - *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ; - - return S_OK; -} - -static const IAudioClockVtbl AudioClock_Vtbl = -{ - AudioClock_QueryInterface, - AudioClock_AddRef, - AudioClock_Release, - AudioClock_GetFrequency, - AudioClock_GetPosition, - AudioClock_GetCharacteristics -}; - -static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface, - REFIID riid, void **ppv) -{ - ACImpl *This = impl_from_IAudioClock2(iface); - return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv); -} - -static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface) -{ - ACImpl *This = impl_from_IAudioClock2(iface); - return IAudioClient_AddRef(&This->IAudioClient_iface); -} - -static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface) -{ - ACImpl *This = impl_from_IAudioClock2(iface); - return IAudioClient_Release(&This->IAudioClient_iface); -} - -static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface, - UINT64 *pos, UINT64 *qpctime) -{ - ACImpl *This = impl_from_IAudioClock2(iface); - return AudioClock_GetPosition(&This->IAudioClock_iface, pos, qpctime); -} - -static const IAudioClock2Vtbl AudioClock2_Vtbl = -{ - AudioClock2_QueryInterface, - AudioClock2_AddRef, - AudioClock2_Release, - AudioClock2_GetDevicePosition -}; - -static HRESULT WINAPI AudioSessionControl_QueryInterface( - IAudioSessionControl2 *iface, REFIID riid, void **ppv) -{ - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IAudioSessionControl) || - IsEqualIID(riid, &IID_IAudioSessionControl2)) - *ppv = iface; - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - return IAudioClient_AddRef(&This->IAudioClient_iface); -} - -static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - return IAudioClient_Release(&This->IAudioClient_iface); -} - -static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface, - AudioSessionState *state) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, state); - - if(!state) - return E_POINTER; - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_GetDisplayName( - IAudioSessionControl2 *iface, WCHAR **name) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, name); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_SetDisplayName( - IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session)); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_GetIconPath( - IAudioSessionControl2 *iface, WCHAR **path) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, path); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_SetIconPath( - IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session)); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_GetGroupingParam( - IAudioSessionControl2 *iface, GUID *group) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, group); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_SetGroupingParam( - IAudioSessionControl2 *iface, const GUID *group, const GUID *session) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group), - debugstr_guid(session)); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification( - IAudioSessionControl2 *iface, IAudioSessionEvents *events) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, events); - - return S_OK; -} - -static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification( - IAudioSessionControl2 *iface, IAudioSessionEvents *events) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, events); - - return S_OK; -} - -static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier( - IAudioSessionControl2 *iface, WCHAR **id) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, id); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier( - IAudioSessionControl2 *iface, WCHAR **id) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - FIXME("(%p)->(%p) - stub\n", This, id); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioSessionControl_GetProcessId( - IAudioSessionControl2 *iface, DWORD *pid) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - TRACE("(%p)->(%p)\n", This, pid); - - if(!pid) - return E_POINTER; - - *pid = GetCurrentProcessId(); - - return S_OK; -} - -static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession( - IAudioSessionControl2 *iface) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - TRACE("(%p)\n", This); - - return S_FALSE; -} - -static HRESULT WINAPI AudioSessionControl_SetDuckingPreference( - IAudioSessionControl2 *iface, BOOL optout) -{ - ACImpl *This = impl_from_IAudioSessionControl2(iface); - - TRACE("(%p)->(%d)\n", This, optout); - - return S_OK; -} - -static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl = -{ - AudioSessionControl_QueryInterface, - AudioSessionControl_AddRef, - AudioSessionControl_Release, - AudioSessionControl_GetState, - AudioSessionControl_GetDisplayName, - AudioSessionControl_SetDisplayName, - AudioSessionControl_GetIconPath, - AudioSessionControl_SetIconPath, - AudioSessionControl_GetGroupingParam, - AudioSessionControl_SetGroupingParam, - AudioSessionControl_RegisterAudioSessionNotification, - AudioSessionControl_UnregisterAudioSessionNotification, - AudioSessionControl_GetSessionIdentifier, - AudioSessionControl_GetSessionInstanceIdentifier, - AudioSessionControl_GetProcessId, - AudioSessionControl_IsSystemSoundsSession, - AudioSessionControl_SetDuckingPreference -}; - -typedef struct _SessionMgr { - IAudioSessionManager2 IAudioSessionManager2_iface; - - LONG ref; - - IMMDevice *device; -} SessionMgr; - -HRESULT WINAPI AudioSessionManager_QueryInterface(IAudioSessionManager2 *iface, - REFIID riid, void **ppv) -{ - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IAudioSessionManager) || - IsEqualIID(riid, &IID_IAudioSessionManager2)) - *ppv = iface; - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static inline SessionMgr *impl_from_IAudioSessionManager2(IAudioSessionManager2 *iface) -{ - return CONTAINING_RECORD(iface, SessionMgr, IAudioSessionManager2_iface); -} - -ULONG WINAPI AudioSessionManager_AddRef(IAudioSessionManager2 *iface) -{ - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - ULONG ref; - ref = InterlockedIncrement(&This->ref); - TRACE("(%p) Refcount now %u\n", This, ref); - return ref; -} - -ULONG WINAPI AudioSessionManager_Release(IAudioSessionManager2 *iface) -{ - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - ULONG ref; - ref = InterlockedDecrement(&This->ref); - TRACE("(%p) Refcount now %u\n", This, ref); - if(!ref) - HeapFree(GetProcessHeap(), 0, This); - return ref; -} - -HRESULT WINAPI AudioSessionManager_GetAudioSessionControl( - IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags, - IAudioSessionControl **out) -{ -#if 0 - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - AudioSession *session; - AudioSessionWrapper *wrapper; - HRESULT hr; - - TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid), - flags, out); - - hr = get_audio_session(session_guid, This->device, 0, &session); - if(FAILED(hr)) - return hr; - - wrapper = AudioSessionWrapper_Create(NULL); - if(!wrapper) - return E_OUTOFMEMORY; - - wrapper->session = session; - - *out = (IAudioSessionControl*)&wrapper->IAudioSessionControl2_iface; - - return S_OK; -#else - FIXME("stub\n"); - return E_NOTIMPL; -#endif -} - -HRESULT WINAPI AudioSessionManager_GetSimpleAudioVolume( - IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags, - ISimpleAudioVolume **out) -{ -#if 0 - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - AudioSession *session; - AudioSessionWrapper *wrapper; - HRESULT hr; - - TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid), - flags, out); - - hr = get_audio_session(session_guid, This->device, 0, &session); - if(FAILED(hr)) - return hr; - - wrapper = AudioSessionWrapper_Create(NULL); - if(!wrapper) - return E_OUTOFMEMORY; - - wrapper->session = session; - - *out = &wrapper->ISimpleAudioVolume_iface; - - return S_OK; -#else - FIXME("stub\n"); - return E_NOTIMPL; -#endif -} - -HRESULT WINAPI AudioSessionManager_GetSessionEnumerator( - IAudioSessionManager2 *iface, IAudioSessionEnumerator **out) -{ - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - FIXME("(%p)->(%p) - stub\n", This, out); - return E_NOTIMPL; -} - -HRESULT WINAPI AudioSessionManager_RegisterSessionNotification( - IAudioSessionManager2 *iface, IAudioSessionNotification *notification) -{ - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - FIXME("(%p)->(%p) - stub\n", This, notification); - return E_NOTIMPL; -} - -HRESULT WINAPI AudioSessionManager_UnregisterSessionNotification( - IAudioSessionManager2 *iface, IAudioSessionNotification *notification) -{ - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - FIXME("(%p)->(%p) - stub\n", This, notification); - return E_NOTIMPL; -} - -HRESULT WINAPI AudioSessionManager_RegisterDuckNotification( - IAudioSessionManager2 *iface, const WCHAR *session_id, - IAudioVolumeDuckNotification *notification) -{ - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - FIXME("(%p)->(%p) - stub\n", This, notification); - return E_NOTIMPL; -} - -HRESULT WINAPI AudioSessionManager_UnregisterDuckNotification( - IAudioSessionManager2 *iface, - IAudioVolumeDuckNotification *notification) -{ - SessionMgr *This = impl_from_IAudioSessionManager2(iface); - FIXME("(%p)->(%p) - stub\n", This, notification); - return E_NOTIMPL; -} - -static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl = -{ - AudioSessionManager_QueryInterface, - AudioSessionManager_AddRef, - AudioSessionManager_Release, - AudioSessionManager_GetAudioSessionControl, - AudioSessionManager_GetSimpleAudioVolume, - AudioSessionManager_GetSessionEnumerator, - AudioSessionManager_RegisterSessionNotification, - AudioSessionManager_UnregisterSessionNotification, - AudioSessionManager_RegisterDuckNotification, - AudioSessionManager_UnregisterDuckNotification -}; - -HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device, - IAudioSessionManager2 **out) -{ - SessionMgr *This; - - This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SessionMgr)); - if(!This) - return E_OUTOFMEMORY; - - This->IAudioSessionManager2_iface.lpVtbl = &AudioSessionManager2_Vtbl; - This->device = device; - This->ref = 1; - - *out = &This->IAudioSessionManager2_iface; - - return S_OK; -} diff --git a/dlls_winepulse.drv_winepulse.drv b/dlls_winepulse.drv_winepulse.drv deleted file mode 100644 index 819ea12..0000000 --- a/dlls_winepulse.drv_winepulse.drv +++ /dev/null @@ -1,4 +0,0 @@ -# MMDevAPI driver functions -@ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs -@ stdcall -private GetAudioEndpoint(ptr ptr long ptr) AUDDRV_GetAudioEndpoint -@ stdcall -private GetAudioSessionManager(ptr ptr) AUDDRV_GetAudioSessionManager diff --git a/sources b/sources index c732477..9e184fa 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -15471f78fee9d211c63381da815cbfb6 wine-1.3.25.tar.bz2 -ba96a3c648f23df05fc5c9d6c412292e wine-1.3.25.tar.bz2.sign +92ea09eb11aec92672671853ce9b792b wine-1.3.26.tar.bz2 +fceac48a09b2dc176c7ef9b22dc1b47a wine-1.3.26.tar.bz2.sign diff --git a/wine-pulseaudio-configure.patch b/wine-pulseaudio-configure.patch deleted file mode 100644 index eda998f..0000000 --- a/wine-pulseaudio-configure.patch +++ /dev/null @@ -1,223 +0,0 @@ ---- wine-1.3.25/configure.winepulse-configure 2011-07-22 19:32:43.000000000 +0200 -+++ wine-1.3.25/configure 2011-08-01 19:53:18.268715283 +0200 -@@ -628,6 +628,8 @@ - ALSALIBS - GSTREAMER_INCL - GSTREAMER_LIBS -+PULSEINCL -+PULSELIBS - LIBGETTEXTPO - ZLIB - FREETYPEINCL -@@ -799,6 +801,7 @@ - with_oss - with_png - with_pthread -+with_pulse - with_sane - with_tiff - with_v4l -@@ -1488,6 +1491,7 @@ - --without-oss do not use the OSS sound support - --without-png do not use PNG - --without-pthread do not use the pthread library -+ --without-pulse do not use PulseAudio sound support - --without-sane do not use SANE (scanner support) - --without-tiff do not use TIFF - --without-v4l do not use v4l1 (v4l support) -@@ -2661,6 +2665,12 @@ - fi - - -+# Check whether --with-pulse was given. -+if test "${with_pulse+set}" = set; then : -+ withval=$with_pulse; -+fi -+ -+ - # Check whether --with-sane was given. - if test "${with_sane+set}" = set; then : - withval=$with_sane; -@@ -10504,6 +10514,87 @@ - fi - fi - -+PULSELIBS="" -+ -+PULSEINCL="" -+ -+if test "x$with_pulse" != "xno"; -+then -+ ac_save_CPPFLAGS="$CPPFLAGS" -+ if test "$PKG_CONFIG" != "false"; -+ then -+ ac_pulse_libs="`$PKG_CONFIG --libs libpulse 2>/dev/null`" -+ ac_pulse_cflags="`$PKG_CONFIG --cflags-only-I libpulse 2>/dev/null`" -+ -+ CPPFLAGS="$CPPFLAGS $ac_pulse_cflags" -+ for ac_header in pulse/pulseaudio.h -+do : -+ ac_fn_c_check_header_mongrel "$LINENO" "pulse/pulseaudio.h" "ac_cv_header_pulse_pulseaudio_h" "$ac_includes_default" -+if test "x$ac_cv_header_pulse_pulseaudio_h" = xyes; then : -+ cat >>confdefs.h <<_ACEOF -+#define HAVE_PULSE_PULSEAUDIO_H 1 -+_ACEOF -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pa_stream_is_corked in -lpulse" >&5 -+$as_echo_n "checking for pa_stream_is_corked in -lpulse... " >&6; } -+if ${ac_cv_lib_pulse_pa_stream_is_corked+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ ac_check_lib_save_LIBS=$LIBS -+LIBS="-lpulse $ac_pulse_libs $LIBS" -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+/* Override any GCC internal prototype to avoid an error. -+ Use char because int might match the return type of a GCC -+ builtin and then its argument prototype would still apply. */ -+#ifdef __cplusplus -+extern "C" -+#endif -+char pa_stream_is_corked (); -+int -+main () -+{ -+return pa_stream_is_corked (); -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_link "$LINENO"; then : -+ ac_cv_lib_pulse_pa_stream_is_corked=yes -+else -+ ac_cv_lib_pulse_pa_stream_is_corked=no -+fi -+rm -f core conftest.err conftest.$ac_objext \ -+ conftest$ac_exeext conftest.$ac_ext -+LIBS=$ac_check_lib_save_LIBS -+fi -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pulse_pa_stream_is_corked" >&5 -+$as_echo "$ac_cv_lib_pulse_pa_stream_is_corked" >&6; } -+if test "x$ac_cv_lib_pulse_pa_stream_is_corked" = xyes; then : -+ -+$as_echo "#define HAVE_PULSEAUDIO 1" >>confdefs.h -+ -+ PULSELIBS="$ac_pulse_libs" -+ PULSEINCL="$ac_pulse_cflags" -+fi -+ -+ -+fi -+ -+done -+ -+ fi -+ CPPFLAGS="$ac_save_CPPFLAGS" -+fi -+if test "$ac_cv_lib_pulse_pa_stream_is_corked" != "yes"; then : -+ case "x$with_pulse" in -+ x) as_fn_append wine_warnings "|libpulse ${notice_platform}development files not found or too old, Pulse won't be supported." ;; -+ xno) ;; -+ *) as_fn_error $? "libpulse ${notice_platform}development files not found or too old, Pulse won't be supported. -+This is an error since --with-pulse was requested." "$LINENO" 5 ;; -+esac -+fi -+ - if test "x$with_gstreamer" != "xno" - then - ac_save_CPPFLAGS="$CPPFLAGS" -@@ -11742,12 +11833,13 @@ - - test -n "$ALSALIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no} - test -n "$COREAUDIO" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no} -+test -n "$PULSELIBS" || enable_winepulse_drv=${enable_winepulse_drv:-no} - test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no} - test "$ac_cv_header_linux_joystick_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no} - --if test "x$ALSALIBS$COREAUDIOLIBS" = "x" -a \ -+if test "x$ALSALIBS$COREAUDIOLIBS$PULSELIBS" = "x" -a \ - "x$ac_cv_member_oss_sysinfo_numaudioengines" != xyes -a \ -- "x$with_alsa$with_coreaudio$with_oss" != xnonono -+ "x$with_alsa$with_coreaudio$with_oss$with_pulse" != xnonono - then - as_fn_append wine_warnings "|No sound system was found. Windows applications will be silent." - fi -@@ -15155,10 +15247,12 @@ - wine_fn_config_dll winegstreamer enable_winegstreamer - wine_fn_config_dll winejoystick.drv enable_winejoystick_drv - wine_fn_config_dll winemapi enable_winemapi -+wine_fn_config_dll winemmaudio.drv enable_winemmaudio_drv - wine_fn_config_dll winemp3.acm enable_winemp3_acm - wine_fn_config_dll wineoss.drv enable_wineoss_drv - wine_fn_config_dll wineps.drv enable_wineps_drv install-lib - wine_fn_config_dll wineps16.drv16 enable_win16 -+wine_fn_config_dll winepulse.drv enable_winepulse_drv - wine_fn_config_dll wineqtdecoder enable_wineqtdecoder - wine_fn_config_dll winequartz.drv enable_winequartz_drv - wine_fn_config_dll winex11.drv enable_winex11_drv ---- wine-1.3.25/configure.ac.winepulse-configure 2011-07-22 19:32:43.000000000 +0200 -+++ wine-1.3.25/configure.ac 2011-08-01 19:51:41.206755129 +0200 -@@ -73,6 +73,7 @@ - [if test "x$withval" = "xno"; then ac_cv_header_png_h=no; fi]) - AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthread library]), - [if test "x$withval" = "xno"; then ac_cv_header_pthread_h=no; fi]) -+AC_ARG_WITH(pulse, AC_HELP_STRING([--without-pulse],[do not use PulseAudio sound support])) - AC_ARG_WITH(sane, AS_HELP_STRING([--without-sane],[do not use SANE (scanner support)])) - AC_ARG_WITH(tiff, AS_HELP_STRING([--without-tiff],[do not use TIFF]), - [if test "x$withval" = "xno"; then ac_cv_header_tiffio_h=no; fi]) -@@ -1435,6 +1436,30 @@ - WINE_WARNING_WITH(gettextpo,[test "x$LIBGETTEXTPO" = "x"],[GetText ${notice_platform}development files not found (or too old). Internationalization won't be fully supported.]) - fi - -+dnl **** Check for PulseAudio **** -+AC_SUBST(PULSELIBS,"") -+AC_SUBST(PULSEINCL,"") -+if test "x$with_pulse" != "xno"; -+then -+ ac_save_CPPFLAGS="$CPPFLAGS" -+ if test "$PKG_CONFIG" != "false"; -+ then -+ ac_pulse_libs="`$PKG_CONFIG --libs libpulse 2>/dev/null`" -+ ac_pulse_cflags="`$PKG_CONFIG --cflags-only-I libpulse 2>/dev/null`" -+ -+ CPPFLAGS="$CPPFLAGS $ac_pulse_cflags" -+ AC_CHECK_HEADERS(pulse/pulseaudio.h, -+ [AC_CHECK_LIB(pulse, pa_stream_is_corked, -+ [AC_DEFINE(HAVE_PULSEAUDIO, 1, [Define if you have pulseaudio]) -+ PULSELIBS="$ac_pulse_libs" -+ PULSEINCL="$ac_pulse_cflags"],,$ac_pulse_libs) -+ ]) -+ fi -+ CPPFLAGS="$ac_save_CPPFLAGS" -+fi -+WINE_WARNING_WITH(pulse, [test "$ac_cv_lib_pulse_pa_stream_is_corked" != "yes"], -+ [libpulse ${notice_platform}development files not found or too old, Pulse won't be supported.]) -+ - dnl **** Check for gstreamer **** - if test "x$with_gstreamer" != "xno" - then -@@ -1636,13 +1661,14 @@ - dnl **** Disable unsupported winmm drivers **** - test -n "$ALSALIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no} - test -n "$COREAUDIO" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no} -+test -n "$PULSELIBS" || enable_winepulse_drv=${enable_winepulse_drv:-no} - test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no} - test "$ac_cv_header_linux_joystick_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no} - - dnl **** Check for any sound system **** --if test "x$ALSALIBS$COREAUDIOLIBS" = "x" -a \ -+if test "x$ALSALIBS$COREAUDIOLIBS$PULSELIBS" = "x" -a \ - "x$ac_cv_member_oss_sysinfo_numaudioengines" != xyes -a \ -- "x$with_alsa$with_coreaudio$with_oss" != xnonono -+ "x$with_alsa$with_coreaudio$with_oss$with_pulse" != xnonono - then - WINE_WARNING([No sound system was found. Windows applications will be silent.]) - fi -@@ -2832,6 +2858,7 @@ - WINE_CONFIG_DLL(wineoss.drv) - WINE_CONFIG_DLL(wineps.drv,,[install-lib]) - WINE_CONFIG_DLL(wineps16.drv16,enable_win16) -+WINE_CONFIG_DLL(winepulse.drv) - WINE_CONFIG_DLL(wineqtdecoder) - WINE_CONFIG_DLL(winequartz.drv) - WINE_CONFIG_DLL(winex11.drv) diff --git a/wine-udisks1.patch b/wine-udisks1.patch index 597271a..f3213ff 100644 --- a/wine-udisks1.patch +++ b/wine-udisks1.patch @@ -1,33 +1,261 @@ From: Detlef Riekenberg -Subject: [PATCH 1/2] mountmgr: Make parse_uuid visible, when hal or dbus/udisks is used [try 4] -Message-Id: <1311335756-9824-1-git-send-email-wine.dev@web.de> -Date: Fri, 22 Jul 2011 13:55:55 +0200 +Subject: [PATCH] mountmgr: Support the dbus service udisks for dynamic devices :-) [try 5] +Message-Id: <1313451410-25324-1-git-send-email-wine.dev@web.de> +Date: Tue, 16 Aug 2011 01:36:50 +0200 + +This Patch allow the libhal requirement on linux to die. + +Recent distributions depend on udisks, so the libhal development package +should be uninstalled or disabled when building Wine (--without-hal). + +libhal support is still present for old OS without udisks support. + +The logic to add/remove the devices/volumes is the same as present in +our libhal support. + +autoheader/autoconf are needed before compilation + +try 5 +As requested by julliard, not moving around the parse_uuid helper and +no sync between hal support and udisks support. + +try 4 +sync to current git (wineesd was removed) -try 2: -make parse_uuid only visible, when hal or dbus/udisks is used try 3: -resend without changes -try 4: -Add a comment as reminder to parse NTFS serial number +changes for configure.ac where missing in try 2 + +try 2: +remove a trailing space in the code an a trailing " \" in Makefile.in -- By by ... Detlef --- - dlls/mountmgr.sys/device.c | 32 ++++++++++++++++++++++++++++++++ - dlls/mountmgr.sys/hal.c | 27 --------------------------- - dlls/mountmgr.sys/mountmgr.h | 1 + - 3 files changed, 33 insertions(+), 27 deletions(-) + configure.ac | 20 ++- + dlls/mountmgr.sys/Makefile.in | 5 +- + dlls/mountmgr.sys/mountmgr.c | 2 + + dlls/mountmgr.sys/mountmgr.h | 1 + + dlls/mountmgr.sys/udisks.c | 556 +++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 581 insertions(+), 3 deletions(-) + create mode 100644 dlls/mountmgr.sys/udisks.c -diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c -index a3aa81c..9537551 100644 ---- a/dlls/mountmgr.sys/device.c -+++ b/dlls/mountmgr.sys/device.c -@@ -121,6 +121,38 @@ static char *strdupA( const char *str ) - return ret; - } +diff --git a/configure.ac b/configure.ac +index e6bbb2a..09eb1c6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -42,6 +42,7 @@ AC_ARG_WITH(coreaudio, AS_HELP_STRING([--without-coreaudio],[do not use the Core + AC_ARG_WITH(cups, AS_HELP_STRING([--without-cups],[do not use CUPS])) + AC_ARG_WITH(curses, AS_HELP_STRING([--without-curses],[do not use (n)curses]), + [if test "x$withval" = "xno"; then ac_cv_header_ncurses_h=no; ac_cv_header_curses_h=no; fi]) ++AC_ARG_WITH(dbus, AS_HELP_STRING([--without-dbus],[do not use dbus (dynamic device support)])) + AC_ARG_WITH(fontconfig,AS_HELP_STRING([--without-fontconfig],[do not use fontconfig]), + [if test "x$withval" = "xno"; then ac_cv_header_fontconfig_fontconfig_h=no; fi]) + AC_ARG_WITH(freetype, AS_HELP_STRING([--without-freetype],[do not use the FreeType library])) +@@ -1201,6 +1202,23 @@ fi + WINE_WARNING_WITH(xslt,[test "x$ac_cv_lib_soname_xslt" = "x"], + [libxslt ${notice_platform}development files not found, xslt won't be supported.]) + ++dnl **** Check for libdbus **** ++AC_SUBST(DBUSINCL,"") ++if test "x$with_dbus" != "xno" ++then ++ ac_save_CPPFLAGS="$CPPFLAGS" ++ if test "$PKG_CONFIG" != "false" ++ then ++ ac_dbus_libs="`$PKG_CONFIG --libs dbus-1 2>/dev/null`" ++ ac_dbus_cflags="`$PKG_CONFIG --cflags dbus-1 2>/dev/null`" ++ CPPFLAGS="$CPPFLAGS $ac_dbus_cflags" ++ fi ++ AC_CHECK_HEADER(dbus/dbus.h, ++ [WINE_CHECK_SONAME(dbus-1,dbus_bus_get,[DBUSINCL="$ac_dbus_cflags"],,[$ac_dbus_libs])]) ++ ++ CPPFLAGS="$ac_save_CPPFLAGS" ++fi ++ + dnl **** Check for libhal **** + AC_SUBST(HALINCL,"") + if test "x$with_hal" != "xno" +@@ -1221,7 +1239,7 @@ then + fi + CPPFLAGS="$ac_save_CPPFLAGS" + fi +-WINE_NOTICE_WITH(hal,[test "x$ac_cv_lib_soname_hal" = "x" -a "x$ac_cv_header_DiskArbitration_DiskArbitration_h" != "xyes"], ++WINE_NOTICE_WITH(hal,[test "x$ac_cv_lib_soname_hal" = "x" -a "x$ac_cv_lib_soname_dbus_1" = "x" -a "x$ac_cv_header_DiskArbitration_DiskArbitration_h" != "xyes"], + [libhal/libdbus ${notice_platform}development files not found, no dynamic device support.]) + + dnl **** Check for libgnutls **** +diff --git a/dlls/mountmgr.sys/Makefile.in b/dlls/mountmgr.sys/Makefile.in +index 91203e1..f3355e0 100644 +--- a/dlls/mountmgr.sys/Makefile.in ++++ b/dlls/mountmgr.sys/Makefile.in +@@ -2,13 +2,14 @@ MODULE = mountmgr.sys + IMPORTS = uuid advapi32 ntoskrnl.exe + DELAYIMPORTS = user32 + EXTRADLLFLAGS = -Wb,--subsystem,native +-EXTRADEFS = @HALINCL@ ++EXTRADEFS = @HALINCL@ @DBUSINCL@ + EXTRALIBS = @DISKARBITRATIONLIB@ + + C_SRCS = \ + device.c \ + diskarb.c \ + hal.c \ +- mountmgr.c ++ mountmgr.c \ ++ udisks.c + + @MAKE_DLL_RULES@ +diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c +index 4e9900f..df0dbd3 100644 +--- a/dlls/mountmgr.sys/mountmgr.c ++++ b/dlls/mountmgr.sys/mountmgr.c +@@ -443,6 +443,8 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) + RtlInitUnicodeString( &nameW, harddiskW ); + status = IoCreateDriver( &nameW, harddisk_driver_entry ); + ++ /* start udisks before hal */ ++ initialize_udisks(); + initialize_hal(); + initialize_diskarbitration(); + +diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h +index a47a3e3..7d07b45 100644 +--- a/dlls/mountmgr.sys/mountmgr.h ++++ b/dlls/mountmgr.sys/mountmgr.h +@@ -35,6 +35,7 @@ + #define WINE_MOUNTMGR_EXTENSIONS + #include "ddk/mountmgr.h" + ++extern void initialize_udisks(void) DECLSPEC_HIDDEN; + extern void initialize_hal(void) DECLSPEC_HIDDEN; + extern void initialize_diskarbitration(void) DECLSPEC_HIDDEN; -+#if defined (SONAME_LIBDBUS_1) || defined (SONAME_LIBHAL) -+GUID *parse_uuid( GUID *guid, const char *str ) +diff --git a/dlls/mountmgr.sys/udisks.c b/dlls/mountmgr.sys/udisks.c +new file mode 100644 +index 0000000..6b7fe13 +--- /dev/null ++++ b/dlls/mountmgr.sys/udisks.c +@@ -0,0 +1,556 @@ ++/* ++ * udisks devices support ++ * ++ * Copyright 2006 Alexandre Julliard ++ * Copyright 2011 Detlef Riekenberg ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include "config.h" ++#include "wine/port.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "mountmgr.h" ++#include "winnls.h" ++#include "excpt.h" ++ ++#include "wine/library.h" ++#include "wine/exception.h" ++#include "wine/debug.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(mountmgr); ++ ++ ++static char udisks_version[32]; ++ ++#ifdef SONAME_LIBDBUS_1 ++ ++#include ++ ++/* ########## */ ++ ++typedef struct properties_s { ++ CHAR *device_file; ++ CHAR *id_usage; ++ CHAR *id_type; ++ CHAR *id_uuid; ++ BOOL device_is_mounted; ++ BOOL device_is_optical_disc; ++ BOOL device_is_removable; ++ CHAR *device_mount_paths; ++ CHAR *drive_media; ++ CHAR *drive_media_compatibility; ++ int depth; ++ const char * last_name; ++}properties_t; ++ ++static const char *my_match_rule = "interface=org.freedesktop.UDisks"; ++static const char *dest_udisks_device = "org.freedesktop.UDisks.Device"; ++static const char *dest_udisks = "org.freedesktop.UDisks"; ++static const char *path_udisks = "/org/freedesktop/UDisks"; ++static const char *iface_dbus_prop = "org.freedesktop.DBus.Properties"; ++static const char *daemonversion = "DaemonVersion"; ++ ++/* ########## */ ++ ++#define DBUS_FUNCS \ ++ DO_FUNC(dbus_bus_add_match); \ ++ DO_FUNC(dbus_bus_get); \ ++ DO_FUNC(dbus_bus_remove_match); \ ++ DO_FUNC(dbus_connection_pop_message); \ ++ DO_FUNC(dbus_connection_read_write_dispatch); \ ++ DO_FUNC(dbus_connection_send_with_reply_and_block); \ ++ DO_FUNC(dbus_connection_unref); \ ++ DO_FUNC(dbus_error_free); \ ++ DO_FUNC(dbus_error_init); \ ++ DO_FUNC(dbus_error_is_set); \ ++ DO_FUNC(dbus_message_append_args); \ ++ DO_FUNC(dbus_message_get_member); \ ++ DO_FUNC(dbus_message_iter_get_arg_type); \ ++ DO_FUNC(dbus_message_iter_get_basic); \ ++ DO_FUNC(dbus_message_iter_init); \ ++ DO_FUNC(dbus_message_iter_next); \ ++ DO_FUNC(dbus_message_iter_recurse); \ ++ DO_FUNC(dbus_message_new_method_call); \ ++ DO_FUNC(dbus_message_type_to_string); \ ++ DO_FUNC(dbus_message_unref) ++ ++#define DO_FUNC(f) static typeof(f) * p_##f ++DBUS_FUNCS; ++#undef DO_FUNC ++ ++ ++static BOOL load_dbus_functions(void) ++{ ++ void *dbus_handle; ++ char error[128]; ++ ++ if (!(dbus_handle = wine_dlopen(SONAME_LIBDBUS_1, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error)))) ++ goto failed; ++ ++#define DO_FUNC(f) if (!(p_##f = wine_dlsym(RTLD_DEFAULT, #f, error, sizeof(error)))) goto failed ++ DBUS_FUNCS; ++#undef DO_FUNC ++ ++ return TRUE; ++ ++failed: ++ WARN("failed to load udisks support: %s\n", error); ++ return FALSE; ++} ++ ++static GUID *parse_uuid( GUID *guid, const char *str ) +{ + /* standard uuid format */ + if (strlen(str) == 36) @@ -45,72 +273,425 @@ index a3aa81c..9537551 100644 + } + } + -+ /* ToDo: Check for NTFS serial number */ -+ + /* check for xxxx-xxxx format (FAT serial number) */ + if (strlen(str) == 9 && str[4] == '-') + { + memset( guid, 0, sizeof(*guid) ); + if (sscanf( str, "%hx-%hx", &guid->Data2, &guid->Data3 ) == 2) return guid; + } -+ + return NULL; +} -+#endif -+ - static const GUID *get_default_uuid( int letter ) - { - static GUID guid; -diff --git a/dlls/mountmgr.sys/hal.c b/dlls/mountmgr.sys/hal.c -index 82a70e9..ff10a3e 100644 ---- a/dlls/mountmgr.sys/hal.c -+++ b/dlls/mountmgr.sys/hal.c -@@ -106,33 +106,6 @@ static LONG WINAPI assert_fault(EXCEPTION_POINTERS *eptr) - return EXCEPTION_CONTINUE_SEARCH; - } - --static GUID *parse_uuid( GUID *guid, const char *str ) --{ -- /* standard uuid format */ -- if (strlen(str) == 36) -- { -- UNICODE_STRING strW; -- WCHAR buffer[39]; -- -- if (MultiByteToWideChar( CP_UNIXCP, 0, str, 36, buffer + 1, 36 )) -- { -- buffer[0] = '{'; -- buffer[37] = '}'; -- buffer[38] = 0; -- RtlInitUnicodeString( &strW, buffer ); -- if (!RtlGUIDFromString( &strW, guid )) return guid; -- } -- } -- -- /* check for xxxx-xxxx format (FAT serial number) */ -- if (strlen(str) == 9 && str[4] == '-') -- { -- memset( guid, 0, sizeof(*guid) ); -- if (sscanf( str, "%hx-%hx", &guid->Data2, &guid->Data3 ) == 2) return guid; -- } -- return NULL; --} -- - /* HAL callback for new device */ - static void new_device( LibHalContext *ctx, const char *udi ) - { -diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h -index a47a3e3..a8e4389 100644 ---- a/dlls/mountmgr.sys/mountmgr.h -+++ b/dlls/mountmgr.sys/mountmgr.h -@@ -52,6 +52,7 @@ enum device_type - DEVICE_RAMDISK - }; - -+extern GUID *parse_uuid( GUID *guid, const char *str ) DECLSPEC_HIDDEN; - extern NTSTATUS add_volume( const char *udi, const char *device, const char *mount_point, - enum device_type type, const GUID *guid ) DECLSPEC_HIDDEN; - extern NTSTATUS remove_volume( const char *udi ) DECLSPEC_HIDDEN; ++ ++static LONG WINAPI assert_fault(EXCEPTION_POINTERS *eptr) ++{ ++ if (eptr->ExceptionRecord->ExceptionCode == EXCEPTION_WINE_ASSERTION) ++ return EXCEPTION_EXECUTE_HANDLER; ++ return EXCEPTION_CONTINUE_SEARCH; ++} ++ ++/* ######################################### ++ * get_properties_from_iter [internal] ++ * ++ * NOTES ++ * format of args in a reply from GetAll: ++ * an ARRAY of DICT_ENTRY ++ * each DICT_ENTRY has a STRING (property name) and a VARIANT (property value) ++ * each VARIANT has a BOOLEAN or a STRING or an ARRAY of STRING or an here unused value ++ */ ++static BOOL get_properties_from_iter(properties_t * p, DBusMessageIter * iter) ++{ ++ DBusMessageIter sub; ++ int arg_type = p_dbus_message_iter_get_arg_type(iter); ++ ++ p->depth++; ++ while (arg_type != DBUS_TYPE_INVALID) ++ { ++ if ((arg_type == DBUS_TYPE_ARRAY) || ++ (arg_type == DBUS_TYPE_DICT_ENTRY) || ++ (arg_type == DBUS_TYPE_VARIANT)) ++ { ++ p_dbus_message_iter_recurse(iter, &sub); ++ if (!get_properties_from_iter(p, &sub)) ++ { ++ p->depth--; ++ return FALSE; ++ } ++ } ++ else if (arg_type == DBUS_TYPE_STRING) ++ { ++ char * data; ++ p_dbus_message_iter_get_basic(iter, &data); ++ if (p->depth == 3) p->last_name = data; ++ else if (p->last_name) ++ { ++ if (!strcmp(p->last_name, "DeviceFile")) ++ p->device_file = data; ++ else if (!strcmp(p->last_name, "DeviceMountPaths")) ++ p->device_mount_paths = data; /* use only the first entry */ ++ else if (!strcmp(p->last_name, "DriveMedia")) ++ p->drive_media = data; ++ else if (!strcmp(p->last_name, "DriveMediaCompatibility")) ++ p->drive_media_compatibility = data; /* use only the first entry */ ++ else if (!strcmp(p->last_name, "IdType")) ++ p->id_type = data; ++ else if (!strcmp(p->last_name, "IdUsage")) ++ p->id_usage = data; ++ else if (!strcmp(p->last_name, "IdUuid")) ++ p->id_uuid = data; ++ ++ p->last_name = NULL; ++ } ++ } ++ else if (arg_type == DBUS_TYPE_BOOLEAN) ++ { ++ dbus_bool_t data; ++ if (p->last_name) ++ { ++ p_dbus_message_iter_get_basic(iter, &data); ++ if (!strcmp(p->last_name, "DeviceIsMounted")) ++ p->device_is_mounted = data; ++ else if (!strcmp(p->last_name, "DeviceIsOpticalDisc")) ++ p->device_is_optical_disc = data; ++ else if (!strcmp(p->last_name, "DeviceIsRemovable")) ++ p->device_is_removable = data; ++ ++ p->last_name = NULL; ++ } ++ } ++ ++ p_dbus_message_iter_next(iter); ++ arg_type = p_dbus_message_iter_get_arg_type(iter); ++ } ++ p->depth--; ++ return TRUE; ++} ++ ++static DBusMessage * get_properties_from_path(properties_t * p, DBusConnection *ctx, const char * path) ++{ ++ DBusMessage *request; ++ DBusMessage *reply = NULL; ++ DBusMessageIter iter; ++ DBusError error; ++ ++ TRACE("(%p, %p, %s)\n", p, ctx, path); ++ ++ memset(p, 0, sizeof(properties_t)); ++ request = p_dbus_message_new_method_call(dest_udisks, path, iface_dbus_prop, "GetAll"); ++ if (request) ++ { ++ if (p_dbus_message_append_args(request, DBUS_TYPE_STRING, &dest_udisks_device, DBUS_TYPE_INVALID)) ++ { ++ p_dbus_error_init(&error); ++ if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error))) ++ { ++ p_dbus_message_iter_init(reply, &iter); ++ get_properties_from_iter(p, &iter); ++ } ++ else ++ WARN("no reply for %s\n", path); ++ ++ p_dbus_error_free(&error); ++ } ++ else ++ WARN("dbus_message_append_args failed for 'GetAll'\n"); ++ ++ p_dbus_message_unref(request); ++ } ++ return reply; ++} ++ ++static int get_drive_type(properties_t * p) ++{ ++ /* examples: optical_cd, optical_cd_rw, optical_dvd_plus_r_dl */ ++ if (p->device_is_optical_disc && p->drive_media && !memcmp(p->drive_media, "optical_", 8)) ++ { ++ if (!memcmp(p->drive_media + 8, "cd", 2)) ++ return DEVICE_CDROM; ++ else ++ return DEVICE_DVD; ++ } ++ else if (p->drive_media_compatibility && !strcmp(p->drive_media_compatibility, "floppy")) ++ return DEVICE_FLOPPY; ++ else if (!p->device_is_removable && p->id_usage && !strcmp(p->id_usage, "filesystem")) ++ return DEVICE_HARDDISK_VOL; ++ ++ return DEVICE_UNKNOWN; ++} ++ ++static void udisks_add_device(DBusConnection *ctx, const char *path) ++{ ++ DBusMessage *reply; ++ properties_t p; ++ GUID guid; ++ GUID *guid_ptr = NULL; ++ ++ TRACE("%s\n", debugstr_a(path)); ++ ++ reply = get_properties_from_path(&p, ctx, path); ++ if (reply) ++ { ++ int drive_type = get_drive_type(&p); ++ ++ TRACE("DeviceFile: %s\n", p.device_file); ++ TRACE("IdUsage: %s\n", p.id_usage); ++ TRACE("IdType: %s\n", p.id_type); ++ TRACE("IdUuid: %s\n", p.id_uuid); ++ TRACE("DeviceIsMounted: %d (%s)\n", p.device_is_mounted, p.device_is_mounted ? "true" : "false"); ++ TRACE("DeviceIsOpticalDisc: %d (%s)\n", p.device_is_optical_disc, p.device_is_optical_disc ? "true" : "false"); ++ TRACE("DeviceIsRemovable: %d (%s)\n", p.device_is_removable, p.device_is_removable ? "true" : "false"); ++ TRACE("DeviceMountPaths: %s\n", p.device_mount_paths); ++ TRACE("DriveMedia: %s\n", p.drive_media); ++ TRACE("DriveMediaCompatibility: %s\n", p.drive_media_compatibility); ++ TRACE("using drive_type: %d\n", drive_type); ++ ++ if (p.device_is_mounted && p.device_mount_paths) ++ { ++ if (p.id_uuid) ++ guid_ptr = parse_uuid(&guid, p.id_uuid); ++ ++ if (p.device_is_removable) ++ add_dos_device(-1, path, p.device_file, p.device_mount_paths, drive_type, guid_ptr); ++ else if (guid_ptr) ++ add_volume(path, p.device_file, p.device_mount_paths, DEVICE_HARDDISK_VOL, guid_ptr); ++ ++ } ++ p_dbus_message_unref(reply); ++ } ++} ++ ++static void udisks_remove_device(DBusConnection *ctx, const char *path) ++{ ++ TRACE("%s\n", debugstr_a(path)); ++ ++ if (remove_dos_device(-1, path)) ++ remove_volume(path); ++} ++ ++static void udisks_change_device(DBusConnection *ctx, const char *path) ++{ ++ DBusMessage *reply; ++ properties_t p; ++ ++ TRACE("%s\n", debugstr_a(path)); ++ ++ reply = get_properties_from_path(&p, ctx, path); ++ if (reply) ++ { ++ int drive_type = get_drive_type(&p); ++ ++ if (p.device_is_mounted && p.device_mount_paths) ++ udisks_add_device(ctx, path); ++ else ++ { ++ TRACE("DeviceFile: %s\n", p.device_file); ++ TRACE("IdUsage: %s\n", p.id_usage); ++ TRACE("IdType: %s\n", p.id_type); ++ TRACE("IdUuid: %s\n", p.id_uuid); ++ TRACE("DeviceIsMounted: %d (%s)\n", p.device_is_mounted, p.device_is_mounted ? "true" : "false"); ++ TRACE("DeviceIsOpticalDisc: %d (%s)\n", p.device_is_optical_disc, p.device_is_optical_disc ? "true" : "false"); ++ TRACE("DeviceIsRemovable: %d (%s)\n", p.device_is_removable, p.device_is_removable ? "true" : "false"); ++ TRACE("DeviceMountPaths: %s\n", p.device_mount_paths); ++ TRACE("DriveMedia: %s\n", p.drive_media); ++ TRACE("DriveMediaCompatibility: %s\n", p.drive_media_compatibility); ++ TRACE("using drive_type: %d\n", drive_type); ++ ++ udisks_remove_device(ctx, path); ++ } ++ p_dbus_message_unref(reply); ++ } ++} ++ ++/* ########### */ ++ ++static void udisks_get_all_devices(DBusConnection *ctx) ++{ ++ DBusMessage *request; ++ DBusMessage *reply; ++ DBusMessageIter iter; ++ DBusMessageIter sub; ++ DBusError error; ++ int arg_type; ++ ++ request = p_dbus_message_new_method_call(dest_udisks, path_udisks, dest_udisks, "EnumerateDevices"); ++ if (request) ++ { ++ p_dbus_error_init(&error); ++ if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error))) ++ { ++ p_dbus_message_iter_init(reply, &iter); ++ arg_type = p_dbus_message_iter_get_arg_type(&iter); ++ if (arg_type == DBUS_TYPE_ARRAY) ++ { ++ p_dbus_message_iter_recurse(&iter, &sub); ++ while ((arg_type = p_dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_OBJECT_PATH) ++ { ++ char * data; ++ p_dbus_message_iter_get_basic(&sub, &data); ++ udisks_add_device(ctx, data); ++ p_dbus_message_iter_next(&sub); ++ } ++ } ++ else ++ WARN("expected ARRAY, got %c\n", arg_type); ++ ++ p_dbus_message_unref(reply); ++ } ++ p_dbus_error_free(&error); ++ p_dbus_message_unref(request); ++ } ++} ++ ++static void udisks_get_version(DBusConnection *ctx) ++{ ++ DBusMessage *request; ++ DBusMessage *reply; ++ DBusMessageIter iter; ++ DBusMessageIter sub; ++ DBusError error; ++ int arg_type; ++ ++ request = p_dbus_message_new_method_call(dest_udisks, path_udisks, iface_dbus_prop, "Get"); ++ if (request) ++ { ++ if (p_dbus_message_append_args(request, DBUS_TYPE_STRING, &dest_udisks, ++ DBUS_TYPE_STRING, &daemonversion, ++ DBUS_TYPE_INVALID)) ++ { ++ p_dbus_error_init(&error); ++ if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error))) ++ { ++ p_dbus_message_iter_init(reply, &iter); ++ arg_type = p_dbus_message_iter_get_arg_type(&iter); ++ if (arg_type == DBUS_TYPE_VARIANT) ++ { ++ p_dbus_message_iter_recurse(&iter, &sub); ++ arg_type = p_dbus_message_iter_get_arg_type(&sub); ++ if (arg_type == DBUS_TYPE_STRING) ++ { ++ char * data; ++ p_dbus_message_iter_get_basic(&sub, &data); ++ lstrcpynA(udisks_version, data, sizeof(udisks_version) - 1); ++ TRACE("found udisks daemon %s\n", udisks_version); ++ } ++ else ++ WARN("expected STRING, got %c\n", arg_type); ++ ++ } ++ else ++ WARN("expected VARIANT, got %c\n", arg_type); ++ ++ p_dbus_message_unref(reply); ++ } ++ p_dbus_error_free(&error); ++ } ++ else ++ WARN("dbus_message_append_args failed\n"); ++ ++ p_dbus_message_unref(request); ++ } ++ return; ++ ++} ++ ++static DWORD WINAPI udisks_thread( void *arg ) ++{ ++ DBusConnection *ctx; ++ DBusMessage *msg; ++ DBusMessageIter iter; ++ DBusError error; ++ const char *member; ++ int arg_type; ++ char *data; ++ ++ p_dbus_error_init(&error); ++ ctx = p_dbus_bus_get(DBUS_BUS_SYSTEM, &error); ++ ++ if (!ctx) ++ { ++ WARN("failed to get system dbus connection: %s\n", error.message); ++ p_dbus_error_free(&error); ++ return 1; ++ } ++ ++ p_dbus_bus_add_match(ctx, my_match_rule, &error); ++ if (p_dbus_error_is_set(&error)) ++ { ++ WARN("add dbus filter failed: %s\n", error.message); ++ p_dbus_error_free(&error); ++ p_dbus_connection_unref(ctx); ++ return 1; ++ } ++ ++ udisks_get_version(ctx); ++ ++ if (!*udisks_version) ++ { ++ TRACE("udisks service not available\n"); ++ p_dbus_bus_remove_match(ctx, my_match_rule, NULL); ++ p_dbus_error_free(&error); ++ p_dbus_connection_unref(ctx); ++ return 1; ++ } ++ ++ __TRY ++ { ++ /* retrieve all existing devices */ ++ udisks_get_all_devices(ctx); ++ ++ while (p_dbus_connection_read_write_dispatch(ctx, -1 )) ++ { ++ while ((msg = p_dbus_connection_pop_message(ctx))) ++ { ++ member = p_dbus_message_get_member(msg); ++ p_dbus_message_iter_init(msg, &iter); ++ arg_type = p_dbus_message_iter_get_arg_type(&iter); ++ ++ if (arg_type == DBUS_TYPE_OBJECT_PATH) ++ p_dbus_message_iter_get_basic(&iter, &data); ++ ++ if (!lstrcmpA(member, "DeviceChanged")) ++ udisks_change_device(ctx, data); ++ else if (!lstrcmpA(member, "DeviceAdded")) ++ udisks_add_device(ctx, data); ++ else if (!lstrcmpA(member, "DeviceRemoved")) ++ udisks_remove_device(ctx, data); ++ else if (lstrcmpA(member, "DeviceJobChanged")) ++ WARN("got signal for %s\n", member); ++ ++ p_dbus_message_unref(msg); ++ } ++ } ++ } ++ __EXCEPT(assert_fault) ++ { ++ WARN("dbus assertion failure, disabling UDisks support\n"); ++ return 1; ++ } ++ __ENDTRY; ++ ++ p_dbus_bus_remove_match(ctx, my_match_rule, NULL); ++ p_dbus_error_free(&error); ++ p_dbus_connection_unref(ctx); ++ return 0; ++} ++ ++void initialize_udisks(void) ++{ ++ HANDLE handle = NULL; ++ ++ if (!load_dbus_functions()) return; ++ if (!(handle = CreateThread(NULL, 0, udisks_thread, NULL, 0, NULL))) return; ++ CloseHandle(handle); ++} ++ ++#else /* SONAME_LIBDBUS_1 */ ++ ++void initialize_udisks(void) ++{ ++ TRACE("Skipping, DBUS support not compiled in\n"); ++} ++ ++#endif /* SONAME_LIBDBUS_1 */ -- 1.7.5.4 diff --git a/wine-udisks2.patch b/wine-udisks2.patch deleted file mode 100644 index e83b339..0000000 --- a/wine-udisks2.patch +++ /dev/null @@ -1,719 +0,0 @@ -From: Detlef Riekenberg -Subject: [PATCH 2/2] mountmgr: Support the dbus service udisks for dynamic devices :-) [try 4] -Message-Id: <1311335756-9824-2-git-send-email-wine.dev@web.de> -Date: Fri, 22 Jul 2011 13:55:56 +0200 - -udisks is prefered, but libhal support is still present as fallback. -This allow the libhal requirement on linux to die. - -libhal support in binary packages is only needed, when udisk is -optional for a linux distribution. - -The logic to add/remove the devices/volumes is the same as present in -our libhal support. - -autoheader/autoconf are needed before compilation - -try 2: -remove a trailing space in the code an a trailing " \" in Makefile.in -try 3: -changes for configure.ac where missing in try 2 -try 4 -sync to current git (wineesd was removed) - --- -By by ... Detlef ---- - configure.ac | 20 ++- - dlls/mountmgr.sys/Makefile.in | 5 +- - dlls/mountmgr.sys/hal.c | 15 ++ - dlls/mountmgr.sys/mountmgr.c | 2 + - dlls/mountmgr.sys/mountmgr.h | 3 + - dlls/mountmgr.sys/udisks.c | 554 +++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 596 insertions(+), 3 deletions(-) - create mode 100644 dlls/mountmgr.sys/udisks.c - -diff --git a/configure.ac b/configure.ac -index b213923..d9d2472 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -42,6 +42,7 @@ AC_ARG_WITH(coreaudio, AS_HELP_STRING([--without-coreaudio],[do not use the Core - AC_ARG_WITH(cups, AS_HELP_STRING([--without-cups],[do not use CUPS])) - AC_ARG_WITH(curses, AS_HELP_STRING([--without-curses],[do not use (n)curses]), - [if test "x$withval" = "xno"; then ac_cv_header_ncurses_h=no; ac_cv_header_curses_h=no; fi]) -+AC_ARG_WITH(dbus, AS_HELP_STRING([--without-dbus],[do not use dbus (dynamic device support)])) - AC_ARG_WITH(fontconfig,AS_HELP_STRING([--without-fontconfig],[do not use fontconfig]), - [if test "x$withval" = "xno"; then ac_cv_header_fontconfig_fontconfig_h=no; fi]) - AC_ARG_WITH(freetype, AS_HELP_STRING([--without-freetype],[do not use the FreeType library])) -@@ -1196,6 +1197,23 @@ fi - WINE_WARNING_WITH(xslt,[test "x$ac_cv_lib_soname_xslt" = "x"], - [libxslt ${notice_platform}development files not found, xslt won't be supported.]) - -+dnl **** Check for libdbus **** -+AC_SUBST(DBUSINCL,"") -+if test "x$with_dbus" != "xno" -+then -+ ac_save_CPPFLAGS="$CPPFLAGS" -+ if test "$PKG_CONFIG" != "false" -+ then -+ ac_dbus_libs="`$PKG_CONFIG --libs dbus-1 2>/dev/null`" -+ ac_dbus_cflags="`$PKG_CONFIG --cflags dbus-1 2>/dev/null`" -+ CPPFLAGS="$CPPFLAGS $ac_dbus_cflags" -+ fi -+ AC_CHECK_HEADER(dbus/dbus.h, -+ [WINE_CHECK_SONAME(dbus-1,dbus_bus_get,[DBUSINCL="$ac_dbus_cflags"],,[$ac_dbus_libs])]) -+ -+ CPPFLAGS="$ac_save_CPPFLAGS" -+fi -+ - dnl **** Check for libhal **** - AC_SUBST(HALINCL,"") - if test "x$with_hal" != "xno" -@@ -1216,7 +1234,7 @@ then - fi - CPPFLAGS="$ac_save_CPPFLAGS" - fi --WINE_NOTICE_WITH(hal,[test "x$ac_cv_lib_soname_hal" = "x" -a "x$ac_cv_header_DiskArbitration_DiskArbitration_h" != "xyes"], -+WINE_NOTICE_WITH(hal,[test "x$ac_cv_lib_soname_hal" = "x" -a "x$ac_cv_lib_soname_dbus_1" = "x" -a "x$ac_cv_header_DiskArbitration_DiskArbitration_h" != "xyes"], - [libhal/libdbus ${notice_platform}development files not found, no dynamic device support.]) - - dnl **** Check for libgnutls **** -diff --git a/dlls/mountmgr.sys/Makefile.in b/dlls/mountmgr.sys/Makefile.in -index 91203e1..f3355e0 100644 ---- a/dlls/mountmgr.sys/Makefile.in -+++ b/dlls/mountmgr.sys/Makefile.in -@@ -2,13 +2,14 @@ MODULE = mountmgr.sys - IMPORTS = uuid advapi32 ntoskrnl.exe - DELAYIMPORTS = user32 - EXTRADLLFLAGS = -Wb,--subsystem,native --EXTRADEFS = @HALINCL@ -+EXTRADEFS = @HALINCL@ @DBUSINCL@ - EXTRALIBS = @DISKARBITRATIONLIB@ - - C_SRCS = \ - device.c \ - diskarb.c \ - hal.c \ -- mountmgr.c -+ mountmgr.c \ -+ udisks.c - - @MAKE_DLL_RULES@ -diff --git a/dlls/mountmgr.sys/hal.c b/dlls/mountmgr.sys/hal.c -index ff10a3e..8e31624 100644 ---- a/dlls/mountmgr.sys/hal.c -+++ b/dlls/mountmgr.sys/hal.c -@@ -245,6 +245,21 @@ void initialize_hal(void) - { - HANDLE handle; - -+ /* wait for udisks, when needed */ -+ if (dbus_present) -+ { -+ DWORD res; -+ -+ TRACE("waiting for udisks\n"); -+ res = WaitForSingleObject(dbus_present, 100); -+ -+ if (!res && *udisks_version) -+ { -+ TRACE("Skipping, found udisks\n"); -+ return; -+ } -+ } -+ - if (!load_functions()) return; - if (!(handle = CreateThread( NULL, 0, hal_thread, NULL, 0, NULL ))) return; - CloseHandle( handle ); -diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c -index 4e9900f..df0dbd3 100644 ---- a/dlls/mountmgr.sys/mountmgr.c -+++ b/dlls/mountmgr.sys/mountmgr.c -@@ -443,6 +443,8 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) - RtlInitUnicodeString( &nameW, harddiskW ); - status = IoCreateDriver( &nameW, harddisk_driver_entry ); - -+ /* start udisks before hal */ -+ initialize_udisks(); - initialize_hal(); - initialize_diskarbitration(); - -diff --git a/dlls/mountmgr.sys/mountmgr.h b/dlls/mountmgr.sys/mountmgr.h -index a8e4389..3c3c564 100644 ---- a/dlls/mountmgr.sys/mountmgr.h -+++ b/dlls/mountmgr.sys/mountmgr.h -@@ -35,8 +35,11 @@ - #define WINE_MOUNTMGR_EXTENSIONS - #include "ddk/mountmgr.h" - -+extern void initialize_udisks(void) DECLSPEC_HIDDEN; - extern void initialize_hal(void) DECLSPEC_HIDDEN; - extern void initialize_diskarbitration(void) DECLSPEC_HIDDEN; -+extern HANDLE dbus_present; -+extern char udisks_version[]; - - /* device functions */ - -diff --git a/dlls/mountmgr.sys/udisks.c b/dlls/mountmgr.sys/udisks.c -new file mode 100644 -index 0000000..898f41d ---- /dev/null -+++ b/dlls/mountmgr.sys/udisks.c -@@ -0,0 +1,554 @@ -+/* -+ * udisks devices support -+ * -+ * Copyright 2006 Alexandre Julliard -+ * Copyright 2011 Detlef Riekenberg -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "config.h" -+#include "wine/port.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "mountmgr.h" -+#include "winnls.h" -+#include "excpt.h" -+ -+#include "wine/library.h" -+#include "wine/exception.h" -+#include "wine/debug.h" -+ -+WINE_DEFAULT_DEBUG_CHANNEL(mountmgr); -+ -+HANDLE dbus_present = NULL; -+char udisks_version[32]; -+ -+#ifdef SONAME_LIBDBUS_1 -+ -+#include -+ -+/* ########## */ -+ -+typedef struct properties_s { -+ CHAR *device_file; -+ CHAR *id_usage; -+ CHAR *id_type; -+ CHAR *id_uuid; -+ BOOL device_is_mounted; -+ BOOL device_is_optical_disc; -+ BOOL device_is_removable; -+ CHAR *device_mount_paths; -+ CHAR *drive_media; -+ CHAR *drive_media_compatibility; -+ int depth; -+ const char * last_name; -+}properties_t; -+ -+static const char *my_match_rule = "interface=org.freedesktop.UDisks"; -+static const char *dest_udisks_device = "org.freedesktop.UDisks.Device"; -+static const char *dest_udisks = "org.freedesktop.UDisks"; -+static const char *path_udisks = "/org/freedesktop/UDisks"; -+static const char *iface_dbus_prop = "org.freedesktop.DBus.Properties"; -+static const char *daemonversion = "DaemonVersion"; -+ -+/* ########## */ -+ -+#define DBUS_FUNCS \ -+ DO_FUNC(dbus_bus_add_match); \ -+ DO_FUNC(dbus_bus_get); \ -+ DO_FUNC(dbus_bus_remove_match); \ -+ DO_FUNC(dbus_connection_pop_message); \ -+ DO_FUNC(dbus_connection_read_write_dispatch); \ -+ DO_FUNC(dbus_connection_send_with_reply_and_block); \ -+ DO_FUNC(dbus_connection_unref); \ -+ DO_FUNC(dbus_error_free); \ -+ DO_FUNC(dbus_error_init); \ -+ DO_FUNC(dbus_error_is_set); \ -+ DO_FUNC(dbus_message_append_args); \ -+ DO_FUNC(dbus_message_get_member); \ -+ DO_FUNC(dbus_message_iter_get_arg_type); \ -+ DO_FUNC(dbus_message_iter_get_basic); \ -+ DO_FUNC(dbus_message_iter_init); \ -+ DO_FUNC(dbus_message_iter_next); \ -+ DO_FUNC(dbus_message_iter_recurse); \ -+ DO_FUNC(dbus_message_new_method_call); \ -+ DO_FUNC(dbus_message_type_to_string); \ -+ DO_FUNC(dbus_message_unref) -+ -+#define DO_FUNC(f) static typeof(f) * p_##f -+DBUS_FUNCS; -+#undef DO_FUNC -+ -+ -+static BOOL load_dbus_functions(void) -+{ -+ void *dbus_handle; -+ char error[128]; -+ -+ if (!(dbus_handle = wine_dlopen(SONAME_LIBDBUS_1, RTLD_NOW|RTLD_GLOBAL, error, sizeof(error)))) -+ goto failed; -+ -+#define DO_FUNC(f) if (!(p_##f = wine_dlsym(RTLD_DEFAULT, #f, error, sizeof(error)))) goto failed -+ DBUS_FUNCS; -+#undef DO_FUNC -+ -+ return TRUE; -+ -+failed: -+ WARN("failed to load udisks support: %s\n", error); -+ return FALSE; -+} -+ -+/* ########## */ -+ -+static LONG WINAPI assert_fault(EXCEPTION_POINTERS *eptr) -+{ -+ if (eptr->ExceptionRecord->ExceptionCode == EXCEPTION_WINE_ASSERTION) -+ return EXCEPTION_EXECUTE_HANDLER; -+ return EXCEPTION_CONTINUE_SEARCH; -+} -+ -+/* ######################################### -+ * get_properties_from_iter [internal] -+ * -+ * NOTES -+ * format of args in a reply from GetAll: -+ * an ARRAY of DICT_ENTRY -+ * each DICT_ENTRY has a STRING (property name) and a VARIANT (property value) -+ * each VARIANT has a BOOLEAN or a STRING or an ARRAY of STRING or an here unused value -+ */ -+static BOOL get_properties_from_iter(properties_t * p, DBusMessageIter * iter) -+{ -+ DBusMessageIter sub; -+ int arg_type = p_dbus_message_iter_get_arg_type(iter); -+ -+ p->depth++; -+ while (arg_type != DBUS_TYPE_INVALID) -+ { -+ if ((arg_type == DBUS_TYPE_ARRAY) || -+ (arg_type == DBUS_TYPE_DICT_ENTRY) || -+ (arg_type == DBUS_TYPE_VARIANT)) -+ { -+ p_dbus_message_iter_recurse(iter, &sub); -+ if (!get_properties_from_iter(p, &sub)) -+ { -+ p->depth--; -+ return FALSE; -+ } -+ } -+ else if (arg_type == DBUS_TYPE_STRING) -+ { -+ char * data; -+ p_dbus_message_iter_get_basic(iter, &data); -+ if (p->depth == 3) p->last_name = data; -+ else if (p->last_name) -+ { -+ if (!strcmp(p->last_name, "DeviceFile")) -+ p->device_file = data; -+ else if (!strcmp(p->last_name, "DeviceMountPaths")) -+ p->device_mount_paths = data; /* use only the first entry */ -+ else if (!strcmp(p->last_name, "DriveMedia")) -+ p->drive_media = data; -+ else if (!strcmp(p->last_name, "DriveMediaCompatibility")) -+ p->drive_media_compatibility = data; /* use only the first entry */ -+ else if (!strcmp(p->last_name, "IdType")) -+ p->id_type = data; -+ else if (!strcmp(p->last_name, "IdUsage")) -+ p->id_usage = data; -+ else if (!strcmp(p->last_name, "IdUuid")) -+ p->id_uuid = data; -+ -+ p->last_name = NULL; -+ } -+ } -+ else if (arg_type == DBUS_TYPE_BOOLEAN) -+ { -+ dbus_bool_t data; -+ if (p->last_name) -+ { -+ p_dbus_message_iter_get_basic(iter, &data); -+ if (!strcmp(p->last_name, "DeviceIsMounted")) -+ p->device_is_mounted = data; -+ else if (!strcmp(p->last_name, "DeviceIsOpticalDisc")) -+ p->device_is_optical_disc = data; -+ else if (!strcmp(p->last_name, "DeviceIsRemovable")) -+ p->device_is_removable = data; -+ -+ p->last_name = NULL; -+ } -+ } -+ -+ p_dbus_message_iter_next(iter); -+ arg_type = p_dbus_message_iter_get_arg_type(iter); -+ } -+ p->depth--; -+ return TRUE; -+} -+ -+/* ########### */ -+ -+static DBusMessage * get_properties_from_path(properties_t * p, DBusConnection *ctx, const char * path) -+{ -+ DBusMessage *request; -+ DBusMessage *reply = NULL; -+ DBusMessageIter iter; -+ DBusError error; -+ -+ TRACE("(%p, %p, %s)\n", p, ctx, path); -+ -+ memset(p, 0, sizeof(properties_t)); -+ request = p_dbus_message_new_method_call(dest_udisks, path, iface_dbus_prop, "GetAll"); -+ if (request) -+ { -+ if (p_dbus_message_append_args(request, DBUS_TYPE_STRING, &dest_udisks_device, DBUS_TYPE_INVALID)) -+ { -+ p_dbus_error_init(&error); -+ if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error))) -+ { -+ p_dbus_message_iter_init(reply, &iter); -+ get_properties_from_iter(p, &iter); -+ } -+ else -+ WARN("no reply for %s\n", path); -+ -+ p_dbus_error_free(&error); -+ } -+ else -+ WARN("dbus_message_append_args failed for 'GetAll'\n"); -+ -+ p_dbus_message_unref(request); -+ } -+ return reply; -+} -+ -+/* ########### */ -+ -+static int get_drive_type(properties_t * p) -+{ -+ /* examples: optical_cd, optical_cd_rw, optical_dvd_plus_r_dl */ -+ if (p->device_is_optical_disc && p->drive_media && !memcmp(p->drive_media, "optical_", 8)) -+ { -+ if (!memcmp(p->drive_media + 8, "cd", 2)) -+ return DEVICE_CDROM; -+ else -+ return DEVICE_DVD; -+ } -+ else if (p->drive_media_compatibility && !strcmp(p->drive_media_compatibility, "floppy")) -+ return DEVICE_FLOPPY; -+ else if (!p->device_is_removable && p->id_usage && !strcmp(p->id_usage, "filesystem")) -+ return DEVICE_HARDDISK_VOL; -+ -+ return DEVICE_UNKNOWN; -+} -+ -+/* ########### */ -+ -+static void udisks_add_device(DBusConnection *ctx, const char *path) -+{ -+ DBusMessage *reply; -+ properties_t p; -+ GUID guid; -+ GUID *guid_ptr = NULL; -+ -+ TRACE("%s\n", debugstr_a(path)); -+ -+ reply = get_properties_from_path(&p, ctx, path); -+ if (reply) -+ { -+ int drive_type = get_drive_type(&p); -+ -+ TRACE("DeviceFile: %s\n", p.device_file); -+ TRACE("IdUsage: %s\n", p.id_usage); -+ TRACE("IdType: %s\n", p.id_type); -+ TRACE("IdUuid: %s\n", p.id_uuid); -+ TRACE("DeviceIsMounted: %d (%s)\n", p.device_is_mounted, p.device_is_mounted ? "true" : "false"); -+ TRACE("DeviceIsOpticalDisc: %d (%s)\n", p.device_is_optical_disc, p.device_is_optical_disc ? "true" : "false"); -+ TRACE("DeviceIsRemovable: %d (%s)\n", p.device_is_removable, p.device_is_removable ? "true" : "false"); -+ TRACE("DeviceMountPaths: %s\n", p.device_mount_paths); -+ TRACE("DriveMedia: %s\n", p.drive_media); -+ TRACE("DriveMediaCompatibility: %s\n", p.drive_media_compatibility); -+ TRACE("using drive_type: %d\n", drive_type); -+ -+ if (p.device_is_mounted && p.device_mount_paths) -+ { -+ if (p.id_uuid) -+ guid_ptr = parse_uuid(&guid, p.id_uuid); -+ -+ if (p.device_is_removable) -+ add_dos_device(-1, path, p.device_file, p.device_mount_paths, drive_type, guid_ptr); -+ else if (guid_ptr) -+ add_volume(path, p.device_file, p.device_mount_paths, DEVICE_HARDDISK_VOL, guid_ptr); -+ -+ } -+ p_dbus_message_unref(reply); -+ } -+} -+ -+static void udisks_remove_device(DBusConnection *ctx, const char *path) -+{ -+ TRACE("%s\n", debugstr_a(path)); -+ -+ if (remove_dos_device(-1, path)) -+ remove_volume(path); -+} -+ -+static void udisks_change_device(DBusConnection *ctx, const char *path) -+{ -+ DBusMessage *reply; -+ properties_t p; -+ -+ TRACE("%s\n", debugstr_a(path)); -+ -+ reply = get_properties_from_path(&p, ctx, path); -+ if (reply) -+ { -+ int drive_type = get_drive_type(&p); -+ -+ if (p.device_is_mounted && p.device_mount_paths) -+ udisks_add_device(ctx, path); -+ else -+ { -+ TRACE("DeviceFile: %s\n", p.device_file); -+ TRACE("IdUsage: %s\n", p.id_usage); -+ TRACE("IdType: %s\n", p.id_type); -+ TRACE("IdUuid: %s\n", p.id_uuid); -+ TRACE("DeviceIsMounted: %d (%s)\n", p.device_is_mounted, p.device_is_mounted ? "true" : "false"); -+ TRACE("DeviceIsOpticalDisc: %d (%s)\n", p.device_is_optical_disc, p.device_is_optical_disc ? "true" : "false"); -+ TRACE("DeviceIsRemovable: %d (%s)\n", p.device_is_removable, p.device_is_removable ? "true" : "false"); -+ TRACE("DeviceMountPaths: %s\n", p.device_mount_paths); -+ TRACE("DriveMedia: %s\n", p.drive_media); -+ TRACE("DriveMediaCompatibility: %s\n", p.drive_media_compatibility); -+ TRACE("using drive_type: %d\n", drive_type); -+ -+ udisks_remove_device(ctx, path); -+ } -+ p_dbus_message_unref(reply); -+ } -+} -+ -+/* ########### */ -+ -+static void udisks_get_all_devices(DBusConnection *ctx) -+{ -+ DBusMessage *request; -+ DBusMessage *reply; -+ DBusMessageIter iter; -+ DBusMessageIter sub; -+ DBusError error; -+ int arg_type; -+ -+ request = p_dbus_message_new_method_call(dest_udisks, path_udisks, dest_udisks, "EnumerateDevices"); -+ if (request) -+ { -+ p_dbus_error_init(&error); -+ if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error))) -+ { -+ p_dbus_message_iter_init(reply, &iter); -+ arg_type = p_dbus_message_iter_get_arg_type(&iter); -+ if (arg_type == DBUS_TYPE_ARRAY) -+ { -+ p_dbus_message_iter_recurse(&iter, &sub); -+ while ((arg_type = p_dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_OBJECT_PATH) -+ { -+ char * data; -+ p_dbus_message_iter_get_basic(&sub, &data); -+ udisks_add_device(ctx, data); -+ p_dbus_message_iter_next(&sub); -+ } -+ } -+ else -+ WARN("expected ARRAY, got %c\n", arg_type); -+ -+ p_dbus_message_unref(reply); -+ } -+ p_dbus_error_free(&error); -+ p_dbus_message_unref(request); -+ } -+} -+ -+/* ########## */ -+ -+static void udisks_get_version(DBusConnection *ctx) -+{ -+ DBusMessage *request; -+ DBusMessage *reply; -+ DBusMessageIter iter; -+ DBusMessageIter sub; -+ DBusError error; -+ int arg_type; -+ -+ request = p_dbus_message_new_method_call(dest_udisks, path_udisks, iface_dbus_prop, "Get"); -+ if (request) -+ { -+ if (p_dbus_message_append_args(request, DBUS_TYPE_STRING, &dest_udisks, -+ DBUS_TYPE_STRING, &daemonversion, -+ DBUS_TYPE_INVALID)) -+ { -+ p_dbus_error_init(&error); -+ if ((reply = p_dbus_connection_send_with_reply_and_block(ctx, request, -1, &error))) -+ { -+ p_dbus_message_iter_init(reply, &iter); -+ arg_type = p_dbus_message_iter_get_arg_type(&iter); -+ if (arg_type == DBUS_TYPE_VARIANT) -+ { -+ p_dbus_message_iter_recurse(&iter, &sub); -+ arg_type = p_dbus_message_iter_get_arg_type(&sub); -+ if (arg_type == DBUS_TYPE_STRING) -+ { -+ char * data; -+ p_dbus_message_iter_get_basic(&sub, &data); -+ lstrcpynA(udisks_version, data, sizeof(udisks_version) - 1); -+ TRACE("found udisks daemon %s\n", udisks_version); -+ } -+ else -+ WARN("expected STRING, got %c\n", arg_type); -+ -+ } -+ else -+ WARN("expected VARIANT, got %c\n", arg_type); -+ -+ p_dbus_message_unref(reply); -+ } -+ p_dbus_error_free(&error); -+ } -+ else -+ WARN("dbus_message_append_args failed\n"); -+ -+ p_dbus_message_unref(request); -+ } -+ return; -+ -+} -+ -+/* ##### */ -+ -+static DWORD WINAPI udisks_thread( void *arg ) -+{ -+ DBusConnection *ctx; -+ DBusMessage *msg; -+ DBusMessageIter iter; -+ DBusError error; -+ const char *member; -+ int arg_type; -+ char *data; -+ -+ p_dbus_error_init(&error); -+ ctx = p_dbus_bus_get(DBUS_BUS_SYSTEM, &error); -+ -+ if (!ctx) -+ { -+ SetEvent(dbus_present); /* wakeup hal support */ -+ WARN("failed to get system dbus connection: %s\n", error.message); -+ p_dbus_error_free(&error); -+ return 1; -+ } -+ -+ p_dbus_bus_add_match(ctx, my_match_rule, &error); -+ if (p_dbus_error_is_set(&error)) -+ { -+ SetEvent(dbus_present); /* wakeup hal support */ -+ WARN("add dbus filter failed: %s\n", error.message); -+ p_dbus_error_free(&error); -+ p_dbus_connection_unref(ctx); -+ return 1; -+ } -+ -+ udisks_get_version(ctx); -+ SetEvent(dbus_present); /* wakeup hal support */ -+ -+ if (!*udisks_version) -+ { -+ TRACE("udisks service not available\n"); -+ p_dbus_bus_remove_match(ctx, my_match_rule, NULL); -+ p_dbus_error_free(&error); -+ p_dbus_connection_unref(ctx); -+ return 1; -+ } -+ -+ __TRY -+ { -+ /* retrieve all existing devices */ -+ udisks_get_all_devices(ctx); -+ -+ while (p_dbus_connection_read_write_dispatch(ctx, -1 )) -+ { -+ while ((msg = p_dbus_connection_pop_message(ctx))) -+ { -+ member = p_dbus_message_get_member(msg); -+ p_dbus_message_iter_init(msg, &iter); -+ arg_type = p_dbus_message_iter_get_arg_type(&iter); -+ -+ if (arg_type == DBUS_TYPE_OBJECT_PATH) -+ p_dbus_message_iter_get_basic(&iter, &data); -+ -+ if (!lstrcmpA(member, "DeviceChanged")) -+ udisks_change_device(ctx, data); -+ else if (!lstrcmpA(member, "DeviceAdded")) -+ udisks_add_device(ctx, data); -+ else if (!lstrcmpA(member, "DeviceRemoved")) -+ udisks_remove_device(ctx, data); -+ else if (lstrcmpA(member, "DeviceJobChanged")) -+ WARN("got signal for %s\n", member); -+ -+ p_dbus_message_unref(msg); -+ } -+ } -+ } -+ __EXCEPT(assert_fault) -+ { -+ WARN("dbus assertion failure, disabling UDisks support\n"); -+ return 1; -+ } -+ __ENDTRY; -+ -+ p_dbus_bus_remove_match(ctx, my_match_rule, NULL); -+ p_dbus_error_free(&error); -+ p_dbus_connection_unref(ctx); -+ return 0; -+} -+ -+void initialize_udisks(void) -+{ -+ HANDLE handle = NULL; -+ -+ dbus_present = NULL; -+ *udisks_version = 0; -+ if (!load_dbus_functions()) return; -+ -+ /* delay hal support, start udisks thread */ -+ if (!(dbus_present = CreateEventW(NULL, TRUE, FALSE, NULL)) || -+ !(handle = CreateThread(NULL, 0, udisks_thread, NULL, 0, NULL))) -+ { -+ /* something failed: wakeup hal now */ -+ if (dbus_present) SetEvent(dbus_present); -+ return; -+ } -+ CloseHandle(handle); -+} -+ -+#else /* SONAME_LIBDBUS_1 */ -+ -+void initialize_udisks(void) -+{ -+ TRACE("Skipping, DBUS support not compiled in\n"); -+} -+ -+#endif /* SONAME_LIBDBUS_1 */ --- -1.7.5.4 - diff --git a/wine.spec b/wine.spec index 5432bdb..33e24a8 100644 --- a/wine.spec +++ b/wine.spec @@ -1,7 +1,7 @@ %global no64bit 0 Name: wine -Version: 1.3.25 -Release: 1%{?dist} +Version: 1.3.26 +Release: 2%{?dist} Summary: A Windows 16/32/64 bit emulator Group: Applications/Emulators @@ -37,20 +37,11 @@ Source300: wine-mime-msi.desktop Patch200: wine-imagemagick-6.5.patch -# pull pulse parts from Maarten Lankhorst multimedia repository -# http://repo.or.cz/w/wine/multimedia.git -Patch400: wine-pulseaudio-configure.patch -Source401: dlls_winepulse.drv_Makefile.in -Source402: dlls_winepulse.drv_mmdevdrv.c -Source403: dlls_winepulse.drv_winepulse.drv - # add udisks support # https://bugzilla.redhat.com/show_bug.cgi?id=712755 # http://bugs.winehq.org/show_bug.cgi?id=21713 -# http://source.winehq.org/patches/data/76788 -# http://source.winehq.org/patches/data/76787 +# http://source.winehq.org/patches/data/77534 Patch410: wine-udisks1.patch -Patch411: wine-udisks2.patch # smooth tahoma (#693180) # disable embedded bitmaps @@ -412,11 +403,16 @@ with the Wine Windows(TM) emulation libraries. Summary: Pulseaudio support for wine Group: System Environment/Libraries Requires: wine-core = %{version}-%{release} +%ifarch %{ix86} +Requires: alsa-plugins-pulseaudio(x86-32) +%endif +%ifarch x86_64 +Requires: alsa-plugins-pulseaudio(x86-64) +%endif %description pulseaudio -This package adds a native pulseaudio driver for wine. This is not an official -wine audio driver. Please do not report bugs regarding this driver at -winehq.org. +This package pulse in the alsa pulseaudio backend to allow for pulse playback +over alsa. %package alsa Summary: Alsa support for wine @@ -439,17 +435,9 @@ This package adds an openal driver for wine. %prep %setup -q -%patch400 -p1 -b .winepulse-configure -mkdir -p dlls/winepulse.drv -cp -p %{SOURCE401} dlls/winepulse.drv/Makefile.in -cp -p %{SOURCE402} dlls/winepulse.drv/mmdevdrv.c -cp -p %{SOURCE403} dlls/winepulse.drv/winepulse.drv.spec - %patch200 -b .imagemagick %patch410 -p1 -b .mountmgr -%patch411 -p1 -b .mountmgr - autoreconf @@ -620,8 +608,8 @@ desktop-file-install \ --dir=%{buildroot}%{_datadir}/applications \ %{SOURCE300} -# deploy pulseaudio readme cp %{SOURCE3} README-FEDORA + cp %{SOURCE502} README-tahoma mkdir -p %{buildroot}%{_sysconfdir}/ld.so.conf.d/ @@ -738,9 +726,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %post capi -p /sbin/ldconfig %postun capi -p /sbin/ldconfig -%post pulseaudio -p /sbin/ldconfig -%postun pulseaudio -p /sbin/ldconfig - %post alsa -p /sbin/ldconfig %postun alsa -p /sbin/ldconfig @@ -936,6 +921,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{_libdir}/wine/iccvid.dll.so %{_libdir}/wine/icinfo.exe.so %{_libdir}/wine/icmp.dll.so +%{_libdir}/wine/ieframe.dll.so %{_libdir}/wine/imaadp32.acm.so %{_libdir}/wine/imagehlp.dll.so %{_libdir}/wine/imm32.dll.so @@ -1134,6 +1120,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{_libdir}/wine/wlanapi.dll.so %{_libdir}/wine/wnaspi32.dll.so %{_libdir}/wine/ws2_32.dll.so +%{_libdir}/wine/wshom.ocx.so %{_libdir}/wine/wsock32.dll.so %{_libdir}/wine/wtsapi32.dll.so %{_libdir}/wine/wuapi.dll.so @@ -1383,7 +1370,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %files pulseaudio %defattr(-,root,root,-) -%{_libdir}/wine/winepulse.drv.so +# empty meta package for deps %files alsa %defattr(-,root,root,-) @@ -1396,6 +1383,16 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %endif %changelog +* Mon Aug 22 2011 Andreas Bierfert +- 1.3.26-2 +- drop pulse patches +- make pulseaudio package meta and require alsa pa plugin +- update udisks patch + +* Sun Aug 07 2011 Andreas Bierfert +- 1.3.26-1 +- version upgrade + * Fri Jul 22 2011 Andreas Bierfert - 1.3.25-1 - version upgrade