www.pudn.com > DalsaNetlink.rar > CyAcquisitionPage.cpp


 
// CyAcquisitionPage.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "CyApp.h" 
#include "CyAcquisitionPage.h" 
#include "CySignalDialog.h" 
#include "ColorAdjustmentDialog.h" 
#include "CyPerfMonitor.h" 
#include "CyMovieSelectionDialog.h" 
#include "CyVideoCompressor.h" 
#include "CyInterPacketDelayDialog.h" 
 
#include  
#include  
#include  
 
#include  
#include  
using namespace std; 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
#define ACQ_MODE_SINGLE_GRAB		 0 
#define ACQ_MODE_CONTINUOUS_GRAB	 1 
#define ACQ_MODE_SINGLE_PLAYBACK	 2 
#define ACQ_MODE_CONTINUOUS_PLAYBACK 3 
#define ACQ_MODE_RECORDING			 4 
 
static void FormatInteger( unsigned long aValue, CString& aResult ) 
{ 
    aResult = ""; 
    CString lTemp; 
 
    while ( aValue / 1000 ) 
    { 
        unsigned long aCurrent = aValue % 1000; 
         
        if ( aResult.GetLength() > 0 ) 
        { 
            lTemp.Format( "%03u,", aCurrent ); 
        } 
        else 
        { 
            lTemp.Format( "%03u", aCurrent ); 
        } 
 
        aResult.Insert( 0, lTemp ); 
 
        // go to the next level 
        aValue /= 1000; 
    } 
 
    // we are left with the last  
    if ( aResult.GetLength() > 0 ) 
    { 
        lTemp.Format( "%u,", aValue ); 
    } 
    else 
    { 
        lTemp.Format( "%u", aValue ); 
    } 
 
    aResult.Insert( 0, lTemp ); 
} 
 
 
// Types 
///////////////////////////////////////////////////////////////////////////// 
 
typedef enum 
{ 
    FORMAT_TEXT     = 0, 
    FORMAT_RAW      = 1, 
    FORMAT_BITMAP   = 2, 
    FORMAT_MOVIE    = 3 
} SaveFormat; 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CyAcquisitionPage property page 
 
IMPLEMENT_DYNCREATE(CyAcquisitionPage, CPropertyPage) 
 
CyAcquisitionPage::CyAcquisitionPage() 
    : CPropertyPage(CyAcquisitionPage::IDD) 
    , mSignalGenerator( NULL ) 
    , mColorAdjustment( NULL ) 
	, mVC( NULL ) 
    , mFilter( NULL ) 
    , mSavingThread( NULL ) 
{ 
	//{{AFX_DATA_INIT(CyAcquisitionPage) 
	mFrameCount = 0; 
	mInvertDeinterlacer = FALSE; 
	mDisplayFullscreen = FALSE; 
	mFullscreenDisplayAdapter = -1; 
	mSaveAsFormat = -1; 
	mGSFrameCount = 0; 
	mGSInfiniteFrames = FALSE; 
	mInterPacketDelay = 0; 
	//}}AFX_DATA_INIT 
 
    mSaveAsFormat = 0; 
    mFrameCount = 1; 
    mNormalDisplay = true; 
    mFullscreenDisplayAdapter = 0; 
 
    m_psp.dwFlags |= PSP_HASHELP; 
} 
 
CyAcquisitionPage::~CyAcquisitionPage() 
{ 
    CyAssert( mSavingThread == NULL ); 
	if( mVC != NULL ) 
		delete mVC; 
} 
 
void CyAcquisitionPage::DoDataExchange(CDataExchange* pDX) 
{ 
	CPropertyPage::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CyAcquisitionPage) 
	DDX_Control(pDX, IDC_INTER_PACKET_DELAY_SPIN, mInterPacketDelaySpin); 
	DDX_Control(pDX, IDC_INTER_PACKET_DELAY, mInterPacketDelayControl); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_PROGRESS_CANCEL_BUTTON, mSequenceProgressCancel); 
	DDX_Control(pDX, IDC_ACQUISITION_MODE, mAcqModeControl); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_INFINITE, mGSInfiniteFramesControl); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_MOVIE_PROPERTIES, mMovieProperties); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_MOVIE, mSaveAsMovie); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_TEXT, mSaveAsText); 
    DDX_Control(pDX, IDC_ACQUISITION_GS_BITMAP, mSaveAsBitmap); 
    DDX_Control(pDX, IDC_ACQUISITION_GS_RAW, mSaveAsRaw); 
	DDX_Control(pDX, IDC_DISPLAY_FS_DISPLAY, mFullscreenDisplayAdapterControl); 
	DDX_Control(pDX, IDC_DISPLAY_FULLSCREEN, mDisplayFullscreenControl); 
	DDX_Control(pDX, IDC_BAD_IMAGE_PASSTHROUGH, mBadImagePassthrough); 
    DDX_Control(pDX, IDC_IGNORE_MISSING_PACKETS, mIgnoreMissingPackets); 
	DDX_Control(pDX, IDC_CHANNEL, mChannels); 
	DDX_Control(pDX, IDC_THROTTLE_TEXT, mThrottleText); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_PROGRESS, mSequenceProgress); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_FRAMES_TEXT, mGSFramesText); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_FRAMES, mGSFrames); 
	DDX_Control(pDX, IDC_ACQUISITION_GRAB_SAVE, mGrabSaveButton); 
	DDX_Control(pDX, IDC_ACQUISITION_GS_FRAMES_SPIN, mGSFramesSpin); 
	DDX_Control(pDX, IDC_ACQUISITION_LAST_ERROR, mLastError); 
	DDX_Control(pDX, IDC_DISPLAY_RATE, mDisplayRate); 
	DDX_Control(pDX, IDC_ACQUISITION_STATUS, mAcquisitionStatus); 
	DDX_Control(pDX, IDC_ACQUISITION_RATE, mAcquisitionRate); 
	DDX_Control(pDX, IDC_ACQUISITION_FRAME_COUNT_SPIN, mFrameCountSpin); 
	DDX_Text(pDX, IDC_ACQUISITION_FRAME_COUNT, mFrameCount); 
	DDV_MinMaxUInt(pDX, mFrameCount, 1, 255); 
	DDX_Check(pDX, IDC_ACQUISITION_INVERT_DEINTERLACER, mInvertDeinterlacer); 
	DDX_Check(pDX, IDC_DISPLAY_FULLSCREEN, mDisplayFullscreen); 
	DDX_CBIndex(pDX, IDC_DISPLAY_FS_DISPLAY, mFullscreenDisplayAdapter); 
	DDX_Radio(pDX, IDC_ACQUISITION_GS_TEXT, mSaveAsFormat); 
	DDX_Text(pDX, IDC_ACQUISITION_GS_FRAMES, mGSFrameCount); 
	DDV_MinMaxUInt(pDX, mGSFrameCount, 1, 16777215); 
	DDX_Check(pDX, IDC_ACQUISITION_GS_INFINITE, mGSInfiniteFrames); 
	DDX_Text(pDX, IDC_INTER_PACKET_DELAY, mInterPacketDelay); 
	DDV_MinMaxUInt(pDX, mInterPacketDelay, 0, 65535); 
	//}}AFX_DATA_MAP 
} 
 
 
BEGIN_MESSAGE_MAP(CyAcquisitionPage, CPropertyPage) 
	//{{AFX_MSG_MAP(CyAcquisitionPage) 
	ON_BN_CLICKED(IDC_ACQUISITION_START, OnAcquisitionStart) 
	ON_BN_CLICKED(IDC_ACQUISITION_STOP, OnAcquisitionStop) 
	ON_BN_CLICKED(IDC_DISPLAY_CLOSE, OnDisplayClose) 
	ON_BN_CLICKED(IDC_DISPLAY_NORMAL, OnDisplayNormal) 
	ON_BN_CLICKED(IDC_DISPLAY_NONE, OnDisplayNone) 
	ON_WM_TIMER() 
	ON_BN_CLICKED(IDC_ACQUISITION_CONTINOUS, OnAcquisitionContinous) 
	ON_WM_DESTROY() 
	ON_BN_CLICKED(IDC_SIGNALS, OnSignals) 
	ON_BN_CLICKED(IDC_SIGNALS_CLOSED, OnSignalsClosed) 
	ON_BN_CLICKED(IDC_ACQUISITION_GRAB_SAVE, OnAcquisitionGrabSave) 
	ON_BN_CLICKED(IDC_ACQUISITION_GS_LOCATION, OnAcquisitionGsLocation) 
	ON_CBN_SELCHANGE(IDC_CHANNEL, OnSelchangeChannel) 
	ON_BN_CLICKED(IDC_BAD_IMAGE_PASSTHROUGH, OnBadImagePassthrough) 
    ON_BN_CLICKED(IDC_IGNORE_MISSING_PACKETS, OnIgnoreMissingPackets) 
	ON_BN_CLICKED(IDC_DISPLAY_FULLSCREEN, OnDisplayFullscreen) 
	ON_BN_CLICKED(IDC_ACQUISITION_GS_MOVIE_PROPERTIES, OnMovieProperties) 
	ON_BN_CLICKED(IDC_ACQUISITION_GS_MOVIE, OnAcquisitionGsMovie) 
	ON_COMMAND(ID_TOOLS_COLOR_ADJUSTMENT, OnToolsColorAdjust) 
	ON_BN_CLICKED(IDC_COLOR_ADJUST_CLOSED, OnColorAdjustClosed) 
	ON_BN_CLICKED(IDC_ACQUISITION_GS_INFINITE, OnAcquisitionGsInfinite) 
	ON_CBN_SELCHANGE(IDC_ACQUISITION_MODE, OnSelchangeAcquisitionMode) 
	ON_BN_CLICKED(IDC_ACQUISITION_GS_PROGRESS_CANCEL_BUTTON, OnAcquisitionGsProgressCancelButton) 
	ON_BN_CLICKED(IDC_IPD_COMPUTE, OnIpdCompute) 
	ON_EN_CHANGE(IDC_INTER_PACKET_DELAY, OnChangeInterPacketDelay) 
	ON_COMMAND(ID_BAYER_INTERPOLATION, OnBayerInterpolation) 
    //}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CyAcquisitionPage message handlers 
 
BOOL CyAcquisitionPage::OnKillActive()  
{ 
    OnClose(); 
 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    lApp->mPropertySheet.GetMenu()->EnableMenuItem( 3, MF_BYPOSITION | MF_GRAYED ); 
 
    KillTimer( 100 ); 
     
	return CPropertyPage::OnKillActive(); 
} 
 
 
void CyAcquisitionPage::OnAcquisitionStart()  
{ 
    // Get the channel 
    CString lChannelName; 
    mChannels.GetLBText( mChannels.GetCurSel(), lChannelName ); 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ) , (LPCTSTR) lChannelName ); 
 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
    CyDisplayEx& lDisplay = lApp->GetDisplay(); 
    CyImageBuffer& lBuffer = lApp->GetBuffer( lChannel ); 
    CyConfig& lConfig = lApp->GetConfig(); 
 
    CyAssert( !lCamera.IsStarted( lChannel ) ); 
 
    UpdateData(); 
 
    // Generate the window name from the device and the channel 
    char lName[ 128 ]; 
    lConfig.GetName( lName, sizeof( lName ) - 1 ); 
    string lWindowName( lName ); 
     
    // Check if the invert de-interlaced box is checked 
    unsigned long lFlags = lApp->mBayerFlag; 
    if ( mInvertDeinterlacer ) 
        lFlags |= CyDisplayEx::FLAG_INVERT_DEINTERLACING; 
    unsigned short lColumns = CyDisplayEx::GetColumnCount( lCamera.GetGrabber().GetDevice().GetChannelCount() ); 
    unsigned short lRows    = CyDisplayEx::GetRowCount( lCamera.GetGrabber().GetDevice().GetChannelCount() ); 
    unsigned int lFrame; 
 
    CyDisplayEx::SetCurrentSystemDisplay( mFullscreenDisplayAdapter ); 
    bool lNoData = reinterpret_cast( AfxGetApp() )->mMulticastMasterNoData; 
	switch( mAcqModeControl.GetCurSel() ) 
	{ 
		default: 
        case ACQ_MODE_SINGLE_GRAB: 
            SetRunning( true ); 
 
            lFlags |= CyDisplayEx::FLAG_WAIT; 
 
            if ( lCamera.IsStarted( lChannel ) ) 
			    lCamera.StopGrabbing( lChannel ); 
 
            if ( mNormalDisplay && !lNoData ) 
		    { 
                mDisplayOpen = true; 
 
                // Giving the desktop window as parent makes the window independent 
                // of this application and we can make the application on top of the 
                // window 
                if ( !lDisplay.IsOpened() ) 
                { 
			        lDisplay.Open( GetDesktopWindow( )->GetSafeHwnd(), 
                                   CyDisplayEx::DEFAULT_POSITION,  
                                   CyDisplayEx::DEFAULT_POSITION, 
                                   lBuffer.GetSizeX(), 
                                   lBuffer.GetSizeY(), 
                                   lColumns,  
                                   lRows, 
                                   mDisplayFullscreen != FALSE ); 
                    lDisplay.SetWindowTitle( lWindowName.c_str() ); 
                    if ( lDisplay.GetSubDisplayCount() > 1 ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), true ); 
                } 
                else 
                { 
                    if ( lDisplay.IsFocusedOnSubDisplay() && 
                         ( lDisplay.GetFocusedSubDisplay() != lChannel.GetID() ) && 
                         ( lDisplay.GetSubDisplayCount() > 1 ) ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), false ); 
                } 
		    } 
 
            if ( lNoData ) 
            { 
                lCamera.GetGrabber().Trigger( lChannel, 0, mFrameCount ); 
            } 
            else 
            { 
                lDisplay.SetRGBFilter( lChannel.GetID(), *mFilter ); 
                for ( lFrame = 0; lFrame < mFrameCount; ++lFrame ) 
                { 
			        if ( lCamera.Grab( lChannel, lBuffer, 0 ) == CY_RESULT_OK ) 
                    { 
			            if ( mNormalDisplay ) 
                        { 
				            lDisplay.Display( lBuffer, lChannel.GetID(), lFlags ); 
                            SetTimer( 1, 500, NULL ); 
                        } 
                    } 
		        } 
            } 
 
            SetRunning( false ); 
            GetDlgItem( IDC_ACQUISITION_START )->SetFocus(); 
			break; 
 
		case ACQ_MODE_SINGLE_PLAYBACK: 
            SetRunning( true ); 
 
            lFlags |= CyDisplayEx::FLAG_WAIT; 
 
            if ( lCamera.IsStarted( lChannel ) ) 
			    lCamera.StopGrabbing( lChannel ); 
 
            if ( mNormalDisplay && !lNoData ) 
		    { 
                mDisplayOpen = true; 
 
                // Giving the desktop window as parent makes the window independent 
                // of this application and we can make the application on top of the 
                // window 
                if ( !lDisplay.IsOpened() ) 
                { 
			        lDisplay.Open( GetDesktopWindow( )->GetSafeHwnd(), 
                                   CyDisplayEx::DEFAULT_POSITION,  
                                   CyDisplayEx::DEFAULT_POSITION, 
                                   lBuffer.GetSizeX(), 
                                   lBuffer.GetSizeY(), 
                                   lColumns,  
                                   lRows, 
                                   mDisplayFullscreen != FALSE ); 
                    lDisplay.SetWindowTitle( lWindowName.c_str() ); 
                    if ( lDisplay.GetSubDisplayCount() > 1 ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), true ); 
                } 
                else 
                { 
                    if ( lDisplay.IsFocusedOnSubDisplay() && 
                         ( lDisplay.GetFocusedSubDisplay() != lChannel.GetID() ) && 
                         ( lDisplay.GetSubDisplayCount() > 1 ) ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), false ); 
                } 
		    } 
 
            if ( lNoData ) 
            { 
                lCamera.GetGrabber().Trigger( lChannel, CyGrabber::FLAG_GRAB_RECORDING, mFrameCount ); 
            } 
            else 
            { 
                lDisplay.SetRGBFilter( lChannel.GetID(), *mFilter ); 
                for ( lFrame = 0; lFrame < mFrameCount; ++lFrame ) 
                { 
			        if ( lCamera.Grab( lChannel, lBuffer, CyGrabber::FLAG_GRAB_RECORDING ) == CY_RESULT_OK ) 
                    { 
			            if ( mNormalDisplay ) 
                        { 
				            lDisplay.Display( lBuffer, lChannel.GetID(), lFlags ); 
                            SetTimer( 1, 500, NULL ); 
                        } 
                    } 
		        } 
            } 
 
            SetRunning( false ); 
            GetDlgItem( IDC_ACQUISITION_START )->SetFocus(); 
			break; 
 
 
		case ACQ_MODE_CONTINUOUS_GRAB: 
            if ( lNoData ) 
                lCamera.GetGrabber().StartContinuous( lChannel, true, 0 ); 
            else 
                lCamera.StartGrabbing( lChannel, lBuffer ); 
 
            if ( mNormalDisplay && !lNoData ) 
		    { 
                mDisplayOpen = true; 
 
                // Giving the desktop window as parent makes the window independent 
                // of this application and we can make the application on top of the 
                // window 
                if ( !lDisplay.IsOpened() ) 
                { 
			        lDisplay.Open( GetDesktopWindow( )->GetSafeHwnd(), 
                                   CyDisplayEx::DEFAULT_POSITION,  
                                   CyDisplayEx::DEFAULT_POSITION, 
                                   lBuffer.GetSizeX(), 
                                   lBuffer.GetSizeY(), 
                                   lColumns,  
                                   lRows, 
                                   mDisplayFullscreen != FALSE ); 
                    lDisplay.SetWindowTitle( lWindowName.c_str() ); 
                    if ( lDisplay.GetSubDisplayCount() > 1 ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), true ); 
                } 
                else 
                { 
                    if ( lDisplay.IsFocusedOnSubDisplay() && 
                         ( lDisplay.GetFocusedSubDisplay() != lChannel.GetID() ) && 
                         ( lDisplay.GetSubDisplayCount() > 1 ) ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), false ); 
                } 
 
                if ( !lDisplay.IsDisplaying( lChannel.GetID() ) ) 
                { 
                    lDisplay.SetRGBFilter( lChannel.GetID(), *mFilter ); 
                    lDisplay.StartDisplaying( lBuffer, lChannel.GetID(), lFlags ); 
                    SetTimer( 1, 500, NULL ); 
                } 
		    } 
 
            SetRunning( true ); 
            GetDlgItem( IDC_ACQUISITION_STOP )->SetFocus(); 
			break; 
 
		case ACQ_MODE_CONTINUOUS_PLAYBACK: 
            if ( lNoData ) 
                lCamera.GetGrabber().StartContinuous( lChannel, true, CyGrabber::FLAG_GRAB_RECORDING ); 
            else 
                lCamera.StartGrabbing( lChannel, lBuffer,  CyGrabber::FLAG_GRAB_RECORDING ); 
                 
 
            if ( mNormalDisplay && !lNoData ) 
		    { 
                mDisplayOpen = true; 
 
                // Giving the desktop window as parent makes the window independent 
                // of this application and we can make the application on top of the 
                // window 
                if ( !lDisplay.IsOpened() ) 
                { 
			        lDisplay.Open( GetDesktopWindow( )->GetSafeHwnd(), 
                                   CyDisplayEx::DEFAULT_POSITION,  
                                   CyDisplayEx::DEFAULT_POSITION, 
                                   lBuffer.GetSizeX(), 
                                   lBuffer.GetSizeY(), 
                                   lColumns,  
                                   lRows, 
                                   mDisplayFullscreen != FALSE ); 
                    lDisplay.SetWindowTitle( lWindowName.c_str() ); 
                    if ( lDisplay.GetSubDisplayCount() > 1 ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), true ); 
                } 
                else 
                { 
                    if ( lDisplay.IsFocusedOnSubDisplay() && 
                         ( lDisplay.GetFocusedSubDisplay() != lChannel.GetID() ) && 
                         ( lDisplay.GetSubDisplayCount() > 1 ) ) 
                        lDisplay.FocusOnSubDisplay( lChannel.GetID(), false ); 
                } 
 
                if ( !lDisplay.IsDisplaying( lChannel.GetID() ) ) 
                { 
                    lDisplay.SetRGBFilter( lChannel.GetID(), *mFilter ); 
                    lDisplay.StartDisplaying( lBuffer, lChannel.GetID(), lFlags ); 
                    SetTimer( 1, 500, NULL ); 
                } 
		    } 
 
            SetRunning( true ); 
            GetDlgItem( IDC_ACQUISITION_STOP )->SetFocus(); 
			break; 
 
 
 
		case ACQ_MODE_RECORDING: 
            lCamera.GetGrabber().StartRecording( lChannel ); 
            SetRunning( true ); 
            GetDlgItem( IDC_ACQUISITION_STOP )->SetFocus(); 
			break; 
	} 
} 
 
void CyAcquisitionPage::OnAcquisitionStop()  
{ 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ) , "" ); 
 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
    CyDisplayEx& lDisplay = lApp->GetDisplay(); 
 
    // Stop the camera, then the display 
    if ( lDisplay.IsDisplaying( lChannel.GetID() ) ) 
    { 
        lDisplay.StopDisplaying( lChannel.GetID() ); 
 
        // if all the channels are not displaying, kill the timer 
        bool lStop = true; 
        for ( unsigned int i = 0; lStop && ( i < lDisplay.GetSubDisplayCount() ); ++i ) 
        { 
            if ( lDisplay.IsDisplaying( i ) ) 
                lStop = false; 
        } 
        if ( lStop ) 
            KillTimer( lChannel.GetID() + 1 ); 
    } 
 
    bool lNoData = reinterpret_cast( AfxGetApp() )->mMulticastMasterNoData; 
    switch( mAcqModeControl.GetCurSel() ) 
    { 
        case ACQ_MODE_CONTINUOUS_GRAB: 
        case ACQ_MODE_CONTINUOUS_PLAYBACK: 
            if ( lNoData ) 
                lCamera.GetGrabber().StopContinuous( lChannel ); 
            else if ( lCamera.IsStarted( lChannel ) ) 
                lCamera.StopGrabbing( lChannel ); 
            break; 
 
        case ACQ_MODE_RECORDING: 
            if ( lCamera.GetGrabber().IsRecording( lChannel ) ) 
                lCamera.GetGrabber().StopRecording( lChannel ); 
            break; 
    } 
 
 
    SetRunning( false ); 
    GetDlgItem( IDC_ACQUISITION_START )->SetFocus(); 
} 
 
void CyAcquisitionPage::OnDisplayClose()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
    CyDisplayEx& lDisplay = lApp->GetDisplay(); 
 
    // Stop the display, will stop all the displaying 
    if ( lDisplay.IsOpened() ) 
        lDisplay.Close(); 
 
    // Stop the camera 
    for ( CyChannelID lID = 0; lID < lApp->GetDevice().GetChannelCount(); ++lID ) 
    { 
        if ( lApp->HasCamera() && lCamera.IsStarted( CyChannel( lID ) ) ) 
            lCamera.StopGrabbing( CyChannel( lID ) ); 
    } 
} 
 
void CyAcquisitionPage::OnDisplayNormal()  
{ 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ) , "" ); 
 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
 
    mNormalDisplay = true; 
    SetRunning( lCamera.IsStarted( lChannel ) ); 
} 
 
void CyAcquisitionPage::OnDisplayNone()  
{ 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ) , "" ); 
 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
 
    mNormalDisplay = false; 
    SetRunning( lCamera.IsStarted( lChannel ) ); 
} 
 
 
BOOL CyAcquisitionPage::OnInitDialog()  
{ 
	CPropertyPage::OnInitDialog(); 
 
    mAcqModeControl.SetCurSel( 1 ); 
	 
    mFrameCountSpin.SetRange32( 1, 255 ); 
 
    mGSFrames.EnableWindow( mGSInfiniteFramesControl.GetCheck() == 0 ); 
 
    if ( mNormalDisplay ) 
        reinterpret_cast( GetDlgItem( IDC_DISPLAY_NORMAL ) )->SetCheck( 1 ); 
    else 
        reinterpret_cast( GetDlgItem( IDC_DISPLAY_NONE ) )->SetCheck( 1 ); 
     
    SetRunning( false ); 
 
    mGSFrames.SetWindowText( "1" ); 
    mGSFramesSpin.SetRange32( 1, 1024 ); 
 
    // Read the actual inter-packet delay from the device 
    unsigned short lDelay = 0; 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyDevice& lDevice = lApp->GetGrabber().GetDevice(); 
    lDevice.GetInterPacketDelay( lDelay ); 
 
    // Set the throttle position 
    CString lTemp; 
    mInterPacketDelaySpin.SetRange32( 0, 65535 ); 
    mInterPacketDelay = lDelay; 
    lTemp.Format( "%u", lDelay ); 
    mInterPacketDelayControl.SetWindowText( lTemp ); 
 
    // Set the throttle text 
    FormatInteger( lDelay * 30, lTemp ); 
    lTemp.Insert( 0, "Packet Delay (" ); 
    lTemp += " ns)"; 
    mThrottleText.SetWindowText( lTemp ); 
 
    // Set the adapters for fullscreen 
    mFullscreenDisplayAdapterControl.ResetContent(); 
    for ( unsigned int i = 0; i < CyDisplayEx::GetSystemDisplayCount(); ++i ) 
    { 
        lTemp.Format( "Adapter %u", i ); 
        mFullscreenDisplayAdapterControl.AddString( lTemp ); 
    } 
    mFullscreenDisplayAdapterControl.SetCurSel( mFullscreenDisplayAdapter ); 
    mFullscreenDisplayAdapterControl.EnableWindow(  mDisplayFullscreenControl.GetCheck() && 
                                                    ( mFullscreenDisplayAdapterControl.GetCount() > 1 ) ); 
 
 
	return TRUE;  // return TRUE unless you set the focus to a control 
	              // EXCEPTION: OCX Property Pages should return FALSE 
} 
 
BOOL CyAcquisitionPage::OnSetActive()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyDevice& lDevice= lApp->GetDevice(); 
    CyGrabber& lGrabber = lApp->GetGrabber(); 
 
    if ( !lApp->HasCamera() ) 
    { 
        CyAssert( "must have a camera" == 0 ); 
    } 
 
    lApp->mPropertySheet.GetMenu()->EnableMenuItem( 3, MF_BYPOSITION | MF_ENABLED ); 
 
    // get some information from the camera 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
 
    // Clear the channel list box and fill it with the channels in the config 
    mChannels.ResetContent(); 
    for ( unsigned short lID = 0; lID < lDevice.GetChannelCount(); ++lID ) 
    { 
        // Get the channel from the device 
        const CyChannel lChannel( lDevice.GetChannel( lID )  ); 
 
        // Add the channel to the combo box and select the first one 
        // if none is already selected 
        int lIndex = mChannels.AddString( lChannel.GetName().c_str() ); 
        mChannels.SetItemData( lIndex, lID ); 
        if ( ( mChannels.GetCurSel() == - 1 ) && ( lID == 0 ) ) 
            mChannels.SetCurSel( lIndex ); 
 
        // adjust the buffer for this channel 
        CyImageBuffer& lBuffer = lApp->GetBuffer( lChannel ); 
        unsigned short lSizeX, lSizeY, lOffsetX, lOffsetY, lDecimationX, lDecimationY, lDecimationBlockX, lDecimationBlockY; 
        unsigned short lBinningX, lBinningY; 
        CyPixelTypeID lPixelType; 
        lCamera.GetSizeX( lSizeX ); 
        lCamera.GetSizeY( lSizeY ); 
        lCamera.GetOffsetX( lOffsetX ); 
        lCamera.GetOffsetY( lOffsetY ); 
        lCamera.GetDecimationX( lDecimationX ); 
        lCamera.GetDecimationY( lDecimationY ); 
        lCamera.GetDecimationBlockX( lDecimationBlockX ); 
        lCamera.GetDecimationBlockY( lDecimationBlockY ); 
        lCamera.GetBinningX( lBinningX ); 
        lCamera.GetBinningY( lBinningY ); 
        lCamera.GetEffectivePixelType( lPixelType ); 
 
	    if ( ( lDecimationX != 0 ) && ( lDecimationY != 0 ) ) 
	    { 
            lSizeX = (( lSizeX / lBinningX ) + (( lSizeX % lBinningX ) ? 1 : 0)); 
            lSizeX = ( ( lSizeX / lDecimationBlockX / lDecimationX ) + ( ( ( lSizeX / lDecimationBlockX ) % lDecimationX ) ? 1 : 0) ); 
            lSizeX *= lDecimationBlockX; 
            lSizeY = (( lSizeY / lBinningY ) + (( lSizeY % lBinningY ) ? 1 : 0)); 
            lSizeY = ( ( lSizeY / lDecimationBlockY / lDecimationY ) + ( ( ( lSizeY / lDecimationBlockY ) % lDecimationY ) ? 1 : 0) ); 
            lSizeY *= lDecimationBlockY; 
		    lBuffer.SetCapacity( lSizeX, lSizeY, lPixelType ); 
	    } 
    } 
 
    // Create a new filter 
    double lRedGain   = 1.0f; 
    double lGreenGain = 1.0f; 
    double lBlueGain  = 1.0f; 
    unsigned short lRedOffset   = 0; 
    unsigned short lGreenOffset = 0; 
    unsigned short lBlueOffset  = 0; 
    if ( mFilter != NULL ) 
    { 
        lRedOffset = mFilter->GetRedValue16( 0 ); 
        lGreenOffset = mFilter->GetGreenValue16( 0 ); 
        lBlueOffset = mFilter->GetBlueValue16( 0 ); 
 
        lRedGain = static_cast( mFilter->GetRedValue16( 255 ) ); 
        lRedGain = ( lRedGain - static_cast( lRedOffset ) ) / 255.0; 
        lGreenGain = static_cast( mFilter->GetGreenValue16( 255 ) ); 
        lGreenGain = ( lGreenGain - static_cast( lGreenOffset ) ) / 255.0; 
        lBlueGain = static_cast( mFilter->GetBlueValue16( 255 ) ); 
        lBlueGain = ( lBlueGain - static_cast( lBlueOffset ) ) / 255.0; 
    } 
    delete mFilter; 
    mFilter = new CyRGBFilter( min( max( 8, lGrabber.GetPixelDepth() ), 16 ) ); 
    mFilter->SetMultipliers( lRedGain, lGreenGain, lBlueGain, lRedOffset, lGreenOffset, lBlueOffset ); 
 
    mChannels.EnableWindow( mChannels.GetCount() > 1 ); 
 
    // set the bad image passthrough from the grabber 
    mBadImagePassthrough.SetCheck( lCamera.GetGrabber().IsBadImagePassthroughEnabled() ); 
    mIgnoreMissingPackets.SetCheck( lCamera.GetGrabber().IgnoringMissingPackets() ); 
 
    SetTimer( 100, 500, NULL ); 
	 
	return CPropertyPage::OnSetActive(); 
} 
 
void CyAcquisitionPage::OnTimer(UINT nIDEvent)  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
    CyGrabber& lGrabber = lApp->GetGrabber(); 
 
    // Event is display closed detection 
    if ( nIDEvent == 1 ) 
    { 
        CyDisplayEx& lDisplay = lApp->GetDisplay(); 
 
        if ( mDisplayOpen && !lDisplay.IsOpened() ) 
        { 
            if ( lApp->HasCamera() ) 
            { 
                for ( unsigned int i = 0; i < lGrabber.GetDevice().GetChannelCount(); ++i ) 
                { 
                    if ( lGrabber.IsStarted( i ) ) 
	                    lCamera.StopGrabbing( i ); 
                } 
            } 
 
            mDisplayOpen = false; 
            SetRunning( false ); 
            KillTimer( nIDEvent ); 
        } 
    } 
 
    // Event is status update 
    else if ( nIDEvent == 100 ) 
    { 
        const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ), "" ); 
        CyDisplayEx& lDisplay = lApp->GetDisplay(); 
        CString lStr; 
 
	    if (    ( !lDisplay.IsOpened()             ) 
             || ( lDisplay.GetPerformanceMonitor( lChannel.GetID() ).GetImageCount()  <= 0   ) 
             || ( lDisplay.GetPerformanceMonitor( lChannel.GetID() ).GetRunningTime() <= 0.0 ) ) 
	    { 
		    lStr.Format( "%04.2f fps, average %04.2f fps (Last Image ID = %08X)", 
                         0.0, 
                         0.0, 
                         0 ); 
	    } 
        else 
        { 
		    lStr.Format( "%04.2f fps, average %04.2f fps (Last Image ID = %08X, timestamp = %u)", 
                         lDisplay.GetPerformanceMonitor( lChannel.GetID() ).GetFrameRate(), 
                         lDisplay.GetPerformanceMonitor( lChannel.GetID() ).GetAverageFrameRate(), 
                         lDisplay.GetLastImageID( lChannel.GetID() ), 
                         lDisplay.GetLastTimestamp( lChannel.GetID() ) ); 
	    } 
        mDisplayRate.SetWindowText( lStr ); 
 
	    if (    ( !lGrabber.IsConnected() ) 
             || ( lGrabber.IsStopped( lChannel ) ) 
             || ( lGrabber.GetPerformanceMonitor( lChannel ).GetImageCount()  <= 0   ) 
             || ( lGrabber.GetPerformanceMonitor( lChannel ).GetRunningTime() <= 0.0 ) ) 
	    { 
		    lStr.Format( "%04.2f fps, average %04.2f fps", 0.0, 0.0 ); 
	    } 
        else 
        { 
		    lStr.Format( "%04.2f fps, average %04.2f fps", 
                         lGrabber.GetPerformanceMonitor( lChannel ).GetFrameRate(), 
                         lGrabber.GetPerformanceMonitor( lChannel ).GetAverageFrameRate() ); 
	    } 
        mAcquisitionRate.SetWindowText( lStr ); 
 
	    lStr.Format( "Image: %010d  (Bad: %05d)", 
                     lGrabber.GetPerformanceMonitor( lChannel ).GetImageCount(), 
                     lGrabber.GetPerformanceMonitor( lChannel ).GetBadImageCount() ); 
 
        mAcquisitionStatus.SetWindowText( lStr ); 
 
 
        if ( lGrabber.GetPerformanceMonitor().GetBadImageCount() > 0 ) 
        { 
            CyErrorInfo lInfo; 
            lGrabber.GetErrorInfo( &lInfo ); 
            if ( lInfo.mResult != CY_RESULT_OK ) 
            { 
                lStr.Format( "%s: %s.", 
                             CoyoteStatusMessage( lInfo.mResult ), 
                             lInfo.mMessage ); 
                mLastError.SetWindowText( lStr ); 
            } 
            else 
            { 
                // when there is no error, display the current callback count 
                lStr.Format( "No errors.  Host PC Interrupt: Count = %lu, Mask = 0x%02X, Time = %lu", 
                             lApp->mCallbackCounter, 
                             lApp->mCallbackMask, 
                             lApp->mCallbackTimestamp ); 
                mLastError.SetWindowText( lStr ); 
            } 
        } 
        else 
        { 
            // when there is no error, display the current callback count 
            lStr.Format( "No errors.  Host PC Interrupt: Count = %lu, Mask = 0x%02X, Time = %lu", 
                         lApp->mCallbackCounter, 
                         lApp->mCallbackMask, 
                         lApp->mCallbackTimestamp ); 
            mLastError.SetWindowText( lStr ); 
        } 
     
        // while were at it, check if the buffer format is interlaced or not 
        // if not, hide the Invert de-interlacer 
        if ( lGrabber.GetInterlaced() ) 
            GetDlgItem( IDC_ACQUISITION_INVERT_DEINTERLACER )->ShowWindow( SW_SHOW ); 
        else 
            GetDlgItem( IDC_ACQUISITION_INVERT_DEINTERLACER )->ShowWindow( SW_HIDE ); 
    } 
	 
	CPropertyPage::OnTimer(nIDEvent); 
} 
 
void CyAcquisitionPage::OnAcquisitionContinous()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ), "" ); 
 
    SetRunning( lCamera.IsStarted( lChannel ) ); 
} 
 
 
void CyAcquisitionPage::SetRunning( bool aRunning ) 
{ 
    BOOL lRunning = aRunning ? TRUE : FALSE; 
    BOOL lContinuous = ( mAcqModeControl.GetCurSel() == 1 ) || 
                       ( mAcqModeControl.GetCurSel() == 3 ) || 
                       ( mAcqModeControl.GetCurSel() == 4 ); 
    BOOL lSaving = ( mSavingThread != NULL ); 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ), "" ); 
 
	GetDlgItem( IDC_ACQUISITION_START )->EnableWindow( !lRunning ); 
    GetDlgItem( IDC_ACQUISITION_STOP )->EnableWindow( lRunning ); 
    mAcqModeControl.EnableWindow( !lRunning ); 
    GetDlgItem( IDC_ACQUISITION_FRAME_COUNT )->EnableWindow( !lRunning && !lContinuous ); 
    mFrameCountSpin.EnableWindow( !lRunning && !lContinuous ); 
    GetDlgItem( IDC_ACQUISITION_FRAME_COUNT_STATIC )->EnableWindow( !lRunning && !lContinuous ); 
 
    GetDlgItem( IDC_DISPLAY_NORMAL )->EnableWindow( !lSaving && !lRunning ); 
    GetDlgItem( IDC_DISPLAY_NONE )->EnableWindow( !lSaving && !lRunning ); 
    GetDlgItem( IDC_DISPLAY_CLOSE )->EnableWindow( !lSaving && mDisplayOpen ); 
 
    mGSFramesSpin.EnableWindow( !lSaving ); 
    mGSInfiniteFramesControl.EnableWindow( !lSaving ); 
    mGSFrames.EnableWindow( !lSaving && ( mGSInfiniteFramesControl.GetCheck() == 0 ) ); 
    mGSFramesText.EnableWindow( !lSaving ); 
    mSaveAsText.EnableWindow( !lSaving ); 
    mSaveAsRaw.EnableWindow( !lSaving ); 
    mSaveAsBitmap.EnableWindow( !lSaving ); 
    mSaveAsMovie.EnableWindow( !lSaving ); 
    mMovieProperties.EnableWindow( !lSaving ); 
    mGrabSaveButton.EnableWindow( !lSaving ); 
} 
 
void CyAcquisitionPage::OnDestroy()  
{ 
    OnDisplayClose(); 
 
    if ( mSignalGenerator ) 
        OnSignalsClosed(); 
 
    if ( mColorAdjustment ) 
        OnColorAdjustClosed(); 
 
	CPropertyPage::OnDestroy(); 
} 
 
BOOL CyAcquisitionPage::PreTranslateMessage(MSG* pMsg)  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
 
	// allow tooltip messages to be filtered 
	if (CPropertyPage::PreTranslateMessage(pMsg)) 
		return TRUE; 
 
	if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) 
	{ 
		// finally, translate the message 
		return ::TranslateAccelerator(m_hWnd, lApp->mAccelerators, pMsg); 
	} 
	return FALSE; 
} 
 
void CyAcquisitionPage::OnSignals()  
{ 
    CyAssert( mSignalGenerator == NULL ); 
 
    // Giving the desktop window as parent makes the window independent 
    // of this application and we can make the application on top of the 
    // window 
    mSignalGenerator = new CySignalDialog( GetDesktopWindow( ), *this ); 
 
    mSignalGenerator->Create( CySignalDialog::IDD, GetDesktopWindow( ) ); 
    mSignalGenerator->ShowWindow( SW_SHOW ); 
    GetDlgItem( IDC_SIGNALS )->EnableWindow( FALSE ); 
} 
 
 
void CyAcquisitionPage::OnSignalsClosed() 
{ 
    CyAssert( mSignalGenerator != NULL ); 
 
    mSignalGenerator->DestroyWindow(); 
    delete mSignalGenerator; 
    mSignalGenerator = NULL; 
 
    GetDlgItem( IDC_SIGNALS )->EnableWindow( TRUE ); 
} 
 
void CyAcquisitionPage::OnColorAdjustClosed()  
{ 
    CyAssert( mColorAdjustment != NULL ); 
 
    mColorAdjustment->DestroyWindow(); 
    delete mColorAdjustment; 
    mColorAdjustment = NULL; 
} 
 
void CyAcquisitionPage::WinHelp(DWORD dwData, UINT nCmd)  
{ 
    CPropertyPage::WinHelp( CyAcquisitionPage::IDD, HELP_CONTEXT ); 
} 
 
 
static void SaveToBitmap( FILE *                aFile, 
                          const unsigned char * aData, 
                          unsigned long         aSizeX, 
                          unsigned long         aSizeY, 
                          bool                  aGrayscale ) 
{ 
    CyAssert( aFile != NULL ); 
 
    BITMAPFILEHEADER lHeader; 
    BITMAPINFOHEADER lInfo; 
    memset( &lHeader, 0, sizeof( lHeader ) ); 
    memset( &lInfo, 0, sizeof( lInfo ) ); 
 
    // compute the size of the data 
    unsigned long lLineSize = aSizeX; 
    if ( !aGrayscale ) 
        lLineSize *= 4; 
    unsigned long lImageSize = lLineSize * aSizeY; 
     
    // compute the offset, where the data will start 
    unsigned long lOffset = sizeof( lHeader ) + sizeof( lInfo ); 
    if ( aGrayscale ) 
        lOffset += ( 256 * 4 ); 
 
    // Prepare the file header 
    lHeader.bfType    = 'B' | ( 'M' << 8 ); 
    lHeader.bfOffBits = lOffset; 
    lHeader.bfSize    = lOffset + lImageSize; 
 
    // Prepare the info header 
    lInfo.biBitCount      = aGrayscale ? 8 : 32; 
    lInfo.biClrImportant  = 0; 
    lInfo.biClrUsed       = aGrayscale ? 256 : 0; 
    lInfo.biCompression   = 0; 
    lInfo.biHeight        = aSizeY; 
    lInfo.biPlanes        = 1; 
    lInfo.biSize          = sizeof( lInfo ); 
    lInfo.biSizeImage     = lImageSize; 
    lInfo.biWidth         = aSizeX; 
    lInfo.biXPelsPerMeter = 0; 
    lInfo.biYPelsPerMeter = 0; 
 
    // save the headers 
    if (    ( fwrite( &lHeader, sizeof( lHeader ), 1, aFile ) != 1 ) 
         || ( fwrite( &lInfo,   sizeof( lInfo   ), 1, aFile ) != 1 ) ) 
    { 
        // Oups ! Write error ! 
        throw CyErrorInfo( "Cannot write output file", 
                           CY_RESULT_FILE_ERROR, 
                           __FILE__, 
                           __LINE__, 
                           GetLastError() ); 
    } 
 
    // write the palette 
    if ( aGrayscale ) 
    { 
        unsigned char lRGB[ 4 ]; 
        for ( unsigned int lI = 0; lI < 256; lI ++ ) 
        { 
            lRGB[ 0 ] = lI; 
            lRGB[ 1 ] = lI; 
            lRGB[ 2 ] = lI; 
            lRGB[ 3 ] = lI; 
 
            fwrite( lRGB, 1, 4, aFile ); 
        } 
    } 
 
    // save the lines starting from the end 
    for ( int lLine = ( aSizeY - 1 ); lLine >= 0; --lLine ) 
    { 
        if ( fwrite( aData + ( lLine * lLineSize ), 1, lLineSize, aFile ) != lLineSize ) 
        { 
            // Oups ! Write error ! 
            throw CyErrorInfo( "Cannot write output file", 
                               CY_RESULT_FILE_ERROR, 
                               __FILE__, 
                               __LINE__, 
                               GetLastError() ); 
        } 
    } 
} 
 
 
class SavingThread : public CyThread 
{ 
public: 
    SavingThread( CyAcquisitionPage&        aDialog, 
                  CyImageBuffer&            aBuffer, 
                  const CyPixelConverter*   aConverter, 
                  const CyPixelType&        aDestPixel, 
                  const CyRGBFilter&        aFilter, 
                  const CString&            aFilename, 
                  FILE*                     aFile, 
                  unsigned long             aFlags ) 
        : mDialog( aDialog ) 
        , mBuffer( aBuffer ) 
        , mConverter( aConverter ) 
        , mDestPixel( aDestPixel ) 
        , mFilter( aFilter ) 
        , mFilename( aFilename ) 
        , mFile( aFile ) 
        , mFlags( aFlags ) 
    { 
        StartThread(); 
    } 
 
    virtual ~SavingThread() 
    { 
        StopThread(); 
        mBuffer.AbortRead(); 
        while ( WaitUntilSignaled( 10 ) == CY_RESULT_TIMEOUT ) 
            mBuffer.AbortRead(); 
    } 
 
    virtual CyResult StopThread() 
    { 
        CyResult lResult = CyThread::StopThread(); 
        mBuffer.AbortRead(); 
        return lResult; 
    } 
 
    virtual CyResult Run() 
    { 
        SetPriority( CyThread::HIGHEST ); 
 
        unsigned char * lOutputBuffer =  
            new unsigned char[ mDestPixel.GetBufferSizeFor( mBuffer.GetSizeX(), 
                                                            mBuffer.GetSizeY() ) ]; 
        if ( lOutputBuffer == NULL ) 
            return CY_RESULT_NOT_ENOUGH_MEMORY; 
 
        try 
        { 
            // Save frames 
            unsigned char * lPtr; 
            unsigned long lSize; 
 
            unsigned long lMax = mDialog.mGSFrameCount; 
            if ( mDialog.mGSInfiniteFrames ) 
                lMax = 1;  
 
            for ( unsigned long i = 0; !IsStopping() && ( i < lMax ); ) 
            { 
                // Lock the buffer 
                if ( mBuffer.LockForRead( (void**)&lPtr, &lSize, CyBuffer::FLAG_NO_WAIT ) == CY_RESULT_OK ) 
                { 
                    switch( mDialog.mSaveAsFormat ) 
                    { 
                        default: 
                        case FORMAT_TEXT: 
                            fprintf( mFile, "%08lu\n", mBuffer.GetReadImageID() ); 
                            break; 
 
 
                        case FORMAT_RAW: 
                            // Open, write and close the file 
                            mFilename.Format("%s\\%08lu.raw", (LPCTSTR)mDialog.mSequenceLocation, mBuffer.GetReadImageID() ); 
                            mFile = fopen( mFilename, "wb" ); 
                            if ( mFile != NULL ) 
                            { 
                                fwrite( lPtr, 1, lSize, mFile ); 
                                fclose( mFile ); 
                                mFile = NULL; 
                            } 
                            break; 
 
 
                        case FORMAT_BITMAP: 
                            CyAssert( mConverter != NULL ); 
 
                            // Convert to RGB 32 
                            mConverter->Convert( mFilter, 
                                                 lPtr, 
                                                 mBuffer.GetSizeX(), mBuffer.GetSizeY(), 
                                                 lOutputBuffer, 
                                                 mBuffer.GetSizeX(), mBuffer.GetSizeY(), 
                                                 mBuffer.GetSizeX(), mBuffer.GetSizeY(),  
                                                 mFlags ); 
 
                            // Open, write and close the file 
                            mFilename.Format("%s\\%08lu.bmp", (LPCTSTR)mDialog.mSequenceLocation, mBuffer.GetReadImageID() ); 
                            mFile = fopen( mFilename, "wb" ); 
                            if ( mFile != NULL ) 
                            { 
                                SaveToBitmap( mFile, 
                                              lOutputBuffer,  
                                              mBuffer.GetSizeX(), 
                                              mBuffer.GetSizeY(), 
                                              ( mDestPixel.GetTypeID() & CyPixelType::GRAYSCALE ) != 0 ); 
                                fclose( mFile ); 
                                mFile = NULL; 
                            } 
                            break; 
 
                        case FORMAT_MOVIE: 
                            CyAssert( mConverter != NULL ); 
                            mConverter->Convert( mFilter, 
                                                 lPtr, 
                                                 mBuffer.GetSizeX(), mBuffer.GetSizeY(), 
                                                 lOutputBuffer, 
                                                 mBuffer.GetSizeX(), mBuffer.GetSizeY(), 
                                                 mBuffer.GetSizeX(), mBuffer.GetSizeY(),  
                                                 mFlags ); 
                            mDialog.mVC->Compress( lOutputBuffer ); 
                            break; 
                    }; 
 
                    mBuffer.SignalReadEnd(); 
                } 
 
                if ( !mDialog.mGSInfiniteFrames ) 
                    mDialog.mSequenceProgress.PostMessage( PBM_SETPOS, ++i, 0L ); 
            } 
        } 
        catch( ... ) 
        { 
        } 
 
        // Delete the temp buffer 
        delete [] lOutputBuffer; 
        lOutputBuffer = NULL; 
 
        return CY_RESULT_OK; 
    } 
 
private: 
    CyAcquisitionPage&      mDialog; 
    CyImageBuffer&          mBuffer; 
    const CyPixelConverter* mConverter; 
    const CyPixelType&      mDestPixel; 
    const CyRGBFilter&      mFilter; 
    CString                 mFilename; 
    FILE*                   mFile; 
    unsigned long           mFlags; 
}; 
 
void CyAcquisitionPage::OnAcquisitionGrabSave()  
{ 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ), "" ); 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyImageBuffer& lBuffer = lApp->GetBuffer( lChannel ); 
    CyDevice& lDevice = lApp->GetDevice(); 
    CyGrabber& lGrabber = lApp->GetGrabber(); 
	CyPerfMonitor& lPerfMonitor = lApp->GetGrabber().GetPerformanceMonitor(); 
    CString lFilename; 
    FILE * lFile; 
    unsigned long lFlags = ( mInvertDeinterlacer ? CyPixelConverter::FLAG_INVERT_DEINTERLACER : 0 ); 
    lFlags |= lApp->mBayerFlag; 
 
    // to get the save mode 
    if ( !UpdateData() ) 
        return; 
 
    // create a buffer for converting to RGB32 
    CyRGB32 lRGB32; 
    CyGrayscale8 lGS8( false ); 
    CyPixelType* lDestPixel = &lRGB32; 
 
    if ( ( lBuffer.GetFormat().GetTypeID() & CyPixelType::GRAYSCALE ) && 
         ( mSaveAsFormat != FORMAT_MOVIE ) ) 
        lDestPixel = &lGS8; 
 
    const CyPixelConverter* lConverter = 0; 
    if ( lDestPixel->HasConverterFrom( lBuffer.GetFormat() ) ) 
    { 
        lConverter = &lDestPixel->GetConverterFrom( lBuffer.GetFormat() ); 
    } 
    else if ( ( mSaveAsFormat == FORMAT_MOVIE ) || ( mSaveAsFormat == FORMAT_BITMAP ) ) 
    { 
        MessageBox( "Grabbed images cannot be converted to bitmap format!", "Error!", MB_OK | MB_ICONEXCLAMATION ); 
        return; 
    } 
 
    // Save start-up 
    switch( mSaveAsFormat ) 
    { 
        default: 
        case FORMAT_TEXT: 
            lFilename = mSequenceLocation; 
            lFilename += "\\ids.txt"; 
 
            // create the file 
            lFile = fopen( lFilename, "wt" ); 
            if ( lFile == NULL ) 
            { 
                MessageBox( "Cannot create id file!", 
                            "File Error!", 
                        MB_OK | MB_ICONEXCLAMATION ); 
                return; 
            } 
            break; 
 
        case FORMAT_RAW: 
        case FORMAT_BITMAP: 
            if ( mSequenceLocation.GetLength() == 0 ) 
            { 
                MessageBox( "You must select a valid location for the sequence!", 
                            "Invalid sequence location!", 
                            MB_OK | MB_ICONEXCLAMATION ); 
                return; 
            } 
            break; 
 
        case FORMAT_MOVIE: 
            if ( ( mVC != NULL ) && ( mVC->mFilename.length() == 0 ) ) 
            { 
                MessageBox( "You must select a valid location for the sequence!", 
                            "Invalid sequence location!", 
                            MB_OK | MB_ICONEXCLAMATION ); 
                return; 
            } 
 
            // Start the movie compressor 
            if ( mVC->Start( lBuffer.GetSizeX(), lBuffer.GetSizeY(), 4,  
				lPerfMonitor.GetFrameRate() ) != CY_RESULT_OK ) 
			{ 
				CyErrorInfo lEI; 
				mVC->GetErrorInfo( &lEI ); 
 
				MessageBox( lEI.mMessage, 
					        "Cannot start Video Compressor!", 
							MB_OK | MB_ICONEXCLAMATION ); 
				return; 
			} 
            break; 
    } 
 
    // Stop the display for the moment 
    unsigned long lQueueSize = lBuffer.GetQueueSize(); 
    bool lDisplaying = lApp->GetDisplay().IsDisplaying( lChannel.GetID() ); 
    if ( lDisplaying ) 
        lApp->GetDisplay().StopDisplaying( lChannel.GetID() ); 
    if ( mGSFrameCount < 256 ) 
        lBuffer.SetQueueSize( mGSFrameCount ); 
    else 
        lBuffer.SetQueueSize( 256 ); 
    lBuffer.ClearQueue(); 
 
    // prepare the progress 
    mSequenceProgress.SetRange32( 0, mGSFrameCount ); 
    mSequenceProgress.SetPos( 0 ); 
    mSequenceProgress.ShowWindow( mGSInfiniteFrames ? SW_HIDE : SW_SHOW ); 
    mSequenceProgressCancel.ShowWindow( SW_SHOW ); 
    mSequenceProgressCancel.EnableWindow( TRUE ); 
    mSaveAsText.ShowWindow( SW_HIDE ); 
    mSaveAsRaw.ShowWindow( SW_HIDE ); 
    mSaveAsBitmap.ShowWindow( SW_HIDE ); 
	mSaveAsMovie.ShowWindow( SW_HIDE ); 
	mMovieProperties.ShowWindow( SW_HIDE ); 
 
    GetDlgItem( IDC_ACQUISITION_GS_LOCATION )->SetFocus(); 
    bool lNormalDisplay = mNormalDisplay; 
    mNormalDisplay = false; 
    try 
    { 
        mSavingThread = new SavingThread( *this, lBuffer, lConverter, *lDestPixel, *mFilter, lFilename, lFile, lFlags ); 
        SetRunning( lGrabber.IsStarted( lChannel ) ); 
 
        // while the thread is running, process the message loop here.  check for 'ESC' 
        MSG lMsg; 
        bool lStop = false; 
        while ( ( !lStop ) && 
                ( mSavingThread->WaitUntilSignaled( 1 ) == CY_RESULT_TIMEOUT ) && 
                ( GetMessage( &lMsg, NULL, 0, 0 ) > 0 ) ) 
        { 
            TranslateMessage(&lMsg);  
            switch( lMsg.message ) 
            { 
                case WM_KEYDOWN: 
                    lStop = ( lMsg.wParam == VK_ESCAPE ); 
 
                default: 
                    DispatchMessage(&lMsg); 
                    break; 
            } 
        } 
    } 
    catch( CyErrorInfo& lEI ) 
    { 
        MessageBox( lEI.mMessage, "Error!", MB_OK | MB_ICONEXCLAMATION ); 
    } 
    catch( ... ) 
    { 
        MessageBox( "Unexpected exception!", "Error!", MB_OK | MB_ICONEXCLAMATION ); 
    } 
 
    delete mSavingThread; 
    mSavingThread = NULL; 
    mNormalDisplay = lNormalDisplay; 
    SetRunning( lGrabber.IsStarted( lChannel ) ); 
 
    // Save clean-up 
    switch( mSaveAsFormat ) 
    { 
        default: 
        case FORMAT_TEXT: 
            CyAssert( lFile != NULL ); 
            fclose( lFile ); 
            lFile = NULL; 
            break; 
 
        case FORMAT_RAW: 
        case FORMAT_BITMAP: 
            break; 
 
        case FORMAT_MOVIE: 
            mVC->Stop(); 
            break; 
    }; 
 
 
    // restart the display 
    if ( lDisplaying ) 
    { 
        unsigned long lFlags = lApp->mBayerFlag; 
        if ( mInvertDeinterlacer ) 
            lFlags |= CyDisplayEx::FLAG_INVERT_DEINTERLACING; 
        lApp->GetDisplay().StartDisplaying( lApp->GetBuffer( lChannel ), lChannel.GetID(), lFlags ); 
    } 
    lBuffer.SetQueueSize( lQueueSize ); 
 
    // reset the UI controls 
    mSequenceProgress.ShowWindow( SW_HIDE ); 
    mSequenceProgressCancel.ShowWindow( SW_HIDE ); 
    mSequenceProgressCancel.EnableWindow( FALSE ); 
    mSaveAsText.ShowWindow( SW_SHOW ); 
    mSaveAsRaw.ShowWindow( SW_SHOW ); 
    mSaveAsBitmap.ShowWindow( SW_SHOW ); 
	mSaveAsMovie.ShowWindow( SW_SHOW ); 
	mMovieProperties.ShowWindow( SW_SHOW ); 
} 
 
void CyAcquisitionPage::OnAcquisitionGsLocation()  
{ 
    // ask the user for the location for saving the files 
    BROWSEINFO lInfo; 
    memset( &lInfo, 0, sizeof ( BROWSEINFO ) ); 
    lInfo.hwndOwner = GetSafeHwnd(); 
    lInfo.lpszTitle = "Select folder to save images"; 
    //lInfo.ulFlags = BIF_NEWDIALOGSTYLE; 
    ITEMIDLIST* lBFFResult; 
    if ( ( lBFFResult = SHBrowseForFolder( &lInfo ) ) == NULL ) 
        return; 
 
    // Get the output directory location from the microsoft pointer 
    // We will need to release it using the IMalloc interface. 
    char lPath[ MAX_PATH ]; 
    SHGetPathFromIDList( lBFFResult, lPath ); 
    IMalloc* pMalloc; 
    SHGetMalloc(&pMalloc); 
    pMalloc->Free( lBFFResult ); 
    pMalloc->Release(); 
     
    mSequenceLocation = lPath; 
} 
 
void CyAcquisitionPage::OnSelchangeChannel()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyGrabber& lGrabber = lApp->GetGrabber(); 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ) , "" ); 
 
	SetRunning( lGrabber.IsStarted( lChannel ) ); 
} 
 
void CyAcquisitionPage::OnBadImagePassthrough()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyGrabber& lGrabber= lApp->GetGrabber(); 
 
    // Enable/disable the bad image passthrough 
    lGrabber.EnableBadImagePassthrough( mBadImagePassthrough.GetCheck() != 0 ); 
} 
 
void CyAcquisitionPage::OnIgnoreMissingPackets()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyGrabber& lGrabber= lApp->GetGrabber(); 
 
    // Enable/disable the bad image passthrough 
    lGrabber.IgnoreMissingPackets( mIgnoreMissingPackets.GetCheck() != 0 ); 
} 
 
void CyAcquisitionPage::OnDisplayFullscreen()  
{ 
	mFullscreenDisplayAdapterControl.EnableWindow( mDisplayFullscreenControl.GetCheck() && 
                                                   ( mFullscreenDisplayAdapterControl.GetCount() > 1 ) ); 
} 
 
void CyAcquisitionPage::OnMovieProperties() 
{ 
	CyMovieSelectionDialog lDlg; 
 
	if( mVC != NULL ) 
	{ 
		lDlg.mMoviePathname = mVC->mFilename.c_str(); 
		memcpy( &lDlg.mCOMPVARS, &mVC->mCOMPVARS, sizeof(COMPVARS) ); 
	} 
 
	if( lDlg.DoModal() != IDOK ) 
		return; 
 
	if( mVC == NULL ) 
		mVC = new CyVideoCompressor; 
 
	memcpy( &mVC->mCOMPVARS, &lDlg.mCOMPVARS, sizeof(COMPVARS) ); 
	mVC->mFilename = (LPCTSTR)lDlg.mMoviePathname; 
 
    this->mSaveAsFormat = FORMAT_MOVIE; 
	UpdateData(FALSE); 
} 
 
void CyAcquisitionPage::OnAcquisitionGsMovie()  
{ 
	// If the movie properties have not been set yet 
	if( mVC == NULL ) 
		OnMovieProperties(); 
 
	// If the user clicked on cancel 
	if( mVC == NULL ) 
		mMovieProperties.SetCheck( 0 ); 
} 
 
void CyAcquisitionPage::OnToolsColorAdjust()  
{ 
    if ( mColorAdjustment != NULL ) 
    { 
        mColorAdjustment->BringWindowToTop(); 
        return; 
    } 
 
    // Giving the desktop window as parent makes the window independent 
    // of this application and we can make the application on top of the 
    // window 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ) , "" ); 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyImageBuffer& lBuffer = lApp->GetBuffer( lChannel ); 
 
    mColorAdjustment = new ColorAdjustmentDialog( GetDesktopWindow( ), *this, *mFilter, lBuffer, lApp->mBayerFlag ); 
    mColorAdjustment->Create( ColorAdjustmentDialog::IDD, GetDesktopWindow( ) ); 
    mColorAdjustment->ShowWindow( SW_SHOW ); 
} 
 
 
void CyAcquisitionPage::OnAcquisitionGsInfinite()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ), "" ); 
 
    mGSFrames.EnableWindow( mGSInfiniteFramesControl.GetCheck() == 0 ); 
} 
 
void CyAcquisitionPage::OnSelchangeAcquisitionMode()  
{ 
    CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
    CyCameraInterface& lCamera = lApp->GetCamera(); 
    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ), "" ); 
 
    SetRunning( lCamera.IsStarted( lChannel ) ); 
} 
 
void CyAcquisitionPage::OnAcquisitionGsProgressCancelButton()  
{ 
    if ( mSavingThread != NULL ) 
        mSavingThread->StopThread(); 
} 
 
 
void CyAcquisitionPage::OnBayerInterpolation()  
{ 
    CyApp& lApp = *reinterpret_cast( AfxGetApp() ); 
    const CyChannelID lChannelID = static_cast( mChannels.GetItemData( mChannels.GetCurSel() ) ); 
 
    if ( lApp.mBayerFlag == 0 ) 
        lApp.mBayerFlag = CyDisplayEx::FLAG_BAYER_INTERPOLATE; 
    else 
        lApp.mBayerFlag = 0; 
    unsigned long lFlags = lApp.GetDisplay().GetSubDisplayFlag( lChannelID ); 
    lFlags &= ~CyDisplayEx::FLAG_BAYER_INTERPOLATE; 
    lFlags |= lApp.mBayerFlag; 
    lApp.GetDisplay().SetSubDisplayFlag( lChannelID, lFlags ); 
 
    if ( lApp.mBayerFlag == 0 ) 
        reinterpret_cast( AfxGetApp() )->mPropertySheet.GetMenu()->GetSubMenu( 3 )->CheckMenuItem( ID_BAYER_INTERPOLATION, MF_BYCOMMAND | MF_UNCHECKED ); 
    else 
        reinterpret_cast( AfxGetApp() )->mPropertySheet.GetMenu()->GetSubMenu( 3 )->CheckMenuItem( ID_BAYER_INTERPOLATION, MF_BYCOMMAND | MF_CHECKED ); 
} 
 
 
void CyAcquisitionPage::OnIpdCompute()  
{ 
    CString lChannelName; 
    mChannels.GetLBText( mChannels.GetCurSel(), lChannelName );    const CyChannel lChannel( (CyChannelID)mChannels.GetItemData( mChannels.GetCurSel() ) , (LPCTSTR) lChannelName ); 
    CyApp& lApp = *reinterpret_cast( AfxGetApp() ); 
    CyImageBuffer& lBuffer = lApp.GetBuffer( lChannel ); 
    CyConfig& lConfig = lApp.GetConfig(); 
 
    unsigned long        lPacketSize; 
    CyConfig::AccessMode lMode; 
    lConfig.GetPacketSize( &lPacketSize ); 
    lConfig.GetAccessMode( &lMode ); 
 
    CyInterPacketDelayDialog lDlg( lBuffer, lPacketSize, lMode, this ); 
 
    CString lTemp; 
    mInterPacketDelayControl.GetWindowText( lTemp ); 
    lDlg.mInterPacketDelay = static_cast( min( 65535, atol( (LPCTSTR)lTemp ) ) ); 
 
    // Show the dialog 
    if ( lDlg.DoModal() != IDOK ) 
        return; 
 
    lTemp.Format( "%lu", lDlg.mInterPacketDelay ); 
	mInterPacketDelayControl.SetWindowText( lTemp ); 
} 
 
void CyAcquisitionPage::OnChangeInterPacketDelay()  
{ 
    if ( IsWindow( mInterPacketDelayControl.GetSafeHwnd() ) ) 
    { 
        CyApp* lApp = reinterpret_cast( AfxGetApp() ); 
        CyDevice& lDevice = lApp->GetGrabber().GetDevice(); 
 
        // Set the delay on the device 
        CString lTemp; 
        mInterPacketDelayControl.GetWindowText( lTemp ); 
        int lDelay = atol( (LPCTSTR)lTemp ); 
        lDevice.SetInterPacketDelay( lDelay ); 
 
        // Set the throttle text 
        FormatInteger( lDelay * 30, lTemp ); 
        lTemp.Insert( 0, "Packet Delay (" ); 
        lTemp += " ns)"; 
        mThrottleText.SetWindowText( lTemp ); 
    } 
}