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)
|
||||
{
|
||||
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);
|
||||
|
||||
padid = MSACM_GetDriverID(hadid);
|
||||
if (!padid) {
|
||||
WARN("invalid handle\n");
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
}
|
||||
|
||||
/* Check for unknown flags */
|
||||
if (fdwPriority &
|
||||
~(ACM_DRIVERPRIORITYF_ENABLE|ACM_DRIVERPRIORITYF_DISABLE|
|
||||
|
@ -442,32 +429,90 @@ MMRESULT WINAPI acmDriverPriority(HACMDRIVERID hadid, DWORD dwPriority, DWORD fd
|
|||
return MMSYSERR_INVALFLAG;
|
||||
}
|
||||
|
||||
lError = RegOpenKeyA(HKEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Multimedia\\"
|
||||
"Audio Compression Manager\\Priority v4.00",
|
||||
&hPriorityKey
|
||||
);
|
||||
/* FIXME: Create key */
|
||||
if (lError != ERROR_SUCCESS) {
|
||||
WARN("RegOpenKeyA failed\n");
|
||||
return MMSYSERR_ERROR;
|
||||
/* 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;
|
||||
|
||||
/* Fetch driver ID */
|
||||
padid = MSACM_GetDriverID(hadid);
|
||||
if (!padid) {
|
||||
WARN("invalid handle\n");
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
}
|
||||
|
||||
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;
|
||||
/* Check whether driver ID is appropriate for requested op */
|
||||
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;
|
||||
}
|
||||
|
||||
RegCloseKey(hPriorityKey);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
WARN("RegQueryValueA failed\n");
|
||||
return MMSYSERR_ERROR;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -491,6 +536,7 @@ MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
|
|||
}
|
||||
|
||||
MSACM_UnregisterDriver(padid);
|
||||
MSACM_BroadcastNotification();
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ HANDLE MSACM_hHeap = NULL;
|
|||
PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
|
||||
PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
|
||||
|
||||
static DWORD MSACM_suspendBroadcastCount = 0;
|
||||
static BOOL MSACM_pendingBroadcast = FALSE;
|
||||
|
||||
static void MSACM_ReorderDriversByPriority(void);
|
||||
|
||||
#if 0
|
||||
|
@ -333,6 +336,90 @@ void MSACM_RegisterAllDrivers(void)
|
|||
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()
|
||||
* 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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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()
|
||||
*/
|
||||
|
|
|
@ -348,6 +348,12 @@ extern PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj, DWORD type);
|
|||
extern MMRESULT MSACM_Message(HACMDRIVER, UINT, LPARAM, LPARAM);
|
||||
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 */
|
||||
extern HINSTANCE MSACM_hInstance32;
|
||||
|
||||
|
|
Loading…
Reference in New Issue