Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
d4e9b26c
Commit
d4e9b26c
authored
Dec 14, 2012
by
Andrew Eikum
Committed by
Alexandre Julliard
Dec 15, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mmdevapi: Send notifications to clients when the user-selected default device changes.
parent
8d775ec0
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
153 additions
and
6 deletions
+153
-6
devenum.c
dlls/mmdevapi/devenum.c
+153
-6
No files found.
dlls/mmdevapi/devenum.c
View file @
d4e9b26c
...
...
@@ -59,6 +59,11 @@ static const WCHAR reg_devicestate[] =
{
'D'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
'S'
,
't'
,
'a'
,
't'
,
'e'
,
0
};
static
const
WCHAR
reg_properties
[]
=
{
'P'
,
'r'
,
'o'
,
'p'
,
'e'
,
'r'
,
't'
,
'i'
,
'e'
,
's'
,
0
};
static
const
WCHAR
slashW
[]
=
{
'\\'
,
0
};
static
const
WCHAR
reg_out_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'O'
,
'u'
,
't'
,
'p'
,
'u'
,
't'
,
0
};
static
const
WCHAR
reg_vout_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'V'
,
'o'
,
'i'
,
'c'
,
'e'
,
'O'
,
'u'
,
't'
,
'p'
,
'u'
,
't'
,
0
};
static
const
WCHAR
reg_in_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'I'
,
'n'
,
'p'
,
'u'
,
't'
,
0
};
static
const
WCHAR
reg_vin_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'V'
,
'o'
,
'i'
,
'c'
,
'e'
,
'I'
,
'n'
,
'p'
,
'u'
,
't'
,
0
};
static
HKEY
key_render
;
static
HKEY
key_capture
;
...
...
@@ -916,12 +921,6 @@ static HRESULT WINAPI MMDevEnum_GetDefaultAudioEndpoint(IMMDeviceEnumerator *ifa
HKEY
key
;
HRESULT
hr
;
static
const
WCHAR
slashW
[]
=
{
'\\'
,
0
};
static
const
WCHAR
reg_out_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'O'
,
'u'
,
't'
,
'p'
,
'u'
,
't'
,
0
};
static
const
WCHAR
reg_vout_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'V'
,
'o'
,
'i'
,
'c'
,
'e'
,
'O'
,
'u'
,
't'
,
'p'
,
'u'
,
't'
,
0
};
static
const
WCHAR
reg_in_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'I'
,
'n'
,
'p'
,
'u'
,
't'
,
0
};
static
const
WCHAR
reg_vin_nameW
[]
=
{
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'V'
,
'o'
,
'i'
,
'c'
,
'e'
,
'I'
,
'n'
,
'p'
,
'u'
,
't'
,
0
};
TRACE
(
"(%p)->(%u,%u,%p)
\n
"
,
This
,
flow
,
role
,
device
);
if
(
!
device
)
...
...
@@ -1042,6 +1041,7 @@ struct NotificationClientWrapper {
};
static
struct
list
g_notif_clients
=
LIST_INIT
(
g_notif_clients
);
static
HANDLE
g_notif_thread
;
static
CRITICAL_SECTION
g_notif_lock
;
static
CRITICAL_SECTION_DEBUG
g_notif_lock_debug
=
...
...
@@ -1052,6 +1052,147 @@ static CRITICAL_SECTION_DEBUG g_notif_lock_debug =
};
static
CRITICAL_SECTION
g_notif_lock
=
{
&
g_notif_lock_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
void
notify_clients
(
EDataFlow
flow
,
ERole
role
,
const
WCHAR
*
id
)
{
struct
NotificationClientWrapper
*
wrapper
;
LIST_FOR_EACH_ENTRY
(
wrapper
,
&
g_notif_clients
,
struct
NotificationClientWrapper
,
entry
)
IMMNotificationClient_OnDefaultDeviceChanged
(
wrapper
->
client
,
flow
,
role
,
id
);
/* Windows 7 treats changes to eConsole as changes to eMultimedia */
if
(
role
==
eConsole
)
notify_clients
(
flow
,
eMultimedia
,
id
);
}
static
int
notify_if_changed
(
EDataFlow
flow
,
ERole
role
,
HKEY
key
,
const
WCHAR
*
val_name
,
WCHAR
*
old_val
,
IMMDevice
*
def_dev
)
{
WCHAR
new_val
[
64
],
*
id
;
DWORD
size
;
HRESULT
hr
;
size
=
sizeof
(
new_val
);
if
(
RegQueryValueExW
(
key
,
val_name
,
0
,
NULL
,
(
BYTE
*
)
new_val
,
&
size
)
!=
ERROR_SUCCESS
){
if
(
old_val
[
0
]
!=
0
){
/* set by user -> system default */
if
(
def_dev
){
hr
=
IMMDevice_GetId
(
def_dev
,
&
id
);
if
(
FAILED
(
hr
)){
ERR
(
"GetId failed: %08x
\n
"
,
hr
);
return
0
;
}
}
else
id
=
NULL
;
notify_clients
(
flow
,
role
,
id
);
old_val
[
0
]
=
0
;
CoTaskMemFree
(
id
);
return
1
;
}
/* system default -> system default, noop */
return
0
;
}
if
(
!
lstrcmpW
(
old_val
,
new_val
)){
/* set by user -> same value */
return
0
;
}
if
(
new_val
[
0
]
!=
0
){
/* set by user -> different value */
notify_clients
(
flow
,
role
,
new_val
);
memcpy
(
old_val
,
new_val
,
sizeof
(
new_val
));
return
1
;
}
/* set by user -> system default */
if
(
def_dev
){
hr
=
IMMDevice_GetId
(
def_dev
,
&
id
);
if
(
FAILED
(
hr
)){
ERR
(
"GetId failed: %08x
\n
"
,
hr
);
return
0
;
}
}
else
id
=
NULL
;
notify_clients
(
flow
,
role
,
id
);
old_val
[
0
]
=
0
;
CoTaskMemFree
(
id
);
return
1
;
}
static
DWORD
WINAPI
notif_thread_proc
(
void
*
user
)
{
HKEY
key
;
WCHAR
reg_key
[
256
];
WCHAR
out_name
[
64
],
vout_name
[
64
],
in_name
[
64
],
vin_name
[
64
];
DWORD
size
;
lstrcpyW
(
reg_key
,
drv_keyW
);
lstrcatW
(
reg_key
,
slashW
);
lstrcatW
(
reg_key
,
drvs
.
module_name
);
if
(
RegCreateKeyExW
(
HKEY_CURRENT_USER
,
reg_key
,
0
,
NULL
,
0
,
MAXIMUM_ALLOWED
,
NULL
,
&
key
,
NULL
)
!=
ERROR_SUCCESS
){
ERR
(
"RegCreateKeyEx failed: %u
\n
"
,
GetLastError
());
return
1
;
}
size
=
sizeof
(
out_name
);
if
(
RegQueryValueExW
(
key
,
reg_out_nameW
,
0
,
NULL
,
(
BYTE
*
)
out_name
,
&
size
)
!=
ERROR_SUCCESS
)
out_name
[
0
]
=
0
;
size
=
sizeof
(
vout_name
);
if
(
RegQueryValueExW
(
key
,
reg_vout_nameW
,
0
,
NULL
,
(
BYTE
*
)
vout_name
,
&
size
)
!=
ERROR_SUCCESS
)
vout_name
[
0
]
=
0
;
size
=
sizeof
(
in_name
);
if
(
RegQueryValueExW
(
key
,
reg_in_nameW
,
0
,
NULL
,
(
BYTE
*
)
in_name
,
&
size
)
!=
ERROR_SUCCESS
)
in_name
[
0
]
=
0
;
size
=
sizeof
(
vin_name
);
if
(
RegQueryValueExW
(
key
,
reg_vin_nameW
,
0
,
NULL
,
(
BYTE
*
)
vin_name
,
&
size
)
!=
ERROR_SUCCESS
)
vin_name
[
0
]
=
0
;
while
(
1
){
if
(
RegNotifyChangeKeyValue
(
key
,
FALSE
,
REG_NOTIFY_CHANGE_LAST_SET
,
NULL
,
FALSE
)
!=
ERROR_SUCCESS
){
ERR
(
"RegNotifyChangeKeyValue failed: %u
\n
"
,
GetLastError
());
RegCloseKey
(
key
);
g_notif_thread
=
NULL
;
return
1
;
}
EnterCriticalSection
(
&
g_notif_lock
);
notify_if_changed
(
eRender
,
eConsole
,
key
,
reg_out_nameW
,
out_name
,
&
MMDevice_def_play
->
IMMDevice_iface
);
notify_if_changed
(
eRender
,
eCommunications
,
key
,
reg_vout_nameW
,
vout_name
,
&
MMDevice_def_play
->
IMMDevice_iface
);
notify_if_changed
(
eCapture
,
eConsole
,
key
,
reg_in_nameW
,
in_name
,
&
MMDevice_def_rec
->
IMMDevice_iface
);
notify_if_changed
(
eCapture
,
eCommunications
,
key
,
reg_vin_nameW
,
vin_name
,
&
MMDevice_def_rec
->
IMMDevice_iface
);
LeaveCriticalSection
(
&
g_notif_lock
);
}
RegCloseKey
(
key
);
g_notif_thread
=
NULL
;
return
0
;
}
static
HRESULT
WINAPI
MMDevEnum_RegisterEndpointNotificationCallback
(
IMMDeviceEnumerator
*
iface
,
IMMNotificationClient
*
client
)
{
MMDevEnumImpl
*
This
=
impl_from_IMMDeviceEnumerator
(
iface
);
...
...
@@ -1072,6 +1213,12 @@ static HRESULT WINAPI MMDevEnum_RegisterEndpointNotificationCallback(IMMDeviceEn
list_add_tail
(
&
g_notif_clients
,
&
wrapper
->
entry
);
if
(
!
g_notif_thread
){
g_notif_thread
=
CreateThread
(
NULL
,
0
,
notif_thread_proc
,
NULL
,
0
,
NULL
);
if
(
!
g_notif_thread
)
ERR
(
"CreateThread failed: %u
\n
"
,
GetLastError
());
}
LeaveCriticalSection
(
&
g_notif_lock
);
return
S_OK
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment