// PlaybackDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DVP2420Sample.h"
#include "PlaybackDlg.h"
#include "DVP2420SampleDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define WM_DECEOFNOTIFY WM_APP+1

HWND	hPlaybackWnd[MAXCHS];

enum
{
	StatusTimer = 33
};

char *FormatRefTime(char *sz, ULONG64 rt)
{
	int hrs, mins, secs;

//	rt += 0.49;
	hrs  =  (int)rt / 3600;
	mins = ((int)rt % 3600) / 60;
	secs = ((int)rt % 3600) % 60;

	sprintf(sz, "%02d:%02d:%02d\n", hrs, mins, secs);
    return sz;
}

/********************************************************
*
*	Decoding EndOfFile callback function
*
/********************************************************/

void DecEndOfFileProc(int nChNum)
{
	::SendNotifyMessage(hPlaybackWnd[nChNum], WM_DECEOFNOTIFY, nChNum, 0);
}

/********************************************************
*
*	Decodeing Failed callback function
*
/********************************************************/

void DecFailProc(int nChNum)
{
	CString errmsg;
	errmsg.Format(_T("Channel %d: Decoding failed!!\n"), nChNum);
	AfxMessageBox(errmsg);
}

/////////////////////////////////////////////////////////////////////////////
// CPlaybackDlg dialog


CPlaybackDlg::CPlaybackDlg(CWnd* pParent /*=NULL*/, int nChNum)
	: CDialog(CPlaybackDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPlaybackDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_nChNum = nChNum;
	m_nPlayRatio = 1;
	m_bChipInited = FALSE;
	m_bDecoded = FALSE;
	m_bPaused = FALSE;
	m_bBeginScroll = FALSE;
	m_dTrackBarScale = 1.0;
	m_pDisplayDlg = NULL;
}


void CPlaybackDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPlaybackDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CPlaybackDlg, CDialog)
	//{{AFX_MSG_MAP(CPlaybackDlg)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_PLAY_BTN, OnPlayBtn)
	ON_BN_CLICKED(IDC_OPEN_BTN, OnOpenBtn)
	ON_BN_CLICKED(IDC_FAST_BTN, OnFastBtn)
	ON_BN_CLICKED(IDC_STOP_BTN, OnStopBtn)
	ON_BN_CLICKED(IDC_REWIND_BTN, OnRewindBtn)
	ON_BN_CLICKED(IDC_SS_BTN, OnSsBtn)
	ON_WM_HSCROLL()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_DISPLAYWND_CHK, OnDisplaywndChk)
	ON_WM_CANCELMODE()
	ON_MESSAGE(WM_DECEOFNOTIFY, OnDecEOFNotify)
	ON_CBN_SELCHANGE(IDC_MPEG_COMBO, OnSelchangeMpegCombo)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CPlaybackDlg::SetDurationLen(ULONG64 rt)
{
	char szFmt[64];

    m_dTrackBarScale = 1;
    while (rt / m_dTrackBarScale > 30000)
    {
        m_dTrackBarScale *= 10;
    }

	((CSliderCtrl *)GetDlgItem(IDC_TRACKBAR))->SetRange(0, (int)(rt / m_dTrackBarScale), TRUE);
	((CSliderCtrl *)GetDlgItem(IDC_TRACKBAR))->SetTicFreq((int)(rt / m_dTrackBarScale) / 9);
	((CSliderCtrl *)GetDlgItem(IDC_TRACKBAR))->SetPageSize((int)(rt / m_dTrackBarScale) / 9);

	SetDlgItemText(IDC_TOTALTIME_TEXT, FormatRefTime(szFmt, rt));
}

void CPlaybackDlg::SetCurPos(ULONG64 rt)
{
	char szFmt[64];

	((CSliderCtrl *)GetDlgItem(IDC_TRACKBAR))->SetPos((int)(rt / m_dTrackBarScale));

	SetDlgItemText(IDC_CURTIME_TEXT, FormatRefTime(szFmt, rt));
}

/////////////////////////////////////////////////////////////////////////////
// CPlaybackDlg message handlers

void CPlaybackDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	switch(nIDEvent)
	{
		case StatusTimer:
		{
			if (m_bDecoded)
			{
				if (pDVPDecSDK && !m_bBeginScroll && !m_bPaused)
				{
					ULONG64 ulPlayedTime = 0;
					if (pDVPDecSDK->DVP2420_GetPlayedTime(m_nChNum, &ulPlayedTime) == DEC_SUCCEEDED)
						SetCurPos(ulPlayedTime);
				}
            }
			break;
		}
    }
	
	CDialog::OnTimer(nIDEvent);
}

BOOL CPlaybackDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	hPlaybackWnd[m_nChNum] = GetSafeHwnd();

	int bEncoded = ((CDVP2420SampleDlg *)GetParent())->m_bEncoded[m_nChNum];
	int bPreviewed = ((CDVP2420SampleDlg *)GetParent())->m_bPreviewed[m_nChNum];
	int retval = pDVPDecSDK->DVP2420_InitSDK();		//Initializes the DVP2420 Encoding SDK.
	if (retval == DEC_SUCCEEDED)
	{
		GetDlgItem(IDC_OPEN_BTN)->EnableWindow(TRUE);
		if (!bEncoded && !bPreviewed)
		{
			GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(TRUE);
		}

	    SetDurationLen(0);
		SetCurPos(0);
		SetTimer(StatusTimer, 500, NULL);
		GetCurrentDirectory(MAX_PATH, m_CurPath);
	}
	
	((CComboBox *)GetDlgItem(IDC_SIGNAL_COMBO))->SetCurSel(1);
	((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->SetCurSel(2);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CPlaybackDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
}

void CPlaybackDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	int nMPEGType = ((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->GetCurSel();

	if (nMPEGType != 0)
	{

		switch (nSBCode)
		{
			case SB_LEFT:
				break;
			case SB_RIGHT:
				break;
			case SB_LINELEFT:
			case SB_LINERIGHT:
			case SB_PAGEUP:
			case SB_PAGEDOWN:
			{
				int SliderPos = ((CSliderCtrl *)GetDlgItem(IDC_TRACKBAR))->GetPos();
				if (pDVPDecSDK)
				{
					m_bBeginScroll = TRUE;
					pDVPDecSDK->DVP2420_SetPlayPos(m_nChNum, SliderPos*m_dTrackBarScale);
					Sleep(3000);
					m_bBeginScroll = FALSE;
				}
				break;
			}
			case SB_THUMBTRACK:
			{
				m_bBeginScroll = TRUE;
				break;
			}
			case SB_THUMBPOSITION:
			{
				if (pDVPDecSDK)
				{
					pDVPDecSDK->DVP2420_SetPlayPos(m_nChNum, nPos*m_dTrackBarScale);
					if (nMPEGType == 1)	//MPEG2
						Sleep(3000);
					else if (nMPEGType == 2)	//MPEG4
						Sleep(2000);
				}

				m_bBeginScroll = FALSE;
				break;
			}
		}
	}
	
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CPlaybackDlg::OnOpenBtn() 
{
	// TODO: Add your control notification handler code here
	CFileDialog FileDlg (TRUE, "mpg", "*.mpg", 
		OFN_FILEMUSTEXIST| OFN_HIDEREADONLY, "MPEG Files (*.mpg)", this);

	if (FileDlg.DoModal() == IDOK)
	{
		strncpy(m_FileName, FileDlg.GetPathName(), MAX_PATH);
		FileDlg.GetPathName().ReleaseBuffer();
		SetCurrentDirectory(m_CurPath);
		GetDlgItem(IDC_PLAY_BTN)->EnableWindow(TRUE);
	}	
}

void CPlaybackDlg::OnPlayBtn() 
{
	// TODO: Add your control notification handler code here
	int nSignalType = ((CComboBox *)GetDlgItem(IDC_SIGNAL_COMBO))->GetCurSel();
	int nMPEGType = ((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->GetCurSel();
	BOOL bDisplayWnd = ((CButton *)GetDlgItem(IDC_DISPLAYWND_CHK))->GetCheck();

	if (m_bDecoded)
	{
		pDVPDecSDK->DVP2420_Pause(m_nChNum);
		if (!m_bPaused)
		{
			SetDlgItemText(IDC_PLAY_BTN, "Play");
			m_bPaused = TRUE;
		}
		else
		{
			m_nPlayRatio = 1;
			SetDlgItemText(IDC_RATIO_TEXT, "1");
			SetDlgItemText(IDC_PLAY_BTN, "Pause");
			m_bPaused = FALSE;
		}

		return;
	}

	switch (nSignalType)
	{
		case 0:
			nSignalType = PAL;
			break;
		case 1:
			nSignalType = NTSC;
			break;
	}

	int nWidth = 320; 
	int nHeight = 240;
	switch (nMPEGType)
	{
		case 0:
			nMPEGType = MPEG1;
			nWidth = 352;
			nHeight = (nSignalType == NTSC) ? 240:288;
			break;
		case 1:
			nMPEGType = MPEG2;
			pDVPDecSDK->DVP2420_GetVideoResolution(m_FileName, &nWidth, &nHeight);	//This function only support MPEG2 and MPEG4.
			break;
		case 2:
			nMPEGType = MPEG4;
			pDVPDecSDK->DVP2420_GetVideoResolution(m_FileName, &nWidth, &nHeight);	//This function only support MPEG2 and MPEG4.
			break;
	}

	//Initialize chip
	if (!m_bChipInited) {
		if (pDVPDecSDK->DVP2420_InitChips(m_nChNum) != DEC_SUCCEEDED) {
			AfxMessageBox("Initialize chip failed!\n");
			return;
		}
		else
			m_bChipInited = TRUE;
	}

	if (!bSkipDL[m_nChNum]) {
		//Download firmware
		if (pDVPDecSDK->DVP2420_DownloadFW(m_nChNum) != DEC_SUCCEEDED) {
			//Release chip
			if (pDVPDecSDK->DVP2420_ReleaseChips(m_nChNum) == DEC_SUCCEEDED)
				m_bChipInited = FALSE;

			AfxMessageBox("Download firmware failed!\n");
			return;
		}
		bSkipDL[m_nChNum] = TRUE;
	}

	if (pDVPDecSDK->DVP2420_SetSignalType(m_nChNum, nSignalType) != DEC_SUCCEEDED)
		TRACE("DVP2420_SetSignalType() Failed!!");

	if (pDVPDecSDK->DVP2420_SetMPEGType(m_nChNum, nMPEGType) != DEC_SUCCEEDED)
		TRACE("DVP2420_SetMPEGType() Failed!!");

	//Register Decoding EOF callback function
	pDVPDecSDK->DVP2420_RegDecEndOfFileCB(DecEndOfFileProc);
	//Register DecodingFail callback function
	pDVPDecSDK->DVP2420_RegDecFailCB(DecFailProc);

	if (bDisplayWnd)
	{
		if (!m_pDisplayDlg)
		{
			m_pDisplayDlg = new CDialog();
			m_pDisplayDlg->Create(IDD_DISPLAY_DLG);
			m_pDisplayDlg->ShowWindow(SW_SHOW);
			m_pDisplayDlg->SetWindowText(m_FileName);
		}
	}
	else
		m_pDisplayDlg = NULL;

	if (m_pDisplayDlg)
	{
	    RECT rcW, rcC;
		int xExtra, yExtra;
	    m_pDisplayDlg->GetWindowRect(&rcW);
		m_pDisplayDlg->GetClientRect(&rcC);
	    xExtra = rcW.right - rcW.left - rcC.right;
		yExtra = rcW.bottom - rcW.top - rcC.bottom;
		GetWindowRect(&rcW);
		m_pDisplayDlg->SetWindowPos(NULL, rcW.left, rcW.bottom, nWidth+xExtra, nHeight+yExtra, SWP_NOZORDER);
	}

	//Start video decode
	if (pDVPDecSDK->DVP2420_StartDecode(m_nChNum, m_FileName, m_pDisplayDlg->GetSafeHwnd()) != DEC_SUCCEEDED) {
		//Release chip
		if (pDVPDecSDK->DVP2420_ReleaseChips(m_nChNum) == DEC_SUCCEEDED)
			m_bChipInited = FALSE;

		AfxMessageBox("Start decoding failed!\n");
		return;
	}

	m_nPlayRatio = 1;
	SetDlgItemText(IDC_RATIO_TEXT, "1");

	ULONG64 nFileTime;
	if (pDVPDecSDK->DVP2420_GetFileTime(m_nChNum, &nFileTime) == DEC_SUCCEEDED)
		SetDurationLen(nFileTime);
	GetDlgItem(IDC_SIGNAL_COMBO)->EnableWindow(FALSE);
	GetDlgItem(IDC_MPEG_COMBO)->EnableWindow(FALSE);
	GetDlgItem(IDC_STOP_BTN)->EnableWindow(TRUE);
	if (nMPEGType != MPEG1)
	{
		GetDlgItem(IDC_REWIND_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_FAST_BTN)->EnableWindow(TRUE);
	}
	GetDlgItem(IDC_SS_BTN)->EnableWindow(TRUE);
	GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(FALSE);
	SetDlgItemText(IDC_PLAY_BTN, "Pause");
	m_bPaused = FALSE;
	m_bDecoded = TRUE;
}

void CPlaybackDlg::OnStopBtn() 
{
	// TODO: Add your control notification handler code here
	int bEncoded = ((CDVP2420SampleDlg *)GetParent())->m_bEncoded[m_nChNum];
	int bPreviewed = ((CDVP2420SampleDlg *)GetParent())->m_bPreviewed[m_nChNum];

	if (m_bDecoded)
	{
		if (pDVPDecSDK->DVP2420_StopDecode(m_nChNum) != DEC_SUCCEEDED)
		{
			AfxMessageBox("Stop decodeing failed!\n");
			return;
		}

		if (pDVPDecSDK->DVP2420_ReleaseChips(m_nChNum) != DEC_SUCCEEDED)
		{
			AfxMessageBox("Release chip failed!\n");
			return;
		}

		if (m_pDisplayDlg)
		{
			m_pDisplayDlg->DestroyWindow();
			delete m_pDisplayDlg;
			m_pDisplayDlg = NULL;
		}

		char szFmt[64];
		m_nPlayRatio = 1;
		SetDlgItemText(IDC_RATIO_TEXT, "1");
		((CSliderCtrl *)GetDlgItem(IDC_TRACKBAR))->SetPos(0);
		SetDlgItemText(IDC_CURTIME_TEXT, FormatRefTime(szFmt, 0));

		GetDlgItem(IDC_SIGNAL_COMBO)->EnableWindow(TRUE);
		GetDlgItem(IDC_MPEG_COMBO)->EnableWindow(TRUE);
		GetDlgItem(IDC_STOP_BTN)->EnableWindow(FALSE);
		GetDlgItem(IDC_REWIND_BTN)->EnableWindow(FALSE);
		GetDlgItem(IDC_FAST_BTN)->EnableWindow(FALSE);
		GetDlgItem(IDC_SS_BTN)->EnableWindow(FALSE);
		if (!bEncoded && !bPreviewed)
			GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(TRUE);
		SetDlgItemText(IDC_PLAY_BTN, "Play");
		m_bDecoded = FALSE;
		m_bChipInited = FALSE;
	}
}

void CPlaybackDlg::OnFastBtn() 
{
	// TODO: Add your control notification handler code here
	if (m_nPlayRatio == 8)
		return;

	pDVPDecSDK->DVP2420_Fast(m_nChNum);
	m_nPlayRatio *= 2;
	char sRatio[5];
	itoa(m_nPlayRatio, sRatio, 10);
	SetDlgItemText(IDC_RATIO_TEXT, sRatio);
}

void CPlaybackDlg::OnRewindBtn() 
{
	// TODO: Add your control notification handler code here
	pDVPDecSDK->DVP2420_Rewind(m_nChNum);
}

void CPlaybackDlg::OnSsBtn() 
{
	// TODO: Add your control notification handler code here
	pDVPDecSDK->DVP2420_SingleStep(m_nChNum);
}

void CPlaybackDlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	if (!((CDVP2420SampleDlg *)GetParent())->m_bEncoded[m_nChNum])
	{
		GetParent()->GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(TRUE);
	}

	GetParent()->GetDlgItem(IDC_PREVIEW_BTN)->EnableWindow(TRUE);
	GetParent()->GetDlgItem(IDC_PLAYBACK_BTN)->EnableWindow(TRUE);
	((CDVP2420SampleDlg *)GetParent())->m_bDecoded[m_nChNum] = FALSE;
	
	CDialog::OnCancel();
}

void CPlaybackDlg::OnSelchangeMpegCombo() 
{
	// TODO: Add your control notification handler code here
	int nMPEGType = ((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->GetCurSel();
	if (nMPEGType == 0)
	{
		GetDlgItem(IDC_FAST_BTN)->EnableWindow(FALSE);
		GetDlgItem(IDC_REWIND_BTN)->EnableWindow(FALSE);
	}
	else
	{
		if (m_bDecoded)
		{
			GetDlgItem(IDC_FAST_BTN)->EnableWindow(TRUE);
			GetDlgItem(IDC_REWIND_BTN)->EnableWindow(TRUE);
		}
	}
}

void CPlaybackDlg::OnDisplaywndChk() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetParent()->GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();
	BOOL bDisplayWnd = ((CButton*)GetDlgItem(IDC_DISPLAYWND_CHK))->GetCheck();

	if (bDisplayWnd && nChNum == m_nChNum)
	{
		GetParent()->GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(FALSE);
		GetParent()->GetDlgItem(IDC_PREVIEW_BTN)->EnableWindow(FALSE);
	}
	else
	{
		GetParent()->GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(TRUE);
		GetParent()->GetDlgItem(IDC_PREVIEW_BTN)->EnableWindow(TRUE);
	}
}

LRESULT CPlaybackDlg::OnDecEOFNotify(WPARAM wParam, LPARAM lParam)
{
	int nChNum = (int)wParam;
	int bEncoded = ((CDVP2420SampleDlg *)GetParent())->m_bEncoded[nChNum];
	int bPreviewed = ((CDVP2420SampleDlg *)GetParent())->m_bPreviewed[nChNum];

	if (pDVPDecSDK->DVP2420_ReleaseChips(nChNum) != DEC_SUCCEEDED)
	{
		AfxMessageBox("Release chip failed!\n");
		return 0;
	}

	if (m_pDisplayDlg)
	{
		m_pDisplayDlg->DestroyWindow();
		delete m_pDisplayDlg;
		m_pDisplayDlg = NULL;
	}

	char szFmt[64];
	m_nPlayRatio = 1;
	SetDlgItemText(IDC_RATIO_TEXT, "1");
	((CSliderCtrl *)GetDlgItem(IDC_TRACKBAR))->SetPos(0);
	SetDlgItemText(IDC_CURTIME_TEXT, FormatRefTime(szFmt, 0));

	GetDlgItem(IDC_SIGNAL_COMBO)->EnableWindow(TRUE);
	GetDlgItem(IDC_MPEG_COMBO)->EnableWindow(TRUE);
	GetDlgItem(IDC_STOP_BTN)->EnableWindow(FALSE);
	GetDlgItem(IDC_REWIND_BTN)->EnableWindow(FALSE);
	GetDlgItem(IDC_FAST_BTN)->EnableWindow(FALSE);
	GetDlgItem(IDC_SS_BTN)->EnableWindow(FALSE);
	if (!bEncoded && !bPreviewed)
		GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(TRUE);
	SetDlgItemText(IDC_PLAY_BTN, "Play");
	m_bDecoded = FALSE;
	m_bChipInited = FALSE;
	return 0;
}
