896 lines
26 KiB
C++
896 lines
26 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// File: gfxui.c
|
|
//
|
|
// This file defines the functions that are used by the Global
|
|
// Effects (GFX) page to drive manipulate the effects for a
|
|
// mixer.
|
|
//
|
|
// History:
|
|
// 10 June 2000 RogerW
|
|
// Created.
|
|
//
|
|
// Copyright (C) 2000 Microsoft Corporation All Rights Reserved.
|
|
//
|
|
// Microsoft Confidential
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//=============================================================================
|
|
// Include files
|
|
//=============================================================================
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include "mmcpl.h"
|
|
#include <mmddkp.h>
|
|
#include <olectl.h>
|
|
#include <ocidl.h>
|
|
#include "gfxui.h"
|
|
|
|
#define ADDGFX
|
|
#define REGSTR_VAL_FRIENDLYNAME TEXT("FriendlyName")
|
|
|
|
|
|
//
|
|
// IDataObject Implementation
|
|
//
|
|
class GFXDataObject : public IDataObject
|
|
{
|
|
public:
|
|
GFXDataObject (DWORD dwGfxID) { m_cRef = 1; m_dwGfxID = dwGfxID; }
|
|
|
|
// IUnknown interface
|
|
STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppv);
|
|
STDMETHODIMP_(ULONG) AddRef () { return ++m_cRef; }
|
|
STDMETHODIMP_(ULONG) Release () { return --m_cRef; }
|
|
|
|
STDMETHODIMP GetData (FORMATETC * pformatetcIn, STGMEDIUM * pmedium);
|
|
STDMETHODIMP GetDataHere (FORMATETC * pformatetc, STGMEDIUM *pmedium) { return E_NOTIMPL; }
|
|
STDMETHODIMP QueryGetData (FORMATETC * pformatetc) { return E_NOTIMPL; }
|
|
STDMETHODIMP GetCanonicalFormatEtc (FORMATETC * pformatetcIn, FORMATETC * pFormatetcOut) { return E_NOTIMPL; }
|
|
STDMETHODIMP SetData (FORMATETC * pformatetc, STGMEDIUM * pmedium, BOOL fRelease) { return E_NOTIMPL; }
|
|
STDMETHODIMP EnumFormatEtc (DWORD dwDirection, IEnumFORMATETC ** ppenumFormatEtc ) { return E_NOTIMPL; }
|
|
STDMETHODIMP DAdvise (FORMATETC * pformatetc, DWORD advf, IAdviseSink* pAdvSnk, DWORD * pdwConnection) { return E_NOTIMPL; }
|
|
STDMETHODIMP DUnadvise (DWORD dwConnection) { return E_NOTIMPL; }
|
|
STDMETHODIMP EnumDAdvise (IEnumSTATDATA ** ppenumAdvise) { return E_NOTIMPL; }
|
|
|
|
private:
|
|
UINT m_cRef;
|
|
DWORD m_dwGfxID;
|
|
|
|
};
|
|
|
|
STDMETHODIMP GFXDataObject::QueryInterface (REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
|
|
if (!ppvObj)
|
|
return E_POINTER;
|
|
|
|
*ppvObj = NULL;
|
|
if (IsEqualIID(riid,IID_IDataObject) ||
|
|
IsEqualIID(riid,IID_IUnknown))
|
|
*ppvObj = (IDataObject *) this;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
((IUnknown *) *ppvObj) -> AddRef ();
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
STDMETHODIMP GFXDataObject::GetData (LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) // @parm Storage to be created.
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pformatetc && pmedium && TYMED_HGLOBAL == pformatetc -> tymed)
|
|
{
|
|
HANDLE hGfx = NULL;
|
|
|
|
#ifdef ADDGFX
|
|
hr = gfxOpenGfx (m_dwGfxID, &hGfx);
|
|
#endif // ADDGFX
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
pmedium -> tymed = TYMED_HGLOBAL;
|
|
pmedium -> pUnkForRelease = NULL;
|
|
pmedium -> hGlobal = hGfx;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT InitList (DWORD dwMixID, DWORD dwType, PPGFXUILIST ppList)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppList)
|
|
{
|
|
PGFXUILIST pList = (PGFXUILIST) LocalAlloc (LPTR, sizeof (GFXUILIST));
|
|
*ppList = NULL; // Init pointer
|
|
|
|
if (pList)
|
|
{
|
|
hr = S_OK;
|
|
pList -> dwType = dwType;
|
|
pList -> puiList = NULL;
|
|
#ifdef UNICODE
|
|
pList -> pszZoneDi = (PWSTR) GetInterfaceName (dwMixID);
|
|
#else
|
|
pList -> pszZoneDi = NULL; // This should not happen
|
|
#endif
|
|
if (pList -> pszZoneDi)
|
|
{
|
|
// Return new list
|
|
*ppList = pList;
|
|
}
|
|
else
|
|
{
|
|
// Error!
|
|
LocalFree (pList);
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
void GFXUI_FreeList (PPGFXUILIST ppList)
|
|
{
|
|
|
|
if (ppList)
|
|
{
|
|
PGFXUILIST pList = *ppList;
|
|
|
|
if (pList)
|
|
{
|
|
// Free Zone
|
|
if (pList -> pszZoneDi)
|
|
GlobalFreePtr (pList -> pszZoneDi);
|
|
pList -> pszZoneDi = NULL;
|
|
|
|
// Free GFX List
|
|
FreeListNodes (&(pList -> puiList));
|
|
|
|
// Free list
|
|
LocalFree (pList);
|
|
*ppList = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FreeListNodes (PPGFXUI ppuiList)
|
|
{
|
|
|
|
if (ppuiList)
|
|
{
|
|
PGFXUI pNodeDelete;
|
|
PGFXUI puiList = *ppuiList;
|
|
|
|
// Free list nodes
|
|
while (puiList)
|
|
{
|
|
pNodeDelete = puiList;
|
|
puiList = puiList -> pNext;
|
|
FreeNode (&pNodeDelete);
|
|
}
|
|
|
|
*ppuiList = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void FreeNode (PPGFXUI ppNode)
|
|
{
|
|
|
|
if (ppNode && *ppNode)
|
|
{
|
|
PGFXUI pNode = *ppNode;
|
|
|
|
// Free the strings
|
|
if (pNode -> pszName)
|
|
LocalFree (pNode -> pszName);
|
|
if (pNode -> pszFactoryDi)
|
|
LocalFree (pNode -> pszFactoryDi);
|
|
|
|
// Free the node
|
|
LocalFree (pNode);
|
|
*ppNode = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
HKEY OpenGfxRegKey (PCWSTR pszGfxFactoryDi, REGSAM sam)
|
|
{
|
|
|
|
HKEY hkeyGfx = NULL;
|
|
|
|
if (pszGfxFactoryDi)
|
|
{
|
|
HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList (NULL, NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE != DeviceInfoSet)
|
|
{
|
|
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
|
|
DeviceInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
|
|
|
|
if (SetupDiOpenDeviceInterface (DeviceInfoSet, pszGfxFactoryDi,
|
|
0, &DeviceInterfaceData))
|
|
{
|
|
hkeyGfx = SetupDiOpenDeviceInterfaceRegKey (
|
|
DeviceInfoSet, &DeviceInterfaceData,
|
|
0, sam);
|
|
}
|
|
SetupDiDestroyDeviceInfoList (DeviceInfoSet);
|
|
}
|
|
}
|
|
|
|
return hkeyGfx;
|
|
|
|
}
|
|
|
|
|
|
HRESULT GetFriendlyName (PCWSTR pszGfxFactoryDi, PWSTR* ppszName)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
HKEY hkeyGfx = NULL;
|
|
|
|
// Check parameters
|
|
if (ppszName && pszGfxFactoryDi)
|
|
{
|
|
HKEY hkeyGfx = OpenGfxRegKey (pszGfxFactoryDi, KEY_READ);
|
|
*ppszName = NULL;
|
|
|
|
if (hkeyGfx)
|
|
{
|
|
WCHAR szBuffer[MAX_PATH];
|
|
DWORD dwType = REG_SZ;
|
|
DWORD cb = sizeof (szBuffer) / sizeof (szBuffer[0]);
|
|
|
|
hr = S_OK;
|
|
|
|
if (ERROR_SUCCESS == RegQueryValueEx (hkeyGfx, REGSTR_VAL_FRIENDLYNAME, NULL, &dwType, (LPBYTE)szBuffer, &cb))
|
|
{
|
|
*ppszName = (PWSTR) LocalAlloc (LPTR, lstrlen (szBuffer)*2+2);
|
|
if (*ppszName)
|
|
wcscpy (*ppszName, szBuffer);
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
hr = REGDB_E_READREGDB;
|
|
|
|
RegCloseKey (hkeyGfx);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
HRESULT AddFactoryNode (PCWSTR pszGfxFactoryDi, PPGFXUILIST ppList)
|
|
{
|
|
return AddNode (pszGfxFactoryDi, 0, GUID_NULL, 0, 0, 0, ppList);
|
|
}
|
|
|
|
|
|
HRESULT AddNode (PCWSTR pszGfxFactoryDi, DWORD Id, REFCLSID rclsid, DWORD Type,
|
|
DWORD Order, DWORD nFlags, PPGFXUILIST ppList)
|
|
{
|
|
|
|
PGFXUI pNode = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
// Check parameters
|
|
if (!ppList || !(*ppList) || !pszGfxFactoryDi)
|
|
return E_INVALIDARG;
|
|
|
|
// Create node
|
|
if (SUCCEEDED (hr = CreateNode (NULL, pszGfxFactoryDi, &pNode)))
|
|
{
|
|
if (pNode)
|
|
{
|
|
// Initilize the rest of the values
|
|
pNode -> Id = Id;
|
|
pNode -> Type = Type;
|
|
pNode -> Order = Order;
|
|
pNode -> nFlags = nFlags;
|
|
pNode -> clsidUI = rclsid;
|
|
|
|
if (FAILED (hr = AttachNode (ppList, pNode)))
|
|
FreeNode (&pNode);
|
|
}
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
// Note: This function always adds the node to the list IN ORDER
|
|
// IFF (pNode -> nFlags & GFX_CREATED).
|
|
HRESULT AttachNode (PPGFXUILIST ppList, PGFXUI pNode)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
// Check parameters
|
|
if (ppList && (*ppList) && pNode)
|
|
{
|
|
PGFXUI puiList = (*ppList) -> puiList;
|
|
hr = S_OK;
|
|
|
|
// Make sure our next pointer starts out null..
|
|
pNode -> pNext = NULL;
|
|
|
|
if (puiList)
|
|
{
|
|
if (!(pNode -> nFlags & GFX_CREATED) ||
|
|
(puiList -> Order >= pNode -> Order))
|
|
{
|
|
// Order is not available, just stick it on the front or
|
|
// the order happens to put the node at the front.
|
|
pNode -> pNext = puiList;
|
|
puiList = pNode;
|
|
}
|
|
else
|
|
{
|
|
PGFXUI pSearch = puiList;
|
|
|
|
if (!(puiList -> pNext))
|
|
{
|
|
// One element list. We know the new node doesn't belong
|
|
// at the head of the list, so it is behind.
|
|
puiList -> pNext = pNode;
|
|
} else {
|
|
|
|
while (pSearch -> pNext)
|
|
{
|
|
if (!(pSearch -> pNext -> nFlags & GFX_CREATED))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
break; // Cannot mix list types
|
|
}
|
|
|
|
if (pSearch -> pNext -> Order >= pNode -> Order)
|
|
{
|
|
// We found the insertion point!
|
|
pNode -> pNext = pSearch -> pNext;
|
|
pSearch -> pNext = pNode;
|
|
break;
|
|
}
|
|
|
|
if (!(pSearch -> pNext -> pNext))
|
|
{
|
|
// At end of list, attach node to end
|
|
pSearch -> pNext -> pNext = pNode;
|
|
break;
|
|
}
|
|
|
|
// Move to next element
|
|
pSearch = pSearch -> pNext;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// First element of the list
|
|
puiList = pNode;
|
|
}
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
// Ensure we pass back the correct list pointer
|
|
(*ppList) -> puiList = puiList;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
LONG GFXEnum (PVOID Context, DWORD Id, PCWSTR GfxFactoryDi, REFCLSID rclsid, DWORD Type, DWORD Order)
|
|
{
|
|
|
|
PGFXUILIST pList = (PGFXUILIST) Context;
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pList)
|
|
{
|
|
if (Type == pList->dwType)
|
|
{
|
|
if (FAILED (hr = AddNode (GfxFactoryDi, Id, rclsid, Type, Order, GFX_CREATED, &pList)))
|
|
{
|
|
// Error, free the list
|
|
GFXUI_FreeList (&pList);
|
|
Context = NULL;
|
|
}
|
|
}
|
|
else hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
BOOL GFXUI_CheckDevice (DWORD dwMixID, DWORD dwType)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL fRet = FALSE;
|
|
PGFXUILIST pList = NULL;
|
|
|
|
if (SUCCEEDED (hr = InitList (dwMixID, dwType, &pList)))
|
|
{
|
|
if (pList && pList -> pszZoneDi)
|
|
{
|
|
PDEVICEINTERFACELIST pdiList = NULL;
|
|
LONG lResult = NO_ERROR;
|
|
|
|
lResult = gfxCreateGfxFactoriesList (pList -> pszZoneDi, &pdiList);
|
|
|
|
if ((lResult == NO_ERROR) && pdiList)
|
|
{
|
|
fRet = TRUE;
|
|
gfxDestroyDeviceInterfaceList (pdiList);
|
|
}
|
|
|
|
GFXUI_FreeList (&pList);
|
|
}
|
|
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
HRESULT GFXUI_CreateList (DWORD dwMixID, DWORD dwType, BOOL fAll, PPGFXUILIST ppList)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppList)
|
|
{
|
|
hr = S_OK;
|
|
|
|
if (SUCCEEDED (hr = InitList (dwMixID, dwType, ppList)))
|
|
{
|
|
if (*ppList && (*ppList) -> pszZoneDi)
|
|
{
|
|
if (!fAll)
|
|
{
|
|
hr = gfxEnumerateGfxs ((*ppList) -> pszZoneDi, GFXEnum, (*ppList));
|
|
}
|
|
else
|
|
{
|
|
PDEVICEINTERFACELIST pdiList = NULL;
|
|
|
|
hr = gfxCreateGfxFactoriesList ((*ppList) -> pszZoneDi, &pdiList);
|
|
|
|
if (SUCCEEDED (hr) && pdiList)
|
|
{
|
|
LONG lIndex;
|
|
|
|
for (lIndex = 0; lIndex < pdiList -> Count; lIndex++)
|
|
{
|
|
hr = AddFactoryNode ((pdiList -> DeviceInterface)[lIndex], ppList);
|
|
if (FAILED (hr))
|
|
{
|
|
GFXUI_FreeList (ppList);
|
|
break;
|
|
}
|
|
}
|
|
|
|
gfxDestroyDeviceInterfaceList (pdiList);
|
|
}
|
|
else
|
|
{
|
|
GFXUI_FreeList (ppList);
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
HRESULT GFXUI_Properties (PGFXUI puiGFX, HWND hWndOwner)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (puiGFX && GFXUI_CanShowProperties (puiGFX) && IsWindow (hWndOwner))
|
|
{
|
|
ISpecifyPropertyPages* pISpecifyPropertyPages = NULL;
|
|
|
|
// Get the Vendor UI Property Pages Interface
|
|
hr = CoCreateInstance (puiGFX -> clsidUI, NULL, CLSCTX_INPROC_SERVER, IID_ISpecifyPropertyPages, (void**)&pISpecifyPropertyPages);
|
|
if (SUCCEEDED (hr) && !pISpecifyPropertyPages)
|
|
hr = E_UNEXPECTED;
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
CAUUID Pages;
|
|
ZeroMemory (&Pages, sizeof (Pages));
|
|
|
|
// Get the VendorUI Property Page CLSID's
|
|
hr = pISpecifyPropertyPages -> GetPages (&Pages);
|
|
if (SUCCEEDED (hr) && (Pages.cElems == 0 || !Pages.pElems))
|
|
hr = E_UNEXPECTED;
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
RECT rcWindow;
|
|
|
|
if (GetWindowRect (hWndOwner, &rcWindow))
|
|
{
|
|
TCHAR szCaption[MAX_PATH];
|
|
GFXDataObject DataObject (puiGFX -> Id);
|
|
IUnknown* punkDataObject = &DataObject;
|
|
|
|
// Load the VendorUI caption
|
|
LoadString (ghInstance, IDS_EFFECTS_PROPERTY_CAPTION, szCaption, sizeof (szCaption)/sizeof(TCHAR));
|
|
|
|
// Bring up the Vendor UI
|
|
hr = OleCreatePropertyFrame (hWndOwner, rcWindow.left + 10, rcWindow.top + 10,
|
|
szCaption, 1, &punkDataObject, Pages.cElems,
|
|
Pages.pElems, GetSystemDefaultLangID (),
|
|
0, NULL);
|
|
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
CoTaskMemFree (Pages.pElems);
|
|
}
|
|
|
|
pISpecifyPropertyPages -> Release ();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
UINT GetListSize (PGFXUI puiList)
|
|
{
|
|
|
|
UINT uiSize = 0;
|
|
PGFXUI puiListSeek = puiList;
|
|
|
|
while (puiListSeek)
|
|
{
|
|
puiListSeek = puiListSeek -> pNext;
|
|
uiSize++;
|
|
}
|
|
|
|
return uiSize;
|
|
|
|
}
|
|
|
|
|
|
HRESULT GFXUI_Apply (PPGFXUILIST ppListApply, PPGFXUI ppuiListDelete)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
PGFXUILIST pListApply = (ppListApply ? *ppListApply : NULL);
|
|
PGFXUI puiListDelete = (ppuiListDelete ? *ppuiListDelete : NULL);
|
|
|
|
if ((pListApply && pListApply -> puiList) || puiListDelete)
|
|
{
|
|
|
|
PGFXREMOVEREQUEST paGfxRemoveRequests = NULL;
|
|
PGFXMODIFYREQUEST paGfxModifyRequests = NULL;
|
|
PGFXADDREQUEST paGfxAddRequests = NULL;
|
|
ULONG cGfxRemoveRequests = 0;
|
|
ULONG cGfxModifyRequests = 0;
|
|
ULONG cGfxAddRequests = 0;
|
|
ULONG cApplyList = GetListSize (pListApply ? pListApply -> puiList : NULL);
|
|
ULONG cDeleteList = GetListSize (puiListDelete);
|
|
PGFXUI puiListSeek = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
// This function needs to create:
|
|
// - Deleted Array of GFXREMOVEREQUEST's
|
|
// - Modify Array of GFXMODIFYREQUEST's
|
|
// - Add Array of GFXADDREQUEST's
|
|
//
|
|
// The deleted array is fairly easy, just pull out the
|
|
// marked ones. With the remaining, we need to loop through
|
|
// them comparing order and create modify records as needed
|
|
// to modify their order (except for the add records where
|
|
// we must save the nessary order in the add request array).
|
|
// Then we create the add array (perhaps with the modify array)
|
|
// and fill in everything else (other than order).
|
|
//
|
|
// Then call GFX_BatchChange().
|
|
//
|
|
// Afterword, we need to update our list accordingly (i.e. delete
|
|
// nodes, update order, etc).
|
|
|
|
// Create our parameters
|
|
// Note: These buffers are really upper bounds on the memory we will need.
|
|
// We will count the actual requests we make and pass that value to
|
|
// the GFX function call.
|
|
if (0 < cDeleteList)
|
|
{
|
|
paGfxRemoveRequests = (PGFXREMOVEREQUEST) LocalAlloc (LPTR, sizeof (*paGfxRemoveRequests) * cDeleteList);
|
|
if (!paGfxRemoveRequests)
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
if (0 < cApplyList)
|
|
{
|
|
paGfxModifyRequests = (PGFXMODIFYREQUEST) LocalAlloc (LPTR, sizeof (*paGfxModifyRequests) * cApplyList);
|
|
paGfxAddRequests = (PGFXADDREQUEST) LocalAlloc (LPTR, sizeof (*paGfxAddRequests) * cApplyList);
|
|
if (!paGfxModifyRequests || !paGfxAddRequests)
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
UINT uiIndx;
|
|
DWORD dwOrder = 0;
|
|
|
|
// Create the remove parameter
|
|
puiListSeek = puiListDelete;
|
|
for (uiIndx = 0; uiIndx < cDeleteList; uiIndx++)
|
|
{
|
|
// Make sure this is created before we ask to delete it.
|
|
// (It may be an AddNode that was deleted before creation).
|
|
if (puiListSeek -> nFlags & GFX_CREATED)
|
|
{
|
|
(paGfxRemoveRequests + cGfxRemoveRequests) -> IdToRemove = puiListSeek -> Id;
|
|
(paGfxRemoveRequests + cGfxRemoveRequests) -> Error = S_OK;
|
|
cGfxRemoveRequests++;
|
|
}
|
|
puiListSeek = puiListSeek -> pNext;
|
|
}
|
|
|
|
// Create the modify and add parameters
|
|
puiListSeek = pListApply ? pListApply -> puiList : NULL;
|
|
for (uiIndx = 0; uiIndx < cApplyList; uiIndx++)
|
|
{
|
|
if (puiListSeek -> nFlags & GFX_ADD)
|
|
{
|
|
(paGfxAddRequests + cGfxAddRequests) -> ZoneFactoryDi = pListApply -> pszZoneDi;
|
|
(paGfxAddRequests + cGfxAddRequests) -> GfxFactoryDi = puiListSeek -> pszFactoryDi;
|
|
(paGfxAddRequests + cGfxAddRequests) -> Type = pListApply -> dwType;
|
|
(paGfxAddRequests + cGfxAddRequests) -> Order = dwOrder++;
|
|
(paGfxAddRequests + cGfxAddRequests) -> NewId = 0;
|
|
(paGfxAddRequests + cGfxAddRequests) -> Error = S_OK;
|
|
cGfxAddRequests++;
|
|
}
|
|
else
|
|
{
|
|
if (puiListSeek -> nFlags & GFX_CREATED)
|
|
{
|
|
// We only need to add modify records for GFX'es
|
|
// that are no longer in order.
|
|
if (puiListSeek -> Order < dwOrder)
|
|
{
|
|
(paGfxModifyRequests + cGfxModifyRequests) -> IdToModify = puiListSeek -> Id;
|
|
(paGfxModifyRequests + cGfxModifyRequests) -> NewOrder = dwOrder++;
|
|
(paGfxModifyRequests + cGfxModifyRequests) -> Error = S_OK;
|
|
cGfxModifyRequests++;
|
|
}
|
|
else
|
|
dwOrder = (puiListSeek -> Order + 1);
|
|
}
|
|
else
|
|
{
|
|
// Bogus list entry, abort everything!
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
}
|
|
puiListSeek = puiListSeek -> pNext;
|
|
}
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
#ifdef ADDGFX
|
|
hr = gfxBatchChange (paGfxRemoveRequests, cGfxRemoveRequests,
|
|
paGfxModifyRequests, cGfxModifyRequests,
|
|
paGfxAddRequests, cGfxAddRequests);
|
|
#endif // ADDGFX
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
PGFXMODIFYREQUEST paGfxModifySeek = paGfxModifyRequests;
|
|
PGFXADDREQUEST paGfxAddSeek = paGfxAddRequests;
|
|
|
|
// Update the passed arrays
|
|
FreeListNodes (ppuiListDelete);
|
|
|
|
puiListSeek = pListApply ? pListApply -> puiList : NULL;
|
|
for (uiIndx = 0; uiIndx < cApplyList; uiIndx++)
|
|
{
|
|
// Update the list items.
|
|
if (puiListSeek -> nFlags & GFX_ADD)
|
|
{
|
|
// Update the newly create GFX
|
|
puiListSeek -> nFlags = GFX_CREATED;
|
|
puiListSeek -> Id = paGfxAddSeek -> NewId;
|
|
puiListSeek -> Type = paGfxAddSeek -> Type;
|
|
puiListSeek -> Order = paGfxAddSeek -> Order;
|
|
paGfxAddSeek++;
|
|
}
|
|
else // must be (puiListSeek -> nFlags & GFX_CREATED)
|
|
{
|
|
// Update the order
|
|
puiListSeek -> Order = paGfxModifySeek -> NewOrder;
|
|
paGfxModifySeek++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Free parameters
|
|
if (paGfxRemoveRequests)
|
|
LocalFree (paGfxRemoveRequests);
|
|
if (paGfxModifyRequests)
|
|
LocalFree (paGfxModifyRequests);
|
|
if (paGfxAddRequests)
|
|
LocalFree (paGfxAddRequests);
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
// Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
PTCHAR GetInterfaceName (DWORD dwMixerID)
|
|
{
|
|
MMRESULT mmr;
|
|
ULONG cbSize=0;
|
|
TCHAR *szInterfaceName=NULL;
|
|
|
|
//Query for the Device interface name
|
|
mmr = mixerMessage(HMIXER_INDEX(dwMixerID), DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&cbSize, 0L);
|
|
if(MMSYSERR_NOERROR == mmr)
|
|
{
|
|
szInterfaceName = (TCHAR *)GlobalAllocPtr(GHND, (cbSize+1)*sizeof(TCHAR));
|
|
if(!szInterfaceName)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
mmr = mixerMessage(HMIXER_INDEX(dwMixerID), DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)szInterfaceName, cbSize);
|
|
if(MMSYSERR_NOERROR != mmr)
|
|
{
|
|
GlobalFreePtr(szInterfaceName);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return szInterfaceName;
|
|
}
|
|
|
|
|
|
BOOL GFXUI_CanShowProperties (PGFXUI puiGFX)
|
|
{
|
|
return (puiGFX && (puiGFX -> nFlags & GFX_CREATED) && (puiGFX -> clsidUI != GUID_NULL));
|
|
}
|
|
|
|
|
|
HRESULT CreateNode (PCWSTR pszName, PCWSTR pszGfxFactoryDi, PPGFXUI ppNode)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppNode)
|
|
{
|
|
// Create node
|
|
PGFXUI pNode = (PGFXUI) LocalAlloc (LPTR, sizeof (GFXUI));
|
|
hr = S_OK;
|
|
|
|
if (pNode)
|
|
{
|
|
ZeroMemory (pNode, sizeof (GFXUI));
|
|
|
|
// Create the strings
|
|
if (pszName)
|
|
{
|
|
pNode -> pszName = (PWSTR) LocalAlloc (LPTR, lstrlen (pszName)*2+2);
|
|
if (pNode -> pszName)
|
|
wcscpy (pNode -> pszName, pszName);
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// If there is no name, get it from the factory
|
|
pNode -> pszName = NULL;
|
|
if (pszGfxFactoryDi)
|
|
hr = GetFriendlyName (pszGfxFactoryDi, &(pNode -> pszName));
|
|
}
|
|
|
|
if (SUCCEEDED (hr) && pszGfxFactoryDi)
|
|
{
|
|
pNode -> pszFactoryDi = (PWSTR) LocalAlloc (LPTR, lstrlen (pszGfxFactoryDi)*2+2);
|
|
if (pNode -> pszFactoryDi)
|
|
wcscpy (pNode -> pszFactoryDi, pszGfxFactoryDi);
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED (hr))
|
|
// Return node
|
|
*ppNode = pNode;
|
|
else
|
|
// Free node
|
|
FreeNode (&pNode);
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// This function creates an "addable" GFXUI element that will be able
|
|
// to create a new GFX when you call GFXUI_Apply() with this new element
|
|
// in the list.
|
|
HRESULT GFXUI_CreateAddGFX (PPGFXUI ppuiGFXAdd, PGFXUI puiGFXSource)
|
|
{
|
|
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppuiGFXAdd && puiGFXSource)
|
|
{
|
|
*ppuiGFXAdd = NULL;
|
|
|
|
hr = CreateNode (puiGFXSource -> pszName,
|
|
puiGFXSource -> pszFactoryDi, ppuiGFXAdd);
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
if (*ppuiGFXAdd)
|
|
{
|
|
// Indicate that this is a new 'Add' node.
|
|
(*ppuiGFXAdd) -> nFlags = GFX_ADD;
|
|
}
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|