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; }