// TestVPlayerDlg.cpp : implementation file
//

#include "stdafx.h"
#include "TestVPlayer.h"
#include "TestVPlayerDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#include "SDK\VideoPlayerSDK_i.c"


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CTestVPlayerDlg dialog




CTestVPlayerDlg::CTestVPlayerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTestVPlayerDlg::IDD, pParent)
{
	m_nVPNumber = 0;
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTestVPlayerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_VPLIST, m_VPCombo);
	DDX_Control(pDX, IDC_FILENAME, m_ctrlFileName);
	DDX_Control(pDX, IDC_LOOP_COUNT, m_LoopCount);
	DDX_Control(pDX, IDC_REST, m_RestTime);
}

BEGIN_MESSAGE_MAP(CTestVPlayerDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BROWSE, &CTestVPlayerDlg::OnBnClickedBrowse)
	ON_BN_CLICKED(IDC_PLAY, &CTestVPlayerDlg::OnBnClickedPlay)
	ON_BN_CLICKED(IDC_PAUSE, &CTestVPlayerDlg::OnBnClickedPause)
	ON_BN_CLICKED(IDC_STOP, &CTestVPlayerDlg::OnBnClickedStop)
	ON_WM_TIMER()
	ON_CBN_SELCHANGE(IDC_VPLIST, &CTestVPlayerDlg::OnCbnSelchangeVplist)
END_MESSAGE_MAP()


// CTestVPlayerDlg message handlers

BOOL CTestVPlayerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	HRESULT hres;
	hres = InitVPList();
	if( hres != S_OK ) {
		MessageBox(_T("there is no VideoPlayer"),_T("Test Video Player"), MB_ICONSTOP);
		EndDialog(IDCANCEL);
	}
	for( int i=0; i<m_nVPNumber; i++ )  m_VPCombo.AddString(m_VPInfo[i].m_szUserName);
	m_VPCombo.SetCurSel(m_nVPNumber>0 ? 0 : -1);
	OnCbnSelchangeVplist();
	m_fLastMovieDuration = 0;
	m_LoopCount.SetWindowText(_T(""));
	m_RestTime.SetWindowText(_T(""));

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CTestVPlayerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CTestVPlayerDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CTestVPlayerDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

HRESULT CTestVPlayerDlg::InitVPList()
{
	CComPtr<ISLTMEnumVideoPlayer4TE> pIEnumVP;
	HRESULT hres = pIEnumVP.CoCreateInstance(CLSID_SLTMEnumVideoPlayer4TE);
	if( hres != S_OK )  return hres;
	long cnt=0;
	hres = pIEnumVP->get_Count(&cnt);
	ATLASSERT(hres==S_OK);
	if( cnt > 16 )  cnt = 16;
	for( int i=0; i<cnt; i++ ) {
		CComBSTR bstr1,bstr2;
		hres = pIEnumVP->get_Name(i,&bstr1);
		ATLASSERT(hres==S_OK);
		m_VPInfo[i].m_szUserName = bstr1;
		hres = pIEnumVP->get_RegName(i,&bstr2);
		ATLASSERT(hres==S_OK);
		m_VPInfo[i].m_szRegName = bstr2;
		hres = pIEnumVP->get_Type(i,&m_VPInfo[i].m_CLSID);
		ATLASSERT(hres==S_OK);
		hres = pIEnumVP->get_Index(i,&m_VPInfo[i].m_nIndex);
		ATLASSERT(hres==S_OK);
	}
	m_nVPNumber = cnt;
	return m_nVPNumber > 0 ? S_OK : S_FALSE;
}

void CTestVPlayerDlg::OnCbnSelchangeVplist()
{
	int n = m_VPCombo.GetCurSel();
	HRESULT hres = CreateVPlayerTE(m_VPInfo[n].m_CLSID, m_VPInfo[n].m_nIndex);
	if( hres != S_OK ) {
		CString str;  str.Format(_T("Can not initialize VideoPlayer!\n\nErrorCode = %d(0x%X)"),hres,hres);
		MessageBox(str,_T("Test Video Player"), MB_ICONSTOP);
	}
}

HRESULT CTestVPlayerDlg::CreateVPlayerTE(CLSID clsidTE, int index)
{
	m_pVPlayer = NULL;
	CComPtr<ISLTMVideoPlayer4TE> pIVPlayer;
	HRESULT hres = pIVPlayer.CoCreateInstance(CLSID_SLTMVideoPlayer4TE_OEM);
	if( hres != S_OK )  return hres;
	hres = pIVPlayer->Init4TitleCore(clsidTE, index, 100);
	if( hres != S_OK )  return hres;
	hres = pIVPlayer.QueryInterface(&m_pVPlayer);
	if( hres != S_OK )  return hres;
	return S_OK;
}

void CTestVPlayerDlg::ReleaseVPlayer()
{
	m_pVPlayer = NULL;
}


void CTestVPlayerDlg::OnBnClickedBrowse()
{
    OPENFILENAME ofn;  ZeroMemory(&ofn,sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = m_hWnd;
	TCHAR filter[]=_T("Movie files (*.avi)|*.avi|"), buf[MAX_PATH];
	for( int i=0; filter[i]; i++ )  if( filter[i]=='|' )  filter[i] = 0;
	buf[0] = 0;
    ofn.lpstrFilter = filter;
    ofn.nFilterIndex = 0;
    ofn.lpstrFile = buf;
    ofn.nMaxFile = MAX_PATH;
	ofn.lpstrTitle = _T("Select Movie");
	ofn.Flags = OFN_FILEMUSTEXIST;
	if( ::GetOpenFileName(&ofn) ) {
		m_fLastMovieDuration = 0;
		m_sFileName = CString(ofn.lpstrFile);
		m_ctrlFileName.SetWindowText(m_sFileName);
	}
}

void CTestVPlayerDlg::OnBnClickedPlay()
{
	HRESULT hres = Play();
	if( hres != S_OK ) {
		CString str;  str.Format(_T("Error on current movie playback starting!\n\nErrorCode = %d(0x%X)"),hres,hres);
		MessageBox(str,_T("Play"));
	}
}

void CTestVPlayerDlg::OnBnClickedPause()
{
	HRESULT hres = Pause();
	if( hres != S_OK ) {
		CString str;  str.Format(_T("Error on current playback pausing!\n\nErrorCode = %d(0x%X)"),hres,hres);
		MessageBox(str,_T("Pause"));
	}
}

void CTestVPlayerDlg::OnBnClickedStop()
{
	HRESULT hres = Stop();
	if( hres != S_OK ) {
		CString str;  str.Format(_T("Error on current playback stop (make show LIVE)!\n\nErrorCode = %d(0x%X)"),hres,hres);
		MessageBox(str,_T("Stop"));
	}
}

void CTestVPlayerDlg::OnTimer(UINT_PTR nIDEvent)
{
	if( !m_bInTimer ) {
		m_bInTimer = true;
		CheckTime();	// looped playback whole movie
//		CheckTime2();	// looped playback begin of the movie
		CString str;  str.Format(_T("%d"),m_nLoopCount);
		m_LoopCount.SetWindowText(str);
		str.Format(_T("%.3f"),m_fRestTime);
		m_RestTime.SetWindowText(str);
		m_bInTimer = false;
	}
	CDialog::OnTimer(nIDEvent);
}

HRESULT CTestVPlayerDlg::Play()
{
	SLTMPlaybackState state;
	HRESULT hres = m_pVPlayer->get_PlaybackState(&state);
	if( hres != S_OK )  return hres;
	switch(state) {
		case SLTMPlaybackStopped:
		case SLTMPlaybackPlaying:
			return StartPlayback();
		case SLTMPlaybackPreparing:
		case SLTMPlaybackPrepared:
			return E_UNEXPECTED;
		case SLTMPlaybackPaused:
			return Unpause();
		case SLTMPlaybackStopOnError:
			return Stop();
		default:
			return E_UNEXPECTED;
	};
}
HRESULT CTestVPlayerDlg::Pause()
{
	HRESULT hres = m_pVPlayer->PauseVideo();
	if( hres != S_OK )  return hres;
	return S_OK;
}

HRESULT CTestVPlayerDlg::Unpause()
{
	HRESULT hres = m_pVPlayer->UnpauseVideo();
	if( hres != S_OK )  return hres;
	return S_OK;
}

HRESULT CTestVPlayerDlg::Stop()
{
	KillTimer(1);
	HRESULT hres = m_pVPlayer->ShowLive(0,0.1);
	if( hres != S_OK )  return hres;
	return S_OK;
}

HRESULT CTestVPlayerDlg::StartPlayback()
{
	m_nLoopCount = 0;
	m_fRestTime = 0;
	m_LoopCount.SetWindowText(_T("0"));
	m_RestTime.SetWindowText(_T("---"));
	// prepare movie
	CComBSTR bstr(m_sFileName);
	HRESULT hres = m_pVPlayer->PrepareVideo(bstr,0,0,SLTMVPAudioFile_Default,&m_fLastMovieDuration);
	if( hres != S_OK )  return hres;
	for( int i=0; i<20; i++ ) {
		Sleep(100);
		SLTMVideoPlayerPrepareState state;
		hres = m_pVPlayer->get_PrepareState(&state);
		if( hres != S_OK )  return hres;
		if( state==SLTMVideoPlayerPreparingVideo )  continue;
		else if( state==SLTMVideoPlayerPreparedVideo )  break;
		else  return E_FAIL;
	}
	// start playback
	hres = m_pVPlayer->PlayVideo(0,0.1);
	if( hres != S_OK )  return hres;
	// start timer
	m_bInTimer = false;
	SetTimer(1,100,NULL);
	return S_OK;
}

HRESULT CTestVPlayerDlg::CheckTime()
{
	// check playback state
	SLTMPlaybackState state;
	HRESULT hres = m_pVPlayer->get_PlaybackState(&state);
	if( hres != S_OK )  return hres;
	if( state != SLTMPlaybackPlaying )  return S_FALSE;
	// check rest duration
	double end_time;
	hres = m_pVPlayer->get_RestDuration(&end_time,&m_fRestTime);
	if( hres != S_OK )  return hres;
	if( m_fRestTime > 1.0 )  return S_OK;
	// prepare next movie
	CComBSTR bstr(m_sFileName);  double time;
	hres = m_pVPlayer->PrepareVideo(bstr,0,0,SLTMVPAudioFile_Default,&time);
	if( hres != S_OK )  return hres;
	for( int i=0; i<20; i++ ) {
		Sleep(100);
		SLTMVideoPlayerPrepareState state;
		hres = m_pVPlayer->get_PrepareState(&state);
		if( hres != S_OK )  return hres;
		if( state==SLTMVideoPlayerPreparingVideo )  continue;
		else if( state==SLTMVideoPlayerPreparedVideo )  break;
		else  return E_FAIL;
	}
	// play the movie after the previous movie
	hres = m_pVPlayer->PlayVideo(end_time-0.1, 0.1);
	if( hres != S_OK )  return hres;
	m_nLoopCount++;
	return S_OK;
}

HRESULT CTestVPlayerDlg::CheckTime2()
{
	// check playback state
	SLTMPlaybackState state;
	HRESULT hres = m_pVPlayer->get_PlaybackState(&state);
	if( hres != S_OK )  return hres;
	if( state != SLTMPlaybackPlaying )  return S_FALSE;
	// check rest duration
	double end_time;
	hres = m_pVPlayer->get_RestDuration(&end_time,&m_fRestTime);
	if( hres != S_OK )  return hres;
	if( m_fRestTime > 4.0  &&  m_fRestTime > m_fLastMovieDuration-3.0 )  return S_OK;
	// prepare next movie
	CComBSTR bstr(m_sFileName);  double time;
	hres = m_pVPlayer->PrepareVideo(bstr,0,0,SLTMVPAudioFile_Default,&time);
	if( hres != S_OK )  return hres;
	for( int i=0; i<20; i++ ) {
		Sleep(100);
		SLTMVideoPlayerPrepareState state;
		hres = m_pVPlayer->get_PrepareState(&state);
		if( hres != S_OK )  return hres;
		if( state==SLTMVideoPlayerPreparingVideo )  continue;
		else if( state==SLTMVideoPlayerPreparedVideo )  break;
		else  return E_FAIL;
	}
	// play the movie through 0.3 second (not wait finish of previous movie)
	hres = m_pVPlayer->PlayVideo(-0.3, 0.1);
	if( hres != S_OK )  return hres;
	m_nLoopCount++;
	Sleep(500);
	return S_OK;
}
