winmm: Rearrange device mapping when a new default device is chosen.
This commit is contained in:
parent
99065bb65f
commit
4ab4bc5d09
|
@ -278,6 +278,15 @@ static void WINMM_InitDevice(WINMM_Device *device,
|
||||||
device->parent = parent;
|
device->parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline WINMM_MMDevice *read_map(WINMM_MMDevice **map, UINT index)
|
||||||
|
{
|
||||||
|
WINMM_MMDevice *ret;
|
||||||
|
EnterCriticalSection(&g_devthread_lock);
|
||||||
|
ret = map[index];
|
||||||
|
LeaveCriticalSection(&g_devthread_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* finds the first unused Device, marks it as "open", and returns
|
/* finds the first unused Device, marks it as "open", and returns
|
||||||
* a pointer to the device
|
* a pointer to the device
|
||||||
*
|
*
|
||||||
|
@ -290,9 +299,9 @@ static WINMM_Device *WINMM_FindUnusedDevice(BOOL is_out, UINT mmdevice_index)
|
||||||
UINT i;
|
UINT i;
|
||||||
|
|
||||||
if(is_out)
|
if(is_out)
|
||||||
mmdevice = g_out_map[mmdevice_index];
|
mmdevice = read_map(g_out_map, mmdevice_index);
|
||||||
else
|
else
|
||||||
mmdevice = g_in_map[mmdevice_index];
|
mmdevice = read_map(g_in_map, mmdevice_index);
|
||||||
|
|
||||||
EnterCriticalSection(&mmdevice->lock);
|
EnterCriticalSection(&mmdevice->lock);
|
||||||
for(i = 0; i < MAX_DEVICES; ++i){
|
for(i = 0; i < MAX_DEVICES; ++i){
|
||||||
|
@ -629,6 +638,112 @@ static HRESULT WINMM_EnumDevices(WINMM_MMDevice **devices,
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI notif_QueryInterface(IMMNotificationClient *iface,
|
||||||
|
const GUID *riid, void **obj)
|
||||||
|
{
|
||||||
|
ERR("Unexpected QueryInterface call: %s\n", wine_dbgstr_guid(riid));
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI notif_AddRef(IMMNotificationClient *iface)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI notif_Release(IMMNotificationClient *iface)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI notif_OnDeviceStateChanged(IMMNotificationClient *iface,
|
||||||
|
const WCHAR *device_id, DWORD new_state)
|
||||||
|
{
|
||||||
|
TRACE("Ignoring OnDeviceStateChanged callback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI notif_OnDeviceAdded(IMMNotificationClient *iface,
|
||||||
|
const WCHAR *device_id)
|
||||||
|
{
|
||||||
|
TRACE("Ignoring OnDeviceAdded callback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI notif_OnDeviceRemoved(IMMNotificationClient *iface,
|
||||||
|
const WCHAR *device_id)
|
||||||
|
{
|
||||||
|
TRACE("Ignoring OnDeviceRemoved callback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI notif_OnDefaultDeviceChanged(IMMNotificationClient *iface,
|
||||||
|
EDataFlow flow, ERole role, const WCHAR *device_id)
|
||||||
|
{
|
||||||
|
WINMM_MMDevice ***map;
|
||||||
|
WINMM_MMDevice *prev;
|
||||||
|
UINT count, i;
|
||||||
|
|
||||||
|
TRACE("%u %u %s\n", flow, role, wine_dbgstr_w(device_id));
|
||||||
|
|
||||||
|
if(role != eConsole)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
EnterCriticalSection(&g_devthread_lock);
|
||||||
|
|
||||||
|
if(flow == eRender){
|
||||||
|
map = &g_out_map;
|
||||||
|
count = g_outmmdevices_count;
|
||||||
|
}else{
|
||||||
|
map = &g_in_map;
|
||||||
|
count = g_inmmdevices_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = (*map)[0];
|
||||||
|
for(i = 0; i < count; ++i){
|
||||||
|
WINMM_MMDevice *tmp;
|
||||||
|
|
||||||
|
if(!lstrcmpW((*map)[i]->dev_id, device_id)){
|
||||||
|
(*map)[0] = (*map)[i];
|
||||||
|
(*map)[i] = prev;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&g_devthread_lock);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = (*map)[i];
|
||||||
|
(*map)[i] = prev;
|
||||||
|
prev = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
WARN("Couldn't find new default device! Rearranged map for no reason.\n");
|
||||||
|
(*map)[0] = prev;
|
||||||
|
|
||||||
|
LeaveCriticalSection(&g_devthread_lock);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI notif_OnPropertyValueChanged(IMMNotificationClient *iface,
|
||||||
|
const WCHAR *device_id, const PROPERTYKEY key)
|
||||||
|
{
|
||||||
|
TRACE("Ignoring OnPropertyValueChanged callback\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IMMNotificationClientVtbl g_notif_vtbl = {
|
||||||
|
notif_QueryInterface,
|
||||||
|
notif_AddRef,
|
||||||
|
notif_Release,
|
||||||
|
notif_OnDeviceStateChanged,
|
||||||
|
notif_OnDeviceAdded,
|
||||||
|
notif_OnDeviceRemoved,
|
||||||
|
notif_OnDefaultDeviceChanged,
|
||||||
|
notif_OnPropertyValueChanged
|
||||||
|
};
|
||||||
|
|
||||||
|
static IMMNotificationClient g_notif = { &g_notif_vtbl };
|
||||||
|
|
||||||
static HRESULT WINMM_InitMMDevices(void)
|
static HRESULT WINMM_InitMMDevices(void)
|
||||||
{
|
{
|
||||||
HRESULT hr, init_hr;
|
HRESULT hr, init_hr;
|
||||||
|
@ -644,6 +759,10 @@ static HRESULT WINMM_InitMMDevices(void)
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
hr = IMMDeviceEnumerator_RegisterEndpointNotificationCallback(devenum, &g_notif);
|
||||||
|
if(FAILED(hr))
|
||||||
|
WARN("RegisterEndpointNotificationCallback failed: %08x\n", hr);
|
||||||
|
|
||||||
hr = WINMM_EnumDevices(&g_out_mmdevices, &g_out_map, &g_outmmdevices_count,
|
hr = WINMM_EnumDevices(&g_out_mmdevices, &g_out_map, &g_outmmdevices_count,
|
||||||
eRender, devenum);
|
eRender, devenum);
|
||||||
if(FAILED(hr)){
|
if(FAILED(hr)){
|
||||||
|
@ -1087,7 +1206,7 @@ static LRESULT WOD_Open(WINMM_OpenInfo *info)
|
||||||
if(info->req_device >= g_outmmdevices_count)
|
if(info->req_device >= g_outmmdevices_count)
|
||||||
return MMSYSERR_BADDEVICEID;
|
return MMSYSERR_BADDEVICEID;
|
||||||
|
|
||||||
mmdevice = g_out_map[info->req_device];
|
mmdevice = read_map(g_out_map, info->req_device);
|
||||||
|
|
||||||
if(!mmdevice->out_caps.szPname[0])
|
if(!mmdevice->out_caps.szPname[0])
|
||||||
return MMSYSERR_NOTENABLED;
|
return MMSYSERR_NOTENABLED;
|
||||||
|
@ -1160,7 +1279,7 @@ static LRESULT WID_Open(WINMM_OpenInfo *info)
|
||||||
if(info->req_device >= g_inmmdevices_count)
|
if(info->req_device >= g_inmmdevices_count)
|
||||||
return MMSYSERR_BADDEVICEID;
|
return MMSYSERR_BADDEVICEID;
|
||||||
|
|
||||||
mmdevice = g_in_map[info->req_device];
|
mmdevice = read_map(g_in_map, info->req_device);
|
||||||
|
|
||||||
if(!mmdevice->in_caps.szPname[0])
|
if(!mmdevice->in_caps.szPname[0])
|
||||||
return MMSYSERR_NOTENABLED;
|
return MMSYSERR_NOTENABLED;
|
||||||
|
@ -1900,10 +2019,10 @@ static WINMM_MMDevice *WINMM_GetMixerMMDevice(HMIXEROBJ hmix, DWORD flags,
|
||||||
case MIXER_OBJECTF_MIXER: /* == 0 */
|
case MIXER_OBJECTF_MIXER: /* == 0 */
|
||||||
*out = HandleToULong(hmix);
|
*out = HandleToULong(hmix);
|
||||||
if(*out < g_outmmdevices_count)
|
if(*out < g_outmmdevices_count)
|
||||||
return g_out_map[*out];
|
return read_map(g_out_map, *out);
|
||||||
if(*out - g_outmmdevices_count < g_inmmdevices_count){
|
if(*out - g_outmmdevices_count < g_inmmdevices_count){
|
||||||
*out -= g_outmmdevices_count;
|
*out -= g_outmmdevices_count;
|
||||||
return g_in_map[*out];
|
return read_map(g_in_map, *out);
|
||||||
}
|
}
|
||||||
/* fall through -- if it's not a valid mixer device, then
|
/* fall through -- if it's not a valid mixer device, then
|
||||||
* it could be a valid mixer handle. windows seems to do
|
* it could be a valid mixer handle. windows seems to do
|
||||||
|
@ -1916,17 +2035,17 @@ static WINMM_MMDevice *WINMM_GetMixerMMDevice(HMIXEROBJ hmix, DWORD flags,
|
||||||
(!is_out && *out >= g_inmmdevices_count))
|
(!is_out && *out >= g_inmmdevices_count))
|
||||||
return NULL;
|
return NULL;
|
||||||
if(is_out)
|
if(is_out)
|
||||||
return g_out_map[*out];
|
return read_map(g_out_map, *out);
|
||||||
return g_in_map[*out];
|
return read_map(g_in_map, *out);
|
||||||
case MIXER_OBJECTF_WAVEOUT:
|
case MIXER_OBJECTF_WAVEOUT:
|
||||||
*out = HandleToULong(hmix);
|
*out = HandleToULong(hmix);
|
||||||
if(*out < g_outmmdevices_count)
|
if(*out < g_outmmdevices_count)
|
||||||
return g_out_map[*out];
|
return read_map(g_out_map, *out);
|
||||||
return NULL;
|
return NULL;
|
||||||
case MIXER_OBJECTF_WAVEIN:
|
case MIXER_OBJECTF_WAVEIN:
|
||||||
*out = HandleToULong(hmix);
|
*out = HandleToULong(hmix);
|
||||||
if(*out < g_inmmdevices_count)
|
if(*out < g_inmmdevices_count)
|
||||||
return g_in_map[*out];
|
return read_map(g_in_map, *out);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2440,7 +2559,7 @@ UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps,
|
||||||
if(uDeviceID >= g_outmmdevices_count)
|
if(uDeviceID >= g_outmmdevices_count)
|
||||||
return MMSYSERR_BADDEVICEID;
|
return MMSYSERR_BADDEVICEID;
|
||||||
|
|
||||||
caps = &g_out_map[uDeviceID]->out_caps;
|
caps = &read_map(g_out_map, uDeviceID)->out_caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(lpCaps, caps, min(uSize, sizeof(*lpCaps)));
|
memcpy(lpCaps, caps, min(uSize, sizeof(*lpCaps)));
|
||||||
|
@ -2939,7 +3058,9 @@ static UINT WINMM_QueryInstanceIDSize(UINT device, DWORD_PTR *len, BOOL is_out)
|
||||||
if(device >= count)
|
if(device >= count)
|
||||||
return MMSYSERR_INVALHANDLE;
|
return MMSYSERR_INVALHANDLE;
|
||||||
|
|
||||||
|
EnterCriticalSection(&g_devthread_lock);
|
||||||
*len = (lstrlenW(devices[device]->dev_id) + 1) * sizeof(WCHAR);
|
*len = (lstrlenW(devices[device]->dev_id) + 1) * sizeof(WCHAR);
|
||||||
|
LeaveCriticalSection(&g_devthread_lock);
|
||||||
|
|
||||||
return MMSYSERR_NOERROR;
|
return MMSYSERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
@ -2963,11 +3084,15 @@ static UINT WINMM_QueryInstanceID(UINT device, WCHAR *str, DWORD_PTR len,
|
||||||
if(device >= count)
|
if(device >= count)
|
||||||
return MMSYSERR_INVALHANDLE;
|
return MMSYSERR_INVALHANDLE;
|
||||||
|
|
||||||
|
EnterCriticalSection(&g_devthread_lock);
|
||||||
id_len = (lstrlenW(devices[device]->dev_id) + 1) * sizeof(WCHAR);
|
id_len = (lstrlenW(devices[device]->dev_id) + 1) * sizeof(WCHAR);
|
||||||
if(len < id_len)
|
if(len < id_len){
|
||||||
|
LeaveCriticalSection(&g_devthread_lock);
|
||||||
return MMSYSERR_ERROR;
|
return MMSYSERR_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(str, devices[device]->dev_id, id_len);
|
memcpy(str, devices[device]->dev_id, id_len);
|
||||||
|
LeaveCriticalSection(&g_devthread_lock);
|
||||||
|
|
||||||
return MMSYSERR_NOERROR;
|
return MMSYSERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
@ -3082,7 +3207,7 @@ UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSi
|
||||||
if(uDeviceID >= g_inmmdevices_count)
|
if(uDeviceID >= g_inmmdevices_count)
|
||||||
return MMSYSERR_BADDEVICEID;
|
return MMSYSERR_BADDEVICEID;
|
||||||
|
|
||||||
caps = &g_in_map[uDeviceID]->in_caps;
|
caps = &read_map(g_in_map, uDeviceID)->in_caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(lpCaps, caps, min(uSize, sizeof(*lpCaps)));
|
memcpy(lpCaps, caps, min(uSize, sizeof(*lpCaps)));
|
||||||
|
@ -3495,10 +3620,10 @@ UINT WINAPI mixerGetDevCapsW(UINT_PTR uDeviceID, LPMIXERCAPSW lpCaps, UINT uSize
|
||||||
return MMSYSERR_BADDEVICEID;
|
return MMSYSERR_BADDEVICEID;
|
||||||
|
|
||||||
if(uDeviceID < g_outmmdevices_count){
|
if(uDeviceID < g_outmmdevices_count){
|
||||||
mmdevice = g_out_map[uDeviceID];
|
mmdevice = read_map(g_out_map, uDeviceID);
|
||||||
memcpy(caps.szPname, mmdevice->out_caps.szPname, sizeof(caps.szPname));
|
memcpy(caps.szPname, mmdevice->out_caps.szPname, sizeof(caps.szPname));
|
||||||
}else{
|
}else{
|
||||||
mmdevice = g_in_map[uDeviceID - g_outmmdevices_count];
|
mmdevice = read_map(g_in_map, uDeviceID - g_outmmdevices_count);
|
||||||
memcpy(caps.szPname, mmdevice->in_caps.szPname, sizeof(caps.szPname));
|
memcpy(caps.szPname, mmdevice->in_caps.szPname, sizeof(caps.szPname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3541,11 +3666,11 @@ UINT WINAPI mixerOpen(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback,
|
||||||
return MMSYSERR_BADDEVICEID;
|
return MMSYSERR_BADDEVICEID;
|
||||||
|
|
||||||
if(uDeviceID < g_outmmdevices_count){
|
if(uDeviceID < g_outmmdevices_count){
|
||||||
mmdevice = g_out_map[uDeviceID];
|
mmdevice = read_map(g_out_map, uDeviceID);
|
||||||
*lphMix = (HMIXER)WINMM_MakeHWAVE(uDeviceID, TRUE,
|
*lphMix = (HMIXER)WINMM_MakeHWAVE(uDeviceID, TRUE,
|
||||||
mmdevice->mixer_count);
|
mmdevice->mixer_count);
|
||||||
}else{
|
}else{
|
||||||
mmdevice = g_in_map[uDeviceID - g_outmmdevices_count];
|
mmdevice = read_map(g_in_map, uDeviceID - g_outmmdevices_count);
|
||||||
*lphMix = (HMIXER)WINMM_MakeHWAVE(uDeviceID - g_outmmdevices_count,
|
*lphMix = (HMIXER)WINMM_MakeHWAVE(uDeviceID - g_outmmdevices_count,
|
||||||
FALSE, mmdevice->mixer_count);
|
FALSE, mmdevice->mixer_count);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue