📄 codec.c
字号:
// open _driver instance_. Do not store/create instance data that must
// be unique for each stream in this function. See the acmdStreamOpen
// function for information on conversion streams.
//
// Arguments:
// HDRVR hdrvr: Driver handle that will be returned to caller of the
// OpenDriver function. Normally, this will be the ACM--but this is
// not guaranteed. For example, if an ACM driver is implemented within
// a waveform driver, then the driver will be opened by both MMSYSTEM
// and the ACM.
//
// LPACMDRVOPENDESC paod: Open description defining how the ACM driver
// is being opened. This argument may be NULL--see the comments below
// for more information.
//
// Return (LRESULT):
// The return value is non-zero if the open is successful. A zero
// return signifies that the driver cannot be opened.
//
//--------------------------------------------------------------------------;
LRESULT FNLOCAL acmdDriverOpen
(
HDRVR hdrvr,
LPACMDRVOPENDESC paod
)
{
PDRIVERINSTANCE pdi;
//
// the [optional] open description that is passed to this driver can
// be from multiple 'managers.' for example, AVI looks for installable
// drivers that are tagged with 'vidc' and 'vcap'. we need to verify
// that we are being opened as an Audio Compression Manager driver.
//
// if paod is NULL, then the driver is being opened for some purpose
// other than converting (that is, there will be no stream open
// requests for this instance of being opened). the most common case
// of this is the Control Panel's Drivers option checking for config
// support (DRV_[QUERY]CONFIGURE).
//
// we want to succeed this open, but be able to know that this
// open instance is bogus for creating streams. for this purpose we
// leave most of the members of our instance structure that we
// allocate below as zero...
//
if (NULL != paod)
{
//
// refuse to open if we are not being opened as an ACM driver.
// note that we do NOT modify the value of paod->dwError in this
// case.
//
if (ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC != paod->fccType)
{
return (0L);
}
}
//
// we are being opened as an installable driver--we can allocate some
// instance data to be returned in dwId argument of the DriverProc;
// or simply return non-zero to succeed the open.
//
// this driver allocates a small instance structure. note that we
// rely on allocating the memory as zero-initialized!
//
pdi = (PDRIVERINSTANCE)LocalAlloc(LPTR, sizeof(*pdi));
if (NULL == pdi)
{
//
// if this open attempt was as an ACM driver, then return the
// reason we are failing in the open description structure..
//
if (NULL != paod)
{
paod->dwError = MMSYSERR_NOMEM;
}
//
// fail to open
//
return (0L);
}
//
// fill in our instance structure... note that this instance data
// can be anything that the ACM driver wishes to maintain the
// open driver instance. this data should not contain any information
// that must be maintained per open stream since multiple streams
// can be opened on a single driver instance.
//
// also note that we do _not_ check the version of the ACM opening
// us (paod->dwVersion) to see if it is at least new enough to work
// with this driver (for example, if this driver required Version 3.0
// of the ACM and a Version 2.0 installation tried to open us). the
// reason we do not fail is to allow the ACM to get the driver details
// which contains the version of the ACM that is _required_ by this
// driver. the ACM will examine that value (in padd->vdwACM) and
// do the right thing for this driver... like not load it and inform
// the user of the problem.
//
pdi->hdrvr = hdrvr;
pdi->hinst = GetDriverModuleHandle(hdrvr); // Module handle.
pdi->fHelpRunning = FALSE;
if (NULL != paod)
{
pdi->fnDriverProc = NULL;
pdi->fccType = paod->fccType;
pdi->vdwACM = paod->dwVersion;
pdi->fdwOpen = paod->dwFlags;
pdi->hkey = NULL; // This is important!
paod->dwError = MMSYSERR_NOERROR;
}
//
// Get config info for this driver. If we're not passed an
// an ACMDRVOPENDESC structure then we'll assume we are being
// opened for configuration and will put off getting the config
// info until we receive the DRV_CONFIGURE message. Otherwise we
// get the config info now using the alias passed through the
// ACMDRVOPENDESC structure.
//
if (NULL != paod)
{
#if defined(WIN32) && !defined(UNICODE)
//
// We must translate the UNICODE alias name to an ANSI version
// that we can use.
//
LPSTR lpstr;
int iLen;
//
// Calculate required length without calling UNICODE APIs or CRT.
//
iLen = WideCharToMultiByte( GetACP(), 0, paod->pszAliasName,-1,
NULL, 0, NULL, NULL );
lpstr = (LPSTR)GlobalAlloc(GPTR, iLen);
if (NULL != lpstr)
{
WideCharToMultiByte( GetACP(), 0, paod->pszAliasName, iLen,
lpstr, iLen, NULL, NULL );
}
acmdDriverConfigInit(pdi, lpstr); // Note: OK to pass lpstr==NULL
if (NULL != lpstr)
{
GlobalFree((HGLOBAL)lpstr);
}
#else
acmdDriverConfigInit(pdi, paod->pszAliasName);
#endif
}
//
// non-zero return is success for DRV_OPEN
//
return ((LRESULT)pdi);
} // acmdDriverOpen()
//--------------------------------------------------------------------------;
//
// LRESULT acmdDriverClose
//
// Description:
// This function handles the DRV_CLOSE message for the ACM driver. The
// driver receives a DRV_CLOSE message for each succeeded DRV_OPEN
// message (see acmdDriverOpen). The driver will only receive a close
// message for _successful_ opens.
//
// Arguments:
// PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
// This structure is [optionally] allocated during the DRV_OPEN message
// which is handled by the acmdDriverOpen function.
//
// Return (LRESULT):
// The return value is non-zero if the open instance can be closed.
// A zero return signifies that the ACM driver instance could not be
// closed.
//
// NOTE! It is _strongly_ recommended that the driver never fail to
// close. Note that the ACM will never allow a driver instance to
// be closed if there are open streams. An ACM driver does not need
// to check for this case.
//
//--------------------------------------------------------------------------;
LRESULT FNLOCAL acmdDriverClose
(
PDRIVERINSTANCE pdi
)
{
//
// Release the registry key, if we allocated one.
//
if( NULL != pdi->hkey )
{
(void)RegCloseKey( pdi->hkey );
}
//
// check to see if we allocated instance data. if we did not, then
// immediately succeed.
//
if (NULL != pdi)
{
//
// close down the driver instance. this driver simply needs
// to free the instance data structure... note that if this
// 'free' fails, then this ACM driver probably trashed its
// heap; assume we didn't do that.
//
LocalFree((HLOCAL)pdi);
}
//
// non-zero return is success for DRV_CLOSE
//
return (1L);
} // acmdDriverClose()
//--------------------------------------------------------------------------;
//
// LRESULT acmdDriverConfigure
//
// Description:
// This function is called to handle the DRV_[QUERY]CONFIGURE messages.
// These messages are for 'configuration' support of the driver.
// Normally this will be for 'hardware'--that is, a dialog should be
// displayed to configure ports, IRQ's, memory mappings, etc if it
// needs to. However, a software only ACM driver may also require
// configuration for 'what is real time' or other quality vs time
// issues.
//
// The most common way that these messages are generated under Win 3.1
// and NT Product 1 is from the Control Panel's Drivers option. Other
// sources may generate these messages in future versions of Windows.
//
// Arguments:
// PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
// This structure is [optionally] allocated during the DRV_OPEN message
// which is handled by the acmdDriverOpen function.
//
// HWND hwnd: Handle to parent window to use when displaying the
// configuration dialog box. An ACM driver is _required_ to display a
// modal dialog box using this hwnd argument as the parent. This
// argument may be (HWND)-1 which tells the driver that it is only
// being queried for configuration support.
//
// LPDRVCONFIGINFO pdci: Pointer to optional DRVCONFIGINFO structure.
// If this argument is NULL, then the ACM driver should invent its own
// storage location.
//
// Return (LRESULT):
// If the driver is being 'queried' for configuration support (that is,
// hwnd == (HWND)-1), then non-zero should be returned specifying
// the driver does support a configuration dialog--or zero should be
// returned specifying that no configuration dialog is supported.
//
// If the driver is being called to display the configuration dialog
// (that is, hwnd != (HWND)-1), then one of the following values
// should be returned:
//
// DRVCNF_CANCEL (0x0000): specifies that the dialog was displayed
// and canceled by the user. this value should also be returned if
// no configuration information was modified.
//
// DRVCNF_OK (0x0001): specifies that the dialog was displayed and
// the user pressed OK. This value should be returned even if the
// user didn't change anything - otherwise, the driver may not
// install properly.
//
// DRVCNF_RESTART (0x0002): specifies that the dialog was displayed
// and some configuration information was changed that requires
// Windows to be restarted before the changes take affect. the driver
// should remain configured with current values until the driver
// has been 'rebooted'.
//
//--------------------------------------------------------------------------;
LRESULT FNLOCAL acmdDriverConfigure
(
PDRIVERINSTANCE pdi,
HWND hwnd,
LPDRVCONFIGINFO pdci
)
{
INT_PTR n;
//
// first check if we are only being queried for configuration
// support. if hwnd == (HWND)-1 then we are being queried and should
// return zero for 'not supported' and non-zero for 'supported'.
//
if ((HWND)-1 == hwnd)
{
//
// this ACM driver supports a configuration dialog box, so
// return non-zero...
//
return (1L);
}
//
// we are being asked to bring up our configuration dialog. if this
// driver supports a configuration dialog box, then after the dialog
// is dismissed we must return one of the following values:
//
// DRVCNF_CANCEL (0x0000): specifies that the dialog was displayed
// and canceled by the user. this value should also be returned if
// no configuration information was modified.
//
// DRVCNF_OK (0x0001): specifies that the dialog was displayed and
// the user pressed OK. This value should be returned even if the
// user didn't change anything - otherwise, the driver may not
// install properly.
//
// DRVCNF_RESTART (0x0002): specifies that the dialog was displayed
// and some configuration information was changed that requires
// Windows to be restarted before the changes take affect. the driver
// should remain configured with current values until the driver
// has been 'rebooted'.
//
//
if (NULL == pdci)
{
//
// !!!
//
return (DRVCNF_CANCEL);
}
pdi->pdci = pdci;
//
// We may not have our config info yet if the driver has only been
// opened specifically for configuration. So, read our configuration
// using the alias passed in the DRVCONFIGINFO structure passed
// through the DRV_CONFIGURE message
//
#if (defined(WIN32) && !defined(UNICODE))
{
//
// We must translate the UNICODE alias name to an ANSI version
// that we can use.
//
LPSTR lpstr;
int iLen;
//
// Calculate required length without calling UNICODE APIs or CRT.
//
iLen = WideCharToMultiByte( GetACP(), 0, pdci->lpszDCIAliasName, -1,
NULL, 0, NULL, NULL );
lpstr = (LPSTR)LocalAlloc(LPTR, iLen);
if (NULL != lpstr)
{
WideCharToMultiByte( GetACP(), 0, pdci->lpszDCIAliasName, iLen,
lpstr, iLen, NULL, NULL );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -