The following code fragment illustrates the routines the sample device driver uses to handle the DRV_OPEN and DRV_CLOSE messages. This device driver supports only one instance of each video channel.
PCHANNEL NEAR PASCAL VideoOpen(LPVIDEO_OPEN_PARMS lpOpenParms)
{
PCHANNEL pChannel;
LPDEVICE_INIT lpDI = &devInit;
LPDWORD lpdwError = &lpOpenParms->dwError;
DWORD dwFlags = lpOpenParms->dwFlags;
// We're passed a DevNode in the VIDEO_OPEN_PARMS, which we'll pass
// down to the VxD. This is really only needed when multiple
// instances of identical hardware are installed, and we want to
// let the application select which instance to use.
// The VxD must then compare the DevNode passed in with its internal
// list of DevNodes and use the corresponding hardware.
lpDI->dnDevNode = lpOpenParms->dnDevNode;
//
// if this is the very first open then init the hardware.
//
AuxDebugEx (2, DEBUGLINE "VideoOpen, RefCount = %d\r\n", gwDriverUsage);
*lpdwError = DV_ERR_OK;
// Only initalize the first time opened
if (!fDeviceInitialized) {
// Acquire use of the capture hardware
if (!(AcquireVXP500( gpVxDEntry, &devInit ))) {
D1("AcquireFailed");
*lpdwError = DV_ERR_NOTDETECTED;
}
// Perform hardware initialization
if (!HardwareInit(lpDI)) {
*lpdwError = DV_ERR_NOTDETECTED;
return NULL;
}
ConfigGetSettings(); // Get global hue, sat, channel, zoom.
if (ConfigInit(lpDI)) {
if (TransInit()) { // Allocate the YUV conversion tables
*lpdwError = DV_ERR_NOMEM;
} else
fDeviceInitialized = TRUE;
} else
*lpdwError = DV_ERR_NOMEM;
if (*lpdwError != DV_ERR_OK) {
TransFini();
HardwareFini();
return NULL;
}
} // end if this is the first open.
// get instance memory
pChannel = (PCHANNEL)LocalAlloc (LPTR, sizeof(CHANNEL));
if (pChannel == NULL)
return (PCHANNEL) NULL;
//
// make sure the channel is not already in use
//
switch (dwFlags &
(VIDEO_EXTERNALIN | VIDEO_EXTERNALOUT | VIDEO_IN | VIDEO_OUT)) {
case VIDEO_EXTERNALIN:
if (gwCaptureUsage >= MAX_CAPTURE_CHANNELS)
goto error;
gwCaptureUsage++;
break;
case VIDEO_EXTERNALOUT:
if ( gwDisplayUsage >= MAX_DISPLAY_CHANNELS)
goto error;
gwDisplayUsage++;
break;
case VIDEO_IN:
if ( gwVideoInUsage >= MAX_IN_CHANNELS)
goto error;
gwVideoInUsage++;
break;
case VIDEO_OUT:
if ( gwVideoOutUsage >= MAX_OUT_CHANNELS)
goto error;
gwVideoOutUsage++;
break;
default:
goto error;
}
//
// Now that the hardware is allocated init our instance struct.
//
pChannel->fccType = OPEN_TYPE_VCAP;
pChannel->dwOpenType = (dwFlags
&(VIDEO_EXTERNALIN | VIDEO_EXTERNALOUT | VIDEO_IN | VIDEO_OUT));
pChannel->dwOpenFlags = dwFlags;
pChannel->lpVHdr = NULL;
pChannel->dwError = 0L;
gwDriverUsage++;
return pChannel;
error:
if (pChannel)
LocalFree((HLOCAL)pChannel);
*lpdwError = DV_ERR_ALLOCATED;
return NULL;
}
The following example shows the function used to close the example video capture device driver:
DWORD NEAR PASCAL VideoClose(PCHANNEL pChannel)
{
// Decrement the channel open counters
switch (pChannel->dwOpenType) {
case VIDEO_EXTERNALIN:
gwCaptureUsage--;
break;
case VIDEO_EXTERNALOUT:
gwDisplayUsage--;
break;
case VIDEO_IN:
// If started, or buffers in the queue,
// don't let the close happen
if (gfVideoInStarted || lpVHdrFirst)
return DV_ERR_STILLPLAYING;
gwVideoInUsage--;
break;
case VIDEO_OUT:
gwVideoOutUsage--;
break;
default:
break;
}
gwDriverUsage--; // Decrement overall driver useage count.
if (gwDriverUsage == 0) {
HardwareFini(); // Shut down the device.
TransFini(); // Free translation tables.
ReleaseVXP500( gpVxDEntry, &devInit );
fDeviceInitialized = FALSE;
}
// Free the instance data.
LocalFree((HLOCAL)pChannel);
return DV_ERR_OK;
}