msacm: Implement acmDriverPriority with driver priority/enabled saving.
Foundation for notification broadcasts with support for deferred notification.
This commit is contained in:
parent
8d52016114
commit
cb37c43d78
|
@ -404,22 +404,9 @@ MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpe
|
||||||
*/
|
*/
|
||||||
MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority)
|
MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority)
|
||||||
{
|
{
|
||||||
PWINE_ACMDRIVERID padid;
|
|
||||||
CHAR szSubKey[17];
|
|
||||||
CHAR szBuffer[256];
|
|
||||||
LONG lBufferLength = sizeof(szBuffer);
|
|
||||||
LONG lError;
|
|
||||||
HKEY hPriorityKey;
|
|
||||||
DWORD dwPriorityCounter;
|
|
||||||
|
|
||||||
TRACE("(%p, %08lx, %08lx)\n", hadid, dwPriority, fdwPriority);
|
TRACE("(%p, %08lx, %08lx)\n", hadid, dwPriority, fdwPriority);
|
||||||
|
|
||||||
padid = MSACM_GetDriverID(hadid);
|
|
||||||
if (!padid) {
|
|
||||||
WARN("invalid handle\n");
|
|
||||||
return MMSYSERR_INVALHANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for unknown flags */
|
/* Check for unknown flags */
|
||||||
if (fdwPriority &
|
if (fdwPriority &
|
||||||
~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE|
|
~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE|
|
||||||
|
@ -441,33 +428,91 @@ MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fd
|
||||||
WARN("invalid flag\n");
|
WARN("invalid flag\n");
|
||||||
return MMSYSERR_INVALFLAG;
|
return MMSYSERR_INVALFLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* According to MSDN, ACM_DRIVERPRIORITYF_BEGIN and ACM_DRIVERPRIORITYF_END
|
||||||
|
may only appear by themselves, and in addition, hadid and dwPriority must
|
||||||
|
both be zero */
|
||||||
|
if ((fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) ||
|
||||||
|
(fdwPriority & ACM_DRIVERPRIORITYF_END)) {
|
||||||
|
if (fdwPriority & ~(ACM_DRIVERPRIORITYF_BEGIN|ACM_DRIVERPRIORITYF_END)) {
|
||||||
|
WARN("ACM_DRIVERPRIORITYF_[BEGIN|END] cannot be used with any other flags\n");
|
||||||
|
return MMSYSERR_INVALPARAM;
|
||||||
|
}
|
||||||
|
if (dwPriority) {
|
||||||
|
WARN("priority invalid with ACM_DRIVERPRIORITYF_[BEGIN|END]\n");
|
||||||
|
return MMSYSERR_INVALPARAM;
|
||||||
|
}
|
||||||
|
if (hadid) {
|
||||||
|
WARN("non-null hadid invalid with ACM_DRIVERPRIORITYF_[BEGIN|END]\n");
|
||||||
|
return MMSYSERR_INVALPARAM;
|
||||||
|
}
|
||||||
|
/* FIXME: MSDN wording suggests that deferred notification should be
|
||||||
|
implemented as a system-wide lock held by a calling task, and that
|
||||||
|
re-enabling notifications should broadcast them across all processes.
|
||||||
|
This implementation uses a simple DWORD counter. One consequence of the
|
||||||
|
current implementation is that applications will never see
|
||||||
|
MMSYSERR_ALLOCATED as a return error.
|
||||||
|
*/
|
||||||
|
if (fdwPriority & ACM_DRIVERPRIORITYF_BEGIN) {
|
||||||
|
MSACM_DisableNotifications();
|
||||||
|
} else if (fdwPriority & ACM_DRIVERPRIORITYF_END) {
|
||||||
|
MSACM_EnableNotifications();
|
||||||
|
}
|
||||||
|
return MMSYSERR_NOERROR;
|
||||||
|
} else {
|
||||||
|
PWINE_ACMDRIVERID padid;
|
||||||
|
BOOL bPerformBroadcast = FALSE;
|
||||||
|
|
||||||
lError = RegOpenKeyA(HKEY_CURRENT_USER,
|
/* Fetch driver ID */
|
||||||
"Software\\Microsoft\\Multimedia\\"
|
padid = MSACM_GetDriverID(hadid);
|
||||||
"Audio Compression Manager\\Priority v4.00",
|
if (!padid) {
|
||||||
&hPriorityKey
|
WARN("invalid handle\n");
|
||||||
);
|
return MMSYSERR_INVALHANDLE;
|
||||||
/* FIXME: Create key */
|
}
|
||||||
if (lError != ERROR_SUCCESS) {
|
|
||||||
WARN("RegOpenKeyA failed\n");
|
/* Check whether driver ID is appropriate for requested op */
|
||||||
return MMSYSERR_ERROR;
|
if (dwPriority) {
|
||||||
|
if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL) {
|
||||||
|
return MMSYSERR_NOTSUPPORTED;
|
||||||
|
}
|
||||||
|
if (dwPriority != 1 && dwPriority != -1) {
|
||||||
|
FIXME("unexpected priority %ld, using sign only\n", dwPriority);
|
||||||
|
if (dwPriority < 0) dwPriority = -1;
|
||||||
|
if (dwPriority > 0) dwPriority = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwPriority == 1 && (padid->pPrevACMDriverID == NULL ||
|
||||||
|
(padid->pPrevACMDriverID->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL))) {
|
||||||
|
/* do nothing - driver is first of list, or first after last
|
||||||
|
local driver */
|
||||||
|
} else if (dwPriority == -1 && padid->pNextACMDriverID == NULL) {
|
||||||
|
/* do nothing - driver is last of list */
|
||||||
|
} else {
|
||||||
|
MSACM_RePositionDriver(padid, dwPriority);
|
||||||
|
bPerformBroadcast = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether driver ID should be enabled or disabled */
|
||||||
|
if (fdwPriority & ACM_DRIVERPRIORITYF_DISABLE) {
|
||||||
|
if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)) {
|
||||||
|
padid->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
|
||||||
|
bPerformBroadcast = TRUE;
|
||||||
|
}
|
||||||
|
} else if (fdwPriority & ACM_DRIVERPRIORITYF_ENABLE) {
|
||||||
|
if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) {
|
||||||
|
padid->fdwSupport &= ~ACMDRIVERDETAILS_SUPPORTF_DISABLED;
|
||||||
|
bPerformBroadcast = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform broadcast of changes */
|
||||||
|
if (bPerformBroadcast) {
|
||||||
|
MSACM_WriteCurrentPriorities();
|
||||||
|
MSACM_BroadcastNotification();
|
||||||
|
}
|
||||||
|
return MMSYSERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (dwPriorityCounter = 1; ; dwPriorityCounter++) {
|
|
||||||
snprintf(szSubKey, 17, "Priority%ld", dwPriorityCounter);
|
|
||||||
lError = RegQueryValueA(hPriorityKey, szSubKey, szBuffer, &lBufferLength);
|
|
||||||
if (lError != ERROR_SUCCESS)
|
|
||||||
break;
|
|
||||||
|
|
||||||
FIXME("(%p, %ld, %ld): stub (partial)\n",
|
|
||||||
hadid, dwPriority, fdwPriority);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(hPriorityKey);
|
|
||||||
|
|
||||||
WARN("RegQueryValueA failed\n");
|
|
||||||
return MMSYSERR_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -491,6 +536,7 @@ MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
|
||||||
}
|
}
|
||||||
|
|
||||||
MSACM_UnregisterDriver(padid);
|
MSACM_UnregisterDriver(padid);
|
||||||
|
MSACM_BroadcastNotification();
|
||||||
|
|
||||||
return MMSYSERR_NOERROR;
|
return MMSYSERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,9 @@ HANDLE MSACM_hHeap = NULL;
|
||||||
PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
|
PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
|
||||||
PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
|
PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
|
||||||
|
|
||||||
|
static DWORD MSACM_suspendBroadcastCount = 0;
|
||||||
|
static BOOL MSACM_pendingBroadcast = FALSE;
|
||||||
|
|
||||||
static void MSACM_ReorderDriversByPriority(void);
|
static void MSACM_ReorderDriversByPriority(void);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -333,6 +336,90 @@ void MSACM_RegisterAllDrivers(void)
|
||||||
MSACM_RegisterDriver(msacm32, msacm32, 0);
|
MSACM_RegisterDriver(msacm32, msacm32, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MSACM_BroadcastNotification()
|
||||||
|
*/
|
||||||
|
void MSACM_BroadcastNotification(void)
|
||||||
|
{
|
||||||
|
if (MSACM_suspendBroadcastCount <= 0) {
|
||||||
|
FIXME("notification broadcast not (yet) implemented\n");
|
||||||
|
} else {
|
||||||
|
MSACM_pendingBroadcast = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MSACM_DisableNotifications()
|
||||||
|
*/
|
||||||
|
void MSACM_DisableNotifications(void)
|
||||||
|
{
|
||||||
|
MSACM_suspendBroadcastCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MSACM_EnableNotifications()
|
||||||
|
*/
|
||||||
|
void MSACM_EnableNotifications(void)
|
||||||
|
{
|
||||||
|
if (MSACM_suspendBroadcastCount > 0) {
|
||||||
|
MSACM_suspendBroadcastCount--;
|
||||||
|
if (MSACM_suspendBroadcastCount == 0 && MSACM_pendingBroadcast) {
|
||||||
|
MSACM_pendingBroadcast = FALSE;
|
||||||
|
MSACM_BroadcastNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MSACM_RePositionDriver()
|
||||||
|
*/
|
||||||
|
void MSACM_RePositionDriver(PWINE_ACMDRIVERID padid, DWORD dwPriority)
|
||||||
|
{
|
||||||
|
PWINE_ACMDRIVERID pTargetPosition = NULL;
|
||||||
|
|
||||||
|
/* Remove selected driver from linked list */
|
||||||
|
if (MSACM_pFirstACMDriverID == padid) {
|
||||||
|
MSACM_pFirstACMDriverID = padid->pNextACMDriverID;
|
||||||
|
}
|
||||||
|
if (MSACM_pLastACMDriverID == padid) {
|
||||||
|
MSACM_pLastACMDriverID = padid->pPrevACMDriverID;
|
||||||
|
}
|
||||||
|
if (padid->pPrevACMDriverID != NULL) {
|
||||||
|
padid->pPrevACMDriverID->pNextACMDriverID = padid->pNextACMDriverID;
|
||||||
|
}
|
||||||
|
if (padid->pNextACMDriverID != NULL) {
|
||||||
|
padid->pNextACMDriverID->pPrevACMDriverID = padid->pPrevACMDriverID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up position where selected driver should be */
|
||||||
|
if (dwPriority == 1) {
|
||||||
|
pTargetPosition = padid->pPrevACMDriverID;
|
||||||
|
while (pTargetPosition->pPrevACMDriverID != NULL &&
|
||||||
|
!(pTargetPosition->pPrevACMDriverID->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL)) {
|
||||||
|
pTargetPosition = pTargetPosition->pPrevACMDriverID;
|
||||||
|
}
|
||||||
|
} else if (dwPriority == -1) {
|
||||||
|
pTargetPosition = padid->pNextACMDriverID;
|
||||||
|
while (pTargetPosition->pNextACMDriverID != NULL) {
|
||||||
|
pTargetPosition = pTargetPosition->pNextACMDriverID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Place selected driver in selected position */
|
||||||
|
padid->pPrevACMDriverID = pTargetPosition->pPrevACMDriverID;
|
||||||
|
padid->pNextACMDriverID = pTargetPosition;
|
||||||
|
if (padid->pPrevACMDriverID != NULL) {
|
||||||
|
padid->pPrevACMDriverID->pNextACMDriverID = padid;
|
||||||
|
} else {
|
||||||
|
MSACM_pFirstACMDriverID = padid;
|
||||||
|
}
|
||||||
|
if (padid->pNextACMDriverID != NULL) {
|
||||||
|
padid->pNextACMDriverID->pPrevACMDriverID = padid;
|
||||||
|
} else {
|
||||||
|
MSACM_pLastACMDriverID = padid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MSACM_ReorderDriversByPriority()
|
* MSACM_ReorderDriversByPriority()
|
||||||
* Reorders all drivers based on the priority list indicated by the registry key:
|
* Reorders all drivers based on the priority list indicated by the registry key:
|
||||||
|
@ -445,6 +532,79 @@ errCleanUp:
|
||||||
if (driverList != NULL) HeapFree(MSACM_hHeap, 0, driverList);
|
if (driverList != NULL) HeapFree(MSACM_hHeap, 0, driverList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* MSACM_WriteCurrentPriorities()
|
||||||
|
* Writes out current order of driver priorities to registry key:
|
||||||
|
* HKCU\\Software\\Microsoft\\Multimedia\\Audio Compression Manager\\Priority v4.00
|
||||||
|
*/
|
||||||
|
void MSACM_WriteCurrentPriorities(void)
|
||||||
|
{
|
||||||
|
LONG lError;
|
||||||
|
HKEY hPriorityKey;
|
||||||
|
static const WCHAR basePriorityKey[] = {
|
||||||
|
'S','o','f','t','w','a','r','e','\\',
|
||||||
|
'M','i','c','r','o','s','o','f','t','\\',
|
||||||
|
'M','u','l','t','i','m','e','d','i','a','\\',
|
||||||
|
'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
|
||||||
|
'P','r','i','o','r','i','t','y',' ','v','4','.','0','0','\0'
|
||||||
|
};
|
||||||
|
PWINE_ACMDRIVERID padid;
|
||||||
|
DWORD dwPriorityCounter;
|
||||||
|
static const WCHAR priorityTmpl[] = {'P','r','i','o','r','i','t','y','%','l','d','\0'};
|
||||||
|
static const WCHAR valueTmpl[] = {'%','c',',',' ','%','s','\0'};
|
||||||
|
static const WCHAR converterAlias[] = {'I','n','t','e','r','n','a','l',' ','P','C','M',' ','C','o','n','v','e','r','t','e','r','\0'};
|
||||||
|
WCHAR szSubKey[17];
|
||||||
|
WCHAR szBuffer[256];
|
||||||
|
|
||||||
|
/* Delete ACM priority key and create it anew */
|
||||||
|
lError = RegDeleteKeyW(HKEY_CURRENT_USER, basePriorityKey);
|
||||||
|
if (lError != ERROR_SUCCESS && lError != ERROR_FILE_NOT_FOUND) {
|
||||||
|
ERR("unable to remove current key %s (0x%08lx) - priority changes won't persist past application end.\n",
|
||||||
|
debugstr_w(basePriorityKey), lError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lError = RegCreateKeyW(HKEY_CURRENT_USER, basePriorityKey, &hPriorityKey);
|
||||||
|
if (lError != ERROR_SUCCESS) {
|
||||||
|
ERR("unable to create key %s (0x%08lx) - priority changes won't persist past application end.\n",
|
||||||
|
debugstr_w(basePriorityKey), lError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write current list of priorities */
|
||||||
|
for (dwPriorityCounter = 0, padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
|
||||||
|
if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL) continue;
|
||||||
|
if (padid->pszDriverAlias == NULL) continue; /* internal PCM converter is last */
|
||||||
|
|
||||||
|
/* Build required value name */
|
||||||
|
dwPriorityCounter++;
|
||||||
|
snprintfW(szSubKey, 17, priorityTmpl, dwPriorityCounter);
|
||||||
|
|
||||||
|
/* Value has a 1 in front for enabled drivers and 0 for disabled drivers */
|
||||||
|
snprintfW(szBuffer, 256, valueTmpl, (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ? '0' : '1', padid->pszDriverAlias);
|
||||||
|
strlwrW(szBuffer);
|
||||||
|
|
||||||
|
lError = RegSetValueExW(hPriorityKey, szSubKey, 0, REG_SZ, (BYTE *)szBuffer, (strlenW(szBuffer) + 1) * sizeof(WCHAR));
|
||||||
|
if (lError != ERROR_SUCCESS) {
|
||||||
|
ERR("unable to write value for %s under key %s (0x%08lx)\n",
|
||||||
|
debugstr_w(padid->pszDriverAlias), debugstr_w(basePriorityKey), lError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build required value name */
|
||||||
|
dwPriorityCounter++;
|
||||||
|
snprintfW(szSubKey, 17, priorityTmpl, dwPriorityCounter);
|
||||||
|
|
||||||
|
/* Value has a 1 in front for enabled drivers and 0 for disabled drivers */
|
||||||
|
snprintfW(szBuffer, 256, valueTmpl, '1', converterAlias);
|
||||||
|
|
||||||
|
lError = RegSetValueExW(hPriorityKey, szSubKey, 0, REG_SZ, (BYTE *)szBuffer, (strlenW(szBuffer) + 1) * sizeof(WCHAR));
|
||||||
|
if (lError != ERROR_SUCCESS) {
|
||||||
|
ERR("unable to write value for %s under key %s (0x%08lx)\n",
|
||||||
|
debugstr_w(converterAlias), debugstr_w(basePriorityKey), lError);
|
||||||
|
}
|
||||||
|
RegCloseKey(hPriorityKey);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* MSACM_UnregisterDriver()
|
* MSACM_UnregisterDriver()
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -348,6 +348,12 @@ extern PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj, DWORD type);
|
||||||
extern MMRESULT MSACM_Message(HACMDRIVER, UINT, LPARAM, LPARAM);
|
extern MMRESULT MSACM_Message(HACMDRIVER, UINT, LPARAM, LPARAM);
|
||||||
extern BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID*, DWORD, LPDWORD);
|
extern BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID*, DWORD, LPDWORD);
|
||||||
|
|
||||||
|
extern void MSACM_RePositionDriver(PWINE_ACMDRIVERID, DWORD);
|
||||||
|
extern void MSACM_WriteCurrentPriorities(void);
|
||||||
|
extern void MSACM_BroadcastNotification(void);
|
||||||
|
extern void MSACM_DisableNotifications(void);
|
||||||
|
extern void MSACM_EnableNotifications(void);
|
||||||
|
|
||||||
/* From msacm32.c */
|
/* From msacm32.c */
|
||||||
extern HINSTANCE MSACM_hInstance32;
|
extern HINSTANCE MSACM_hInstance32;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue