// Copyright (c) 1998-2005 B2C2, Incorporated.  All Rights Reserved.
//
// THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF B2C2, INCORPORATED.
// The copyright notice above does not evidence any
// actual or intended publication of such source code.
//
// This file is proprietary source code of B2C2, Incorporated. and is released pursuant to and
// subject to the restrictions of the non-disclosure agreement and license contract entered
// into by the parties.
//
//
// AVPlaybackCtrl.cpp: implementation of the CAVPlaybackCtrl class.
//
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "AVPlaybackCtrl.h"
#include "TunerCtrlDlg.h"

#include "B2FilterGraphHandler.h"
#include "B2FilterGraphException.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


E_PVR_CALLBACK_STATE CAVPlaybackCtrl::m_ePvrStateChange = E_PVR_CALLBACK_STATE (-1);

static int iRecordState = FALSE;

/*-----------------------------------------------------------------------------------------------*/
/*	FUNCTION:	CAVPlaybackCtrl (CONSTRUCTOR)
*/
CAVPlaybackCtrl::CAVPlaybackCtrl()
{
	m_pB2FilterGraph = NULL;
	m_eState = STATE_UNKNOWN;

	m_cstrRecordPathName.Empty();

	ZeroMemory( m_alPids, sizeof (m_alPids));

	m_bAutoDeleteTimeshift = TRUE;
	m_bAutoStartTimeshift = FALSE;

	m_i64PlaybackFilePosition = 0;
	m_i64RecordFileSize = 0;
}

/*-----------------------------------------------------------------------------------------------*/
/*	FUNCTION:	~CAVPlaybackCtrl (DESTRUCTOR)
*/
CAVPlaybackCtrl::~CAVPlaybackCtrl()
{
	Release();
}

/*-----------------------------------------------------------------------------------------------*/

BOOL CAVPlaybackCtrl::Initialize(HWND hVideoWnd)
{
	// Update state
	m_eState = STATE_INITIALIZING;

	try
	{
		m_pB2FilterGraph->GetAudioVideoOutPins();

		m_pB2FilterGraph->SetAudioVideoPids( m_iAudioPID , m_iVideoPID);

		m_pB2FilterGraph->RenderAudioVideoPins();

		m_pB2FilterGraph->SetVideoWindow( hVideoWnd);

		// Set Callback for Timeshift State Change
		m_pB2FilterGraph->GetTimeshiftControl()->SetCallback(&CAVPlaybackCtrl::UpdatePvrState);

		// Configure Auto-Record with Play option 

		int iParameter = m_bAutoStartTimeshift ? 1 : 0;
		m_pB2FilterGraph->GetTimeshiftControl()->SetOption( PVR_AUTO_RECORD_WITH_PLAY, (PVOID) &iParameter );;

		// Configure Auto-Delete on Stop option

		iParameter = m_bAutoDeleteTimeshift ? 1 : 0;
		m_pB2FilterGraph->GetTimeshiftControl()->SetOption( PVR_AUTO_DELETE_RECORD_FILE, (PVOID) &iParameter );;

	} catch (CB2FilterGraphException *pErr)
	{
		pErr->ReportError();
		pErr->Delete();
	}

	m_eState = STATE_STOP;

	return TRUE;
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::Release()
{
	// Remove Callback for Timeshift State Change
	m_pB2FilterGraph->GetTimeshiftControl()->SetCallback(NULL);
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::Pause()
{
	ASSERT( m_pB2FilterGraph);
	if (!m_pB2FilterGraph)
	{
		return;
	}
	try
	{
		if (m_eState == STATE_LIVE_RECORD || m_eState == STATE_LIVE_PLAY)
		{
			m_eState = STATE_LIVE_PAUSE;
		}
		else if (m_eState == STATE_TIMESHIFT_PLAY)
		{
			m_eState = STATE_TIMESHIFT_PAUSE;
		}

		m_pB2FilterGraph->Pause();

	} catch (CB2FilterGraphException *pErr)
	{
		pErr->ReportError();
		pErr->Delete();
	}
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::GenerateTimeStampedFilename( CString* pcsRecordPathName, char* szPath, char* szRootName )
{
	COleDateTime Time = COleDateTime::GetCurrentTime();

	char szDate[100];
	sprintf(szDate,"_%d-%02d-%02d_%02d-%02d-%02d", Time.GetYear(),Time.GetMonth(),Time.GetDay(),Time.GetHour(),
			Time.GetMinute(),Time.GetSecond());

	*pcsRecordPathName = "";
	*pcsRecordPathName = *pcsRecordPathName + szPath + szRootName + szDate + ".ts";
}

/*-----------------------------------------------------------------------------------------------*/

BOOL CAVPlaybackCtrl::UpdateVideoSize(HWND hVideoWnd)
{
	BOOL bRet = FALSE;
	try
	{
		m_pB2FilterGraph->UpdateVideoSize( hVideoWnd);

		bRet = TRUE;
	} catch (CB2FilterGraphException *pErr)
	{
		pErr->ReportError();
		pErr->Delete();
	}

	return bRet;
}

///////////////////////////////////////////////////////////////////////////////
void CAVPlaybackCtrl::GetStatistics()
{
	// Get Record File Size
	HRESULT hr = m_pB2FilterGraph->GetTimeshiftControl()->GetFileSize( &m_i64RecordFileSize );

	if (FAILED (hr))
	{
		CString cstrTemp;
		cstrTemp.Format( _T("B2C2 MPEG2 TimeshiftCtrl. Interface GetFileSize method failed, error: 0x%8.8x"), hr);
//		MessageBox(cstrTemp, "SDK Demo Error", MB_OK);
	}

	// Get Playback File Position
	hr = m_pB2FilterGraph->GetTimeshiftControl()->GetFilePosition( &m_i64PlaybackFilePosition );

	if (FAILED (hr))
	{
		CString cstrTemp;
		cstrTemp.Format( _T("B2C2 MPEG2 TimeshiftCtrl. Interface GetFilePosition method failed, error: 0x%8.8x"), hr);
//		MessageBox(cstrTemp, "SDK Demo Error", MB_OK);
	}
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::Play()
{
	ASSERT( m_pB2FilterGraph);
	if (!m_pB2FilterGraph)
	{
		return;
	}

	if (m_eState == STATE_LIVE_PAUSE || m_eState == STATE_TIMESHIFT_PAUSE)
	{
		m_pB2FilterGraph->Run();

		// Update state
		m_eState = STATE_TIMESHIFT_PLAY;
	}
	else if (m_eState == STATE_STOP)
	{
		try
		{
			// Setup the PVR Filename
			if (m_bAutoStartTimeshift)
			{
				// Generate Timeshift file name
				GenerateTimeStampedFilename(&m_cstrRecordPathName, "C:\\", "Timeshift" );
			}
			else
			{
				m_cstrRecordPathName = "C:\\";
			}

			WCHAR szFilePath[256];

			// Convert the string
			mbstowcs ( szFilePath , m_cstrRecordPathName, strlen(m_cstrRecordPathName)+1);

			m_pB2FilterGraph->GetTimeshiftControl()->SetFilename( szFilePath );


			// Start the Filter Graph
			m_pB2FilterGraph->Run();

			// Set the Application State
			if (m_bAutoStartTimeshift)
			{
				m_eState = STATE_LIVE_RECORD;
			}
			else
			{
				// Update state
				m_eState = STATE_LIVE_PLAY;
			}

		} catch (CB2FilterGraphException *pErr)
		{
			pErr->ReportError();
			pErr->Delete();
		}

	}
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::Stop()
{
	// Check if Playing Live stream
	switch (m_eState)
	{
		case STATE_TIMESHIFT_PLAY:
		case STATE_TIMESHIFT_PAUSE:
		case STATE_LIVE_RECORD:
		case STATE_LIVE_PAUSE:
		{
			try
			{
				// Stop the Filter Graph
				m_pB2FilterGraph->Stop();

				m_eState = STATE_STOP;

			} catch (CB2FilterGraphException *pErr)
			{
				pErr->ReportError();
				pErr->Delete();
			}
	
			break;
		}
		case STATE_LIVE_PLAY:
		{
			try
			{
				m_pB2FilterGraph->Stop();

			} catch (CB2FilterGraphException *pErr)
			{
				pErr->ReportError();
				pErr->Delete();
			}
			m_eState = STATE_STOP;

			break;
		}
		case STATE_STOP:
		{
			break;
		}	
		default:
		{
			ASSERT(FALSE);
			break;
		}
	}
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::CheckTimeshiftStateChange( void )
{
	if (m_ePvrStateChange != (E_PVR_CALLBACK_STATE) -1 )
	{
		if (m_ePvrStateChange == PVR_PLAY_FILE_EOF)
		{
			if (m_eState == STATE_TIMESHIFT_PLAY)
			{
				// Check if set to automatically creating Timeshift file on playback start
				if (m_bAutoStartTimeshift)
				{
					m_eState = STATE_LIVE_RECORD;
				}
				else
				{
					m_eState = STATE_LIVE_PLAY;
				}
			}
		}
		else if (m_ePvrStateChange == PVR_RECORD_FILE_ERROR)
		{
			if ( m_eState == STATE_LIVE_PAUSE)
			{
				m_eState = STATE_LIVE_PLAY;
			}

			iRecordState = FALSE;
		}

		m_ePvrStateChange = (E_PVR_CALLBACK_STATE) -1;
	}
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::JumpToStart( void )
{
	if (IsJumpToStartEnabled())
	{
		// Reposition to start of Timeshift File
		m_pB2FilterGraph->GetTimeshiftControl()->SetFilePosition(0);

		// Update state
		m_eState = STATE_TIMESHIFT_PLAY;
	}
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::JumpToEnd( void )
{
	m_pB2FilterGraph->GetTimeshiftControl()->SetFilePosition(-1);
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::RepositionSliderBar( int iPositionPercentage )
{
	switch (m_eState)
	{
		case STATE_LIVE_PAUSE:
		case STATE_TIMESHIFT_PLAY:
		case STATE_LIVE_RECORD:
		{
			// If Slider not at far right, reposition in file appropriately
			if (iPositionPercentage < 100)
			{
				__int64 iNewFilePosition = GetRecordFileSize() * iPositionPercentage / 100;

				m_pB2FilterGraph->GetTimeshiftControl()->SetFilePosition( iNewFilePosition );

				m_eState = STATE_TIMESHIFT_PLAY;
			}
			// Position to end of file to resume Live Playback
			else
			{
				m_pB2FilterGraph->GetTimeshiftControl()->SetFilePosition(-1);
			}

			break;
		}
	}
}

/*-----------------------------------------------------------------------------------------------*/

BOOL CAVPlaybackCtrl::IsStopEnabled()
{
	BOOL bEnabled = FALSE;

	switch (m_eState)
	{
		case STATE_LIVE_PLAY:
		case STATE_LIVE_PAUSE:
		case STATE_TIMESHIFT_PLAY:
		case STATE_LIVE_RECORD:
		{
			bEnabled = TRUE;
			break;
		}
	}
	return (bEnabled);
}

/*-----------------------------------------------------------------------------------------------*/

BOOL CAVPlaybackCtrl::IsJumpToStartEnabled()
{
	BOOL bEnabled = FALSE;

	switch (m_eState)
	{
		case STATE_TIMESHIFT_PLAY:
		case STATE_LIVE_RECORD:
		case STATE_LIVE_PAUSE:
		{
			bEnabled = TRUE;
			break;
		}
	}
	return (bEnabled);
}

/*-----------------------------------------------------------------------------------------------*/

BOOL CAVPlaybackCtrl::IsPauseEnabled()
{
	BOOL bEnabled = FALSE;

	switch (m_eState)
	case STATE_TIMESHIFT_PLAY:
	case STATE_LIVE_PLAY:
	case STATE_LIVE_RECORD:
	{
		bEnabled = TRUE;
		break;
	}

	return (bEnabled);
}

/*-----------------------------------------------------------------------------------------------*/

BOOL CAVPlaybackCtrl::IsRecordEnabled()
{
	BOOL bEnabled = FALSE;

	switch (m_eState)
	{
		case STATE_LIVE_PLAY:
		case STATE_LIVE_RECORD:
		case STATE_TIMESHIFT_PLAY:
		{
			bEnabled = TRUE;
			break;
		}
	}
	return (bEnabled);
}

/*-----------------------------------------------------------------------------------------------*/

void CAVPlaybackCtrl::Record( void)
{
	switch (m_eState)
	{
		case STATE_LIVE_PLAY:
		{
			m_eState = STATE_LIVE_RECORD;

			m_pB2FilterGraph->GetTimeshiftControl()->StartRecord();
			break;
		}
		case STATE_LIVE_RECORD:
		{
			m_eState = STATE_LIVE_PLAY;
		}
		case STATE_TIMESHIFT_PLAY:
		{
			m_pB2FilterGraph->GetTimeshiftControl()->StopRecord();
		}
	}
}

/*-----------------------------------------------------------------------------------------------*/

UINT __stdcall
CAVPlaybackCtrl::UpdatePvrState ( E_PVR_CALLBACK_STATE eCommand )
{
	// Store State change
	m_ePvrStateChange = eCommand;

	return (UINT) 1;
}
