public static void WriteDeviceConfig <T>(this PXCMCapture.Device device, T metaData, CaptureMode captureMode) where T : DS4Meta
        {
            int backLightCompensation = device.QueryColorBackLightCompensation();
            int brightness            = device.QueryColorBrightness();
            int contrast = device.QueryColorContrast();

            PXCMRangeF32 depthRange    = device.QueryDepthSensorRange();
            float        minDepthRange = depthRange.min;
            float        maxDepthRange = depthRange.max;

            ushort confidenceThreshold = device.QueryDepthConfidenceThreshold();

            bool autoExposure  = device.QueryColorAutoExposure();
            bool autoPowerline = device.QueryColorAutoPowerLineFrequency();

            int colorExposure = device.QueryColorExposure();
            int colorGain     = device.QueryColorGain();

            float depthExposure = device.QueryDSLeftRightExposure();
            int   depthGain     = device.QueryDSLeftRightGain();

            var  depthExposureInfo = device.QueryDSLeftRightExposureInfo();
            bool depthAutoExposure = depthExposureInfo.automatic;

            metaData.DeviceConfig.BackLightCompensation = backLightCompensation;
            metaData.DeviceConfig.minDepthRange         = minDepthRange;
            metaData.DeviceConfig.maxDepthRange         = maxDepthRange;
            metaData.DeviceConfig.colorAutoExposure     = autoExposure;
            metaData.DeviceConfig.depthAutoExposure     = depthAutoExposure;

            metaData.DeviceConfig.ColorExposure = (float)colorExposure;
            metaData.DeviceConfig.ColorGain     = colorGain;

            if (metaData.DeviceConfig.DepthExposure == 0)
            {
                metaData.DeviceConfig.DepthExposure = 33.3f;
                metaData.DeviceConfig.DepthGain     = 1;
            }
            //{
            //    BackLightCompensation = backLightCompensation,
            //    Brightness = brightness,
            //    Contrast = contrast,
            //    minDepthRange = minDepthRange,
            //    maxDepthRange = maxDepthRange,
            //    confidenceThreshold = confidenceThreshold,
            //    autoPowerline = autoPowerline,

            //    colorAutoExposure = autoExposure,
            //    depthAutoExposure = depthAutoExposure,

            //    ColorExposure = (float)colorExposure,
            //    ColorGain = colorGain,
            //    DepthExposure = depthExposure,
            //    DepthGain = depthGain
            //};

            metaData.CaptureMode = captureMode.ToString().ToLower();
        }
        public void StreamColorDepth(String scanType) /* Stream Color and Depth Synchronously or Asynchronously */
        {
            bool sts = true;

            PXCM3DScan.Configuration scan_config = new PXCM3DScan.Configuration();
            String statusString;

            /* Create an instance of the PXCSenseManager interface */
            PXCMSenseManager pp = PXCMSenseManager.CreateInstance();

            if (pp == null)
            {
                form.UpdateStatus("Failed to create sense manager");
                return;
            }
            if (pp.captureManager == null)
            {
                form.UpdateStatus("Capture manager does not exist");
                return;
            }
            if (!form.IsModeLive())
            {
                pp.captureManager.SetFileName(form.GetFileName(), form.IsModeRecord());
            }

            /* Set Input Source */
            PXCMCapture.DeviceInfo dinfo2 = form.GetCheckedDevice();
            if (form.IsModeLive() || form.IsModeRecord())
            {
                pp.captureManager.FilterByDeviceInfo(dinfo2);
            }

            if (form.IsModeRecord())
            {
                // Delay recording frames until the scan starts
                pp.captureManager.SetPause(true);
            }
            else if (!form.IsModeLive())
            {
                // Disable real-time mode if we are playing back a file
                // to ensure that frames are not skipped.
                pp.captureManager.SetRealtime(false);
            }

            /* Set Color & Depth Resolution */
            PXCMCapture.Device.StreamProfile cinfo = form.GetColorConfiguration();
            if (cinfo.imageInfo.format != 0)
            {
                Single cfps = cinfo.frameRate.max;
                pp.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR, cinfo.imageInfo.width, cinfo.imageInfo.height, cfps);
            }

            PXCMCapture.Device.StreamProfile dinfo = form.GetDepthConfiguration();
            if (dinfo.imageInfo.format != 0)
            {
                Single dfps = dinfo.frameRate.max;
                pp.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_DEPTH, dinfo.imageInfo.width, dinfo.imageInfo.height, dfps);
            }

            /* Initialization */
            FPSTimer timer = new FPSTimer(form);

            if (form.IsModeLive())
            {
                form.UpdateStatus("Initializing...");
            }
            /* Enable the 3D Scan video module */
            pxcmStatus result = pp.Enable3DScan();

            if (result != pxcmStatus.PXCM_STATUS_NO_ERROR)
            {
                pp.Close();
                pp.Dispose();
                form.UpdateStatus("Enable3DScan() returned " + result);
                return;
            }

            /* Initialize the camera system */
            result = pp.Init();
            form.UpdateStatus("");
            device = pp.captureManager.device;
            if (result >= pxcmStatus.PXCM_STATUS_NO_ERROR && device != null)
            {
                bool bAutoExpAndWBChanged     = false;
                bool bAutoExposureEnabled     = true;
                bool bAutoWhiteBalanceEnabled = true;

                /* Setup the scanning configuration */
                if (scanType == "Object")
                {
                    scan_config.mode = PXCM3DScan.ScanningMode.OBJECT_ON_PLANAR_SURFACE_DETECTION;
                }
                else if (scanType == "Face")
                {
                    scan_config.mode = PXCM3DScan.ScanningMode.FACE;
                }
                else if (scanType == "Body")
                {
                    scan_config.mode = PXCM3DScan.ScanningMode.BODY;
                }
                else if (scanType == "Head")
                {
                    scan_config.mode = PXCM3DScan.ScanningMode.HEAD;
                }
                else if (scanType == "Full")
                {
                    scan_config.mode = PXCM3DScan.ScanningMode.VARIABLE;
                }

                /* Select the Targeting Options */
                scan_config.options = PXCM3DScan.ReconstructionOption.NONE;
                if (form.isSolidificationSelected())
                {
                    scan_config.options
                        |= (PXCM3DScan.ReconstructionOption.SOLIDIFICATION);
                }
                if (form.isTextureSelected())
                {
                    scan_config.options
                        |= (PXCM3DScan.ReconstructionOption.TEXTURE);
                }
                if (form.isLandmarksSelected())
                {
                    scan_config.options
                        |= (PXCM3DScan.ReconstructionOption.LANDMARKS);
                }
                //scan_config.useMarker = form.isUseMarkerChecked();

                scan_config.flopPreviewImage = form.isFlopPreviewImageSelected();

                /* Try to initialize the scanning system */
                PXCM3DScan scan = pp.Query3DScan();
                sts = false;
                if (scan == null)
                {
                    form.UpdateStatus("3DScan module not found.");
                }
                else
                {
                    result = scan.SetConfiguration(scan_config);
                    if (result < pxcmStatus.PXCM_STATUS_NO_ERROR)
                    {
                        scan.Dispose();

                        // Show the configuration related error code
                        switch (result)
                        {
                        case pxcmStatus.PXCM_STATUS_FEATURE_UNSUPPORTED:
                            form.UpdateStatus("Configuration not supported.");
                            break;

                        case pxcmStatus.PXCM_STATUS_ITEM_UNAVAILABLE:
                            form.UpdateStatus("Face module not found.");
                            break;

                        default:
                            form.UpdateStatus("SetConfiguration returned an error.");
                            break;
                        }
                    }
                    else
                    {
                        sts = true;
                    }
                }

                // Conditionally finish the initialization and enter the main loop
                if (sts == true)
                {
                    // Subscribe to recieve range and tracking alerts
                    scan.Subscribe(OnAlert);

                    Projection projection = new Projection(
                        pp.session, device, dinfo.imageInfo);

                    Boolean bScanning        = false;
                    Boolean bPlaybackStarted = false;
                    form.Invoke(new Action(() => form.SetButtonState(sample3dscan.cs.MainForm.ButtonState.Ce_SSd)));

                    while (form.reconstruct_requested || !form.GetStopState())
                    {
                        if (form.GetScanRequested()) /* one time latch */
                        {
                            form.Invoke(new Action(() => form.SetScanRequested(false)));

                            // Delay recording frames until the start of the scan is requested
                            if (form.IsModeRecord())
                            {
                                pp.captureManager.SetPause(false);
                            }

                            // If the max tri/vert controls are enabled,
                            // use the set values. Otherwise, disabled decimation
                            // by setting the values to zero.

                            /*
                             * scan_config.maxTriangles = form.getMaxTrianglesEnabledChecked()
                             *  ? form.getMaxTriangles() : 0;
                             * scan_config.maxVertices = form.getMaxVerticesEnabledChecked()
                             *  ? form.getMaxVertices() : 0;
                             */
                            // Request that the scan starts as soon as possible
                            scan_config.startScan = true;
                            scan.SetConfiguration(scan_config);

                            /* Update the status bar to help users understand what the detector is looking for */
                            if (form.IsModeLive())
                            {
                                if (scan_config.mode == PXCM3DScan.ScanningMode.OBJECT_ON_PLANAR_SURFACE_DETECTION)
                                {
                                    form.UpdateStatus("Object not detected. Place object on flat surface in center of view.");
                                }
                            }
                        }
                        else if (form.reconstruct_requested)
                        {
                            sts = SaveMesh(scan);
                        }

                        /* Get preview image from the 3D Scan video module */
                        if (!form.GetStopState())
                        {
                            /* Wait until a frame is ready: Synchronized or Asynchronous */
                            if (pp.AcquireFrame() < pxcmStatus.PXCM_STATUS_NO_ERROR)
                            {
                                projection.Dispose();
                                if (!form.IsModeLive())
                                {
                                    form.Invoke(new Action(() => form.EndScan()));
                                    sts = SaveMesh(scan);
                                }
                                break;
                            }

                            /* Get preview image from the 3D Scan video module */
                            PXCMImage preview_image = scan.AcquirePreviewImage();
                            pp.ReleaseFrame();

                            /* Display Image and Status */
                            if (preview_image != null)
                            {
                                form.SetBitmap(preview_image);

                                if (scan.IsScanning())
                                {
                                    statusString = "Scanning";
                                    timer.Tick(statusString + " ");
                                    if (bScanning == false) // Lazy initializer
                                    {
                                        bScanning = true;   // One way latch

                                        // Once the scanning process starts, we want to enable the Reconstruct button
                                        form.Invoke(new Action(() => form.SetButtonState(sample3dscan.cs.MainForm.ButtonState.Ce_ESe)));

                                        // Object, head and body scanning with a rear facing camera involves walking
                                        // around the target, which effectivly exposes the camera to the full
                                        // environment, similar to a panorama. To avoid undesirable color
                                        // inconsistencies (realted to the response of the auto-exposure/wb changes),
                                        // it usually works best to disable them.
                                        // Note that these property changes are restored (below).
                                        if (device.deviceInfo.orientation
                                            == PXCMCapture.DeviceOrientation.DEVICE_ORIENTATION_REAR_FACING &&
                                            scan_config.mode != PXCM3DScan.ScanningMode.FACE &&
                                            form.IsModeLive())
                                        {
                                            bAutoExpAndWBChanged = true;
                                            bAutoExposureEnabled = device.QueryColorAutoExposure();
                                            device.SetColorAutoExposure(false);
                                            bAutoWhiteBalanceEnabled = device.QueryColorAutoWhiteBalance();
                                            device.SetColorAutoWhiteBalance(false);
                                        }
                                    }
                                }
                                else
                                {
                                    if (!form.IsModeLive() && !form.IsModeRecord()) // In playback mode, automatically request the scan
                                    {
                                        if (bPlaybackStarted == false)              // Lazy initializer
                                        {
                                            bPlaybackStarted    = true;             // One way latch
                                            form.scan_requested = true;
                                            form.Invoke(new Action(() => form.StartScanning(false)));
                                            form.Invoke(new Action(() => form.SetButtonState(sample3dscan.cs.MainForm.ButtonState.Ce_ESe)));
                                        }
                                    }
                                    else
                                    {
                                        if (!form.GetStopState())
                                        {
                                            if (isScanReady(form.landmarksChecked()))
                                            {
                                                form.Invoke(new Action(() => form.EnableReconstruction(true)));
                                            }
                                            else
                                            {
                                                form.Invoke(new Action(() => form.EnableReconstruction(false)));
                                            }
                                        }
                                    }
                                }
                                preview_image.Dispose();
                            }
                        }
                    }
                    projection.Dispose();
                    scan.Dispose();
                }
                // Restore the default camera properties
                if (bAutoExpAndWBChanged)
                {
                    device.SetColorAutoExposure(bAutoExposureEnabled);
                    device.SetColorAutoWhiteBalance(bAutoWhiteBalanceEnabled);
                }

                device.Dispose();
                device = null;
            }
            else
            {
                try { form.UpdateStatus(result + ""); }
                catch { }
                sts = false;
            }

            if (sts)
            {
                try { form.UpdateStatus(""); }
                catch { }
            }

            pp.Close();
            pp.Dispose();

            try { form.Invoke(new Action(() => form.ResetStop())); }
            catch { }
        }