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

	Filename:	TunerCtrlDlg.cpp

	Description:	

	History:		

		12/15/06	Added support of IR input.
					Correct spelling.
					Separate released defines from internal defines. [ARS]
		04/27/07	Change format of incoming IR data from  WORD to BYTE. [ARS]

	Copyright (c) 1998-2004, B2C2, Inc.
	Copyright (c) 2004-2007, Broadband Technologies, Inc.

	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF B2C2, INC. The copyright notice 
	above does not evidence any actual or intended publication of such source code.

	This file is released pursuant to and subject to the restrictions of the 
	non-disclosure agreement and license contract entered into by the parties.

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

#include "stdafx.h"
#include "resource.h"

#include <Dshow.h>
#include <initguid.h>

#include "B2C2_Defs.h"

#include "TunerCtrlDlg.h"
#include "AVPlaybackDlg.h"
#include "AVStreamingDlg.h"
#include "TSRecordingDlg.h"

#include "IB2C2MPEG2DataCtrl.h"
#include "IB2C2MPEG2TunerCtrl.h"
#include "IB2C2MPEG2AVCtrl.h"

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

#include "DeviceList.h"

#include "AboutDlg.h"

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

enum
{
	TIMER_CHECK_PARAMETERS = 1,
	TIMER_CHECK_IR_DATA,
	TIMER_CLEAR_IR_DATA
};

#define TIMER_CHECK_PARAMS_TIME		2000
#define TIMER_CHECK_IR_DATA_TIME	 250
#define TIMER_CLEAR_IR_DATA_TIME	2000

// Define RGB Colors
#define	RED		0x0000FF
#define	GREEN	0x00FF00	
#define BLACK	0x000000


TCHAR szBandwidth[BANDWIDTH_COUNT][6] = 
{
	_T("6 MHz"),
	_T("7 MHz"),
	_T("8 MHz"),
};

int iBandwidthIndex[BANDWIDTH_COUNT] = 
{
	BANDWIDTH_6_MHZ,
	BANDWIDTH_7_MHZ,
	BANDWIDTH_8_MHZ,
};

TCHAR szGuardInterval[GUARD_INTERVAL_COUNT][5] = 
{
	_T("1/32"),
	_T("1/16"),
	_T("1/8"),
	_T("1/4"),
	_T("Auto")
};

int nFEC[FEC_COUNT] = {
	FEC_1_2,
	FEC_2_3,
	FEC_3_4,
	FEC_5_6,
	FEC_7_8,
	FEC_AUTO
};
	
int nPolarity[POLARITY_COUNT] = {
	POLARITY_HORIZONTAL,
	POLARITY_VERTICAL
};
	
int nDiseqc[DISEQC_COUNT] = {
	DISEQC_NONE,
	DISEQC_SIMPLE_A,
	DISEQC_SIMPLE_B,
	DISEQC_LEVEL_1_A_A,
	DISEQC_LEVEL_1_B_A,
	DISEQC_LEVEL_1_A_B,
	DISEQC_LEVEL_1_B_B
};
	
int nLnbSelection[LNB_SELECTION_COUNT] = {
	LNB_SELECTION_0,
	LNB_SELECTION_22,
	LNB_SELECTION_33,
	LNB_SELECTION_44
};
	
TCHAR aszDiseqcStrings[DISEQC_COUNT][26] = {
	_T("None"),
	_T("Simple A"),
	_T("Simple B"),
	_T("Pos A - Opt A"),
	_T("Pos B - Opt A"),
	_T("Pos A - Opt B"),
	_T("Pos B - Opt B")
	};

#define MODULATION_COUNT	10
TCHAR aszModulationStrings[MODULATION_COUNT][26] = {
	_T("QAM4"),
	_T("QAM16"),
	_T("QAM32"),
	_T("QAM64"),
	_T("QAM128"),
	_T("QAM256"),
	_T("QAM64(B)"),
	_T("QAM256(B)"),
	_T("8VSB"),
	_T("16VSB"),
	};

int nModulation[MODULATION_COUNT] = {
	QAM_4,
	QAM_16,
	QAM_32,
	QAM_64,
	QAM_128,
	QAM_256,
};

TCHAR aszFECStrings[FEC_COUNT][5] = {
	_T("1/2"),
	_T("2/3"),
	_T("3/4"),
	_T("5/6"),
	_T("7/8"),
	_T("Auto")
	};

TCHAR aszLnbKHzStrings[LNB_SELECTION_COUNT][5] = {
	_T("None"),
	_T("22"),
	_T("33"),
	_T("44")
	};

TCHAR aszPolarityStrings[POLARITY_COUNT][23] = {
	_T("Horizontal/Left (High)"),
	_T("Vertical/Right (Low)")
	};


/////////////////////////////////////////////////////////////////////////////
// CTunerCtrlDlg dialog

CTunerCtrlDlg::CTunerCtrlDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTunerCtrlDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTunerCtrlDlg)
	m_fFrequency = 0.0;
	m_lPID = 0;
	m_lSatLnbFrequency = 0;
	m_lSymbolRate = 0;
	m_lSatTunerFrequency = 0;
	m_iGuardIntervalIndex = -1;
	m_iVideoPID = 0;
	m_iAudioPID = 0;
	m_lRecordingFileSizeLimit = 0;
	m_lRecordingTimeLimit = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_pDevNotify = NULL;

	m_pB2C2FilterTunerCtrl = NULL;
	m_pB2C2FilterDataCtrl = NULL;
	m_pB2C2FilterAVCtrl = NULL;

	m_nSatDiseqcIndex = 0; 
	m_nSatFECIndex =0; 
	m_nSatLnbSelectionIndex = 0;
	m_nSatPolarityIndex = 0;
	m_bProcessTunerFields = TRUE;
	m_bProcessPidFields = TRUE;

	m_bTunerLocked = FALSE;

	m_pB2FilterGraph = NULL;
	m_bListboxesInitialized = FALSE;

	m_bAutoDeleteTimeshift = TRUE;
	m_bAutoStartTimeshift = FALSE;

	m_dwMulticastAddress = 0;
	m_dwMulticastPort = 0;
	m_dwMulticastPID1 = 0x1fff;
	m_dwMulticastPID2 = 0x1fff;
	m_dwMulticastPID3 = 0x1fff;
	m_dwMulticastPID4 = 0x1fff;
	m_dwMulticastPID5 = 0x1fff;

	m_iBandwidthIndex = 0;

	m_dwIRDataCount = 0;

	m_szRecordFileName[0] = NULL;

	ZeroMemory( &MulticastInfo, sizeof (MulticastInfo));

	m_nIRDataDuplicateCount = 0;
	m_ucPreviousIRData[0] = 0xFF;
	m_ucPreviousIRData[1] = 0xFF;
}

CTunerCtrlDlg::~CTunerCtrlDlg()
{
	// Close Audio/Video Streaming Dialogs
	CloseAVStreamingDlgs();
}


void CTunerCtrlDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTunerCtrlDlg)
	DDX_Text(pDX, IDC_EDIT_FREQUENCY, m_fFrequency);
	DDX_CBIndex(pDX, IDC_COMBO_GUARD_INTERVAL, m_iGuardIntervalIndex);
	//}}AFX_DATA_MAP

	if (m_bProcessTunerFields)
	{
		DDX_Text(pDX, IDC_EDIT_SAT_LNB_FREQUENCY, m_lSatLnbFrequency);
		DDX_Text(pDX, IDC_EDIT_SAT_SYMBOL_RATE, m_lSymbolRate);
		DDX_Text(pDX, IDC_EDIT_SAT_TUNER_FREQUENCY, m_lSatTunerFrequency);
	}

	if (m_bProcessPidFields)
	{
		DDX_Text(pDX, IDC_EDIT_PID, m_lPID);
	}
	DDX_Text(pDX, IDC_EDIT_VIDEO_PID, m_iVideoPID);
	DDX_Text(pDX, IDC_EDIT_AUDIO_PID, m_iAudioPID);
	DDX_Text(pDX, IDC_EDIT_FILE_SIZE_LIMIT, m_lRecordingFileSizeLimit);
	DDX_Text(pDX, IDC_EDIT_TIME_LIMIT, m_lRecordingTimeLimit);
	DDX_Check(pDX, IDC_CHECK_AUTO_DELETE_TIMESHIFT, m_bAutoDeleteTimeshift);
	DDX_Check(pDX, IDC_CHECK_AUTO_START_TIMESHIFT, m_bAutoStartTimeshift);
	DDX_IPAddress(pDX, IDC_IPADDRESS1, m_dwMulticastAddress);
	DDX_Text(pDX, IDC_EDIT_MULTICAST_PORT, m_dwMulticastPort);
	DDV_MinMaxUInt(pDX, m_dwMulticastPort, 0, 65535);
	DDX_Text(pDX, IDC_EDIT_MULTICAST_PID, m_dwMulticastPID1);
	DDX_Text(pDX, IDC_EDIT_MULTICAST_PID2, m_dwMulticastPID2);
	DDX_Text(pDX, IDC_EDIT_MULTICAST_PID3, m_dwMulticastPID3);
	DDV_MinMaxUInt(pDX, m_dwMulticastPID3, 0, 8191);
	DDX_Text(pDX, IDC_EDIT_MULTICAST_PID4, m_dwMulticastPID4);
	DDV_MinMaxUInt(pDX, m_dwMulticastPID4, 0, 8191);
	DDX_Text(pDX, IDC_EDIT_MULTICAST_PID5, m_dwMulticastPID5);
	DDV_MinMaxUInt(pDX, m_dwMulticastPID5, 0, 8191);
	DDX_Control(pDX, IDC_IPADDRESS1, m_MulticastAddressCtrl);
	DDX_Control(pDX, IDC_IPADDRESS2, m_NetworkAdapterCtrl);
	DDX_CBIndex(pDX, IDC_COMBO_BANDWIDTH, m_iBandwidthIndex);
}

BEGIN_MESSAGE_MAP(CTunerCtrlDlg, CDialog)
	//{{AFX_MSG_MAP(CTunerCtrlDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_ADD_PID, OnButtonAddPid)
	ON_BN_CLICKED(IDC_BUTTON_DEL_PID, OnButtonDelPid)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON_APPLY_TUNER_SETTINGS, OnButtonApplyTunerSettings)
	ON_BN_CLICKED(IDC_Reset, OnReset)
	ON_EN_CHANGE(IDC_EDIT_FREQUENCY, OnChangeEditFrequency)
	ON_BN_CLICKED(IDC_BUTTON_SHOW_PIDS, OnButtonShowPids)
	ON_BN_CLICKED(IDC_BUTTON_SET_UNICAST_MAC, OnButtonSetUnicastMac)
	ON_BN_CLICKED(IDC_BUTTON_PLAY_AV, OnBnClickedPlayAudioVideo)
	ON_BN_CLICKED(IDC_BUTTON_STREAM, OnBnClickedButtonStream)
	ON_CBN_SELCHANGE(IDC_COMBO_BANDWIDTH, OnCbnSelchangeComboBandwidth)
	//}}AFX_MSG_MAP
//	ON_MESSAGE(WM_DEVICECHANGE, OnDeviceChange)
	ON_BN_CLICKED(IDC_BUTTON_SHOW_TS_PIDS, &CTunerCtrlDlg::OnBnClickedButtonShowTsPids)
	ON_BN_CLICKED(IDC_BUTTON_SHOW_ALL_PIDS, &CTunerCtrlDlg::OnBnClickedButtonShowAllPids)
	ON_BN_CLICKED(IDC_BUTTON_GO_EAST, &CTunerCtrlDlg::OnBnClickedButtonGoEast)
	ON_BN_CLICKED(IDC_BUTTON_STOP, &CTunerCtrlDlg::OnBnClickedButtonStop)
	ON_BN_CLICKED(IDC_BUTTON_GO_WEST, &CTunerCtrlDlg::OnBnClickedButtonGoWest)
	ON_BN_CLICKED(IDC_STATIC_RECORD_TS, &CTunerCtrlDlg::OnBnClickedStaticRecordTs)
	ON_BN_CLICKED(IDC_BUTTON_RECORD, &CTunerCtrlDlg::OnBnClickedButtonRecord)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTunerCtrlDlg message handlers

BOOL CTunerCtrlDlg::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

	HideUserInterface();

	// Clear Performance Statistics

	ZeroPerformanceStatistics();

	// Create B2C2 Adapter object

	ASSERT( m_pB2FilterGraph == NULL);

	// Instantiate and create B2C2 Filter and filter graph
	m_pB2FilterGraph = new CB2FilterGraphHandler();
	ASSERT(m_pB2FilterGraph);

	if( !m_pB2FilterGraph)
	{
		AfxThrowMemoryException();
	}

	// Register device notification

	InitializeNotification();
	
	// Initialize Filter

	InitializeB2C2Filter();


	// Start Status refresh timer
	m_nTimerCheckParameters = SetTimer( TIMER_CHECK_PARAMETERS, 
										TIMER_CHECK_PARAMS_TIME, 
										NULL);

	// Initialize the current tuner values to the dialog

	m_MulticastAddressCtrl.SetAddress(224,0,0,1);
	m_dwMulticastPort = (WORD) 1234;

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

	
void CTunerCtrlDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;

		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

HRESULT CTunerCtrlDlg::InitializeB2C2Filter()
{
	HRESULT	hr;

	ASSERT( m_pB2FilterGraph);
	if( !m_pB2FilterGraph)
	{
		return E_FAIL;
	}

	// Check if already initialized

	if( !m_pB2FilterGraph->IsInitialized())
	{
		try 
		{
			// Initialize Filter Graph
			m_pB2FilterGraph->Initialize();

			// Get member pointer
			m_pB2C2FilterTunerCtrl = m_pB2FilterGraph->GetTunerControl();
			ASSERT( m_pB2C2FilterTunerCtrl);

			m_pB2C2FilterDataCtrl = m_pB2FilterGraph->GetDataControl();
			ASSERT( m_pB2C2FilterDataCtrl);

			m_pB2C2FilterAVCtrl = m_pB2FilterGraph->GetAvControl();
			ASSERT( m_pB2C2FilterAVCtrl);

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

			// No adapter present; reset control pointer
			ReleaseB2C2Filter();

			return E_FAIL;
		}
	}

	ASSERT( m_pB2FilterGraph);

	// Display a list of available devices if more than one device installed.

	hr = SelectDevice();

	if(FAILED(hr))
	{
		return hr;
	}

	// Display the User Interface

	hr = ShowUserInterface();

	// Only do this once
	if (!m_bListboxesInitialized)
	{
		PopulateLists ();
		m_bListboxesInitialized = TRUE;

		UpdateTunerSettings();
	}

	if(FAILED(hr))
	{
		return hr;
	}

	return TRUE;
}

// Display a list of available devices if more than one device installed.
HRESULT CTunerCtrlDlg::SelectDevice()
{
	HRESULT hr;

	// First, get the list and count of devices

	tDEVICE_INFORMATION ListOfAdapters[MAX_DEVICES_SUPPORTED];
	DWORD dwDeviceCount = MAX_DEVICES_SUPPORTED;
	long  lSize = sizeof(ListOfAdapters);

	hr = m_pB2C2FilterDataCtrl->GetDeviceList (ListOfAdapters, &lSize, &dwDeviceCount);

	if (FAILED (hr) || (dwDeviceCount == 0))
	{
		return hr;
	}
	
	// IDC_DEVICE_LIST
	DWORD dwTunerID = 0;

	// Add entries to list boxes.
	CDeviceList SelectDeviceDlg;

	SelectDeviceDlg.SetDeviceListCount(dwDeviceCount);
	SelectDeviceDlg.SetDeviceListAddress(&ListOfAdapters[0]);

	dwDeviceCount = SelectDeviceDlg.GetAvailableDeviceCount();
	if (dwDeviceCount == 0)
	{
		hr = B2C2_SDK_E_NO_DEVICE_AVAILABLE;
		return hr;
	}

	if (dwDeviceCount > 1)
	{
		int nResponse = SelectDeviceDlg.DoModal();
		if (nResponse == IDOK)
		{
		}
		else
		{
			hr = B2C2_SDK_E_NO_DEVICE_AVAILABLE;
			return hr;
		}
	}

	// Open the tuner
	hr = m_pB2C2FilterDataCtrl->SelectDevice (SelectDeviceDlg.GetSelectedDevice());

	if (FAILED (hr))
	{
		return hr;
	}

	return S_OK;
}


void CTunerCtrlDlg::ReleaseB2C2Filter()
{
	// Clear member pointer
	m_pB2C2FilterDataCtrl = NULL;
	m_pB2C2FilterTunerCtrl = NULL;
	m_pB2C2FilterAVCtrl = NULL;

	// Check if initialized
	if( m_pB2FilterGraph)
	{
		// No adapter present; delete adapter object to indicate
		m_pB2FilterGraph->Release();
	}

	HideUserInterface();
}

void CTunerCtrlDlg::HideUserInterface()
{
	// Show Hardware not Found message

	GetDlgItem(IDC_STATIC_HARDWARE_NOT_FOUND)->ShowWindow(SW_SHOW);

	// Hide Tuner Control 

	GetDlgItem(IDC_STATIC_TUNER_SETTINGS)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_ATSC_FREQUENCY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_FREQUENCY)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_GUARD_INTERVAL)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_COMBO_GUARD_INTERVAL)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_TRANSPONDER)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_LNB_FREQUENCY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_SAT_LNB_FREQUENCY)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_TUNER_FREQUENCY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_SAT_TUNER_FREQUENCY)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_FEC)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_COMBO_SAT_FEC)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_SYMBOL_RATE)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_SAT_SYMBOL_RATE)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_POLARITY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_COMBO_SAT_POLARITY)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_LNB_SELECTION)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_COMBO_SAT_LNB_SELECTION)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SAT_DISEQC)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_COMBO_SAT_DISEQC)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_BUTTON_APPLY_TUNER_SETTINGS)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_MODULATION)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_COMBO_MODULATION)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SIGNAL_QUALITY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_SIGNAL_QUALITY)->ShowWindow(SW_HIDE);

	// Hide Performance Statistics

	GetDlgItem(IDC_STATIC_STATUS)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_LOCK_STATUS)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_LOCK_STATUS)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_SIGNAL_STRENGTH)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_SIGNAL_STRENGTH)->ShowWindow(SW_HIDE);
	
	GetDlgItem(IDC_STATIC_SNR)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_SNR)->ShowWindow(SW_HIDE);
	
	GetDlgItem(IDC_STATIC_BER)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_BER)->ShowWindow(SW_HIDE);
	
	GetDlgItem(IDC_STATIC_CORRECTED_BLOCKS)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_CORRECTED_BLOCKS)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_UNCORRECTED_BLOCKS)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_UNCORRECTED_BLOCKS)->ShowWindow(SW_HIDE);
	
	GetDlgItem(IDC_STATIC_TOTAL_BLOCKS)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_TOTAL_BLOCKS)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_TS_QUALITY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_TS_QUALITY)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_STATIC_IP_QUALITY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_IP_QUALITY)->ShowWindow(SW_HIDE);

	GetDlgItem(IDC_Reset)->ShowWindow(SW_HIDE);

	// Hide PID Management 

	GetDlgItem(IDC_STATIC_PID_CONTROL)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_STATIC_PID)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_PID)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_BUTTON_ADD_PID)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_BUTTON_DEL_PID)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_BUTTON_SHOW_PIDS)->ShowWindow(SW_HIDE);

	// Hide Unicast MAC Filter

	GetDlgItem(IDC_STATIC_FRAME_UNICAST_MAC)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_STATIC_CURRENT_UNICAST_MAC)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_STATIC_NEW_UNICAST_MAC)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_CURRENT_MAC_FILTER)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_NEW_UNICAST_MAC)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_BUTTON_SHOW_PIDS)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_BUTTON_SET_UNICAST_MAC)->ShowWindow(SW_HIDE);

	// Hide IR input

	GetDlgItem(IDC_STATIC_IR_INPUT)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_EDIT_IR_INPUT)->ShowWindow(SW_HIDE);
}

void CTunerCtrlDlg::PopulateLists ()
{
	// Add entries to list boxes.
	CComboBox* pComboBox;
	int index;

	//  Bandwidth list box.
	pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_BANDWIDTH);
	for (index = 0;index < BANDWIDTH_COUNT ;index++)
	{
		pComboBox->AddString( szBandwidth[index] );
	}

	pComboBox->SetCurSel(m_iBandwidthIndex ); 

	//  Guard list box.
	pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_GUARD_INTERVAL);
	for (index = 0;index < GUARD_INTERVAL_COUNT;index++)
	{
		pComboBox->AddString( szGuardInterval[index] );
	}

	pComboBox->SetCurSel(m_nSatFECIndex ); 

	//  Modulation list box.
	pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_MODULATION);
	for (index = 0;index < MODULATION_COUNT;index++)
	{
		pComboBox->AddString( aszModulationStrings[index] );
	}

	pComboBox->SetCurSel(m_nModulationIndex ); 

	//  Diseqc list box.
	pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_DISEQC);

	for (index = 0;index < DISEQC_COUNT;index++)
	{
		pComboBox->AddString( aszDiseqcStrings[index] );
	}

	pComboBox->SetCurSel(m_nSatDiseqcIndex ); 

	//  FEC list box.
	pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_FEC);

	for (index = 0;index < FEC_COUNT;index++)
	{
		pComboBox->AddString( aszFECStrings[index] );
	}

	pComboBox->SetCurSel(m_nSatFECIndex ); 

	// LNB Sel. list box.
	pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_LNB_SELECTION);
	for (index = 0;index < LNB_SELECTION_COUNT;index++)
	{
	  pComboBox->AddString( aszLnbKHzStrings[index] );
	}

	pComboBox->SetCurSel(m_nSatLnbSelectionIndex ); 

	//  Polarity list box.
	pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_POLARITY);
	for (index = 0;index < POLARITY_COUNT;index++)
	{
	  pComboBox->AddString( aszPolarityStrings[index] );
	}

	pComboBox->SetCurSel(m_nSatPolarityIndex ); 

}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::ShowUserInterface() 

	Displays the user interface with the relevant settings.
*/
HRESULT CTunerCtrlDlg::ShowUserInterface()
{
	HRESULT	hr;
	int nVisibility;

	// Paranoia
	ASSERT( m_pB2C2FilterTunerCtrl);
	ASSERT( m_pB2C2FilterDataCtrl);
	ASSERT( m_pB2C2FilterAVCtrl);

	GetDlgItem(IDC_STATIC_HARDWARE_NOT_FOUND)->ShowWindow(SW_HIDE);

	// Show PID Management 

	GetDlgItem(IDC_STATIC_PID_CONTROL)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_STATIC_PID)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_EDIT_PID)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_BUTTON_ADD_PID)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_BUTTON_DEL_PID)->ShowWindow(SW_SHOW);
//	GetDlgItem(IDC_BUTTON_SHOW_PIDS)->ShowWindow(SW_SHOW);

	// Show Audio/Video PID

	GetDlgItem(IDC_STATIC_VIDEO_PID)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_EDIT_VIDEO_PID)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_STATIC_AUDIO_PID)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_EDIT_AUDIO_PID)->ShowWindow(SW_SHOW);


	// Show Unicast MAC Filter

	GetDlgItem(IDC_STATIC_FRAME_UNICAST_MAC)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_STATIC_CURRENT_UNICAST_MAC)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_STATIC_NEW_UNICAST_MAC)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_EDIT_CURRENT_MAC_FILTER)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_EDIT_NEW_UNICAST_MAC)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_BUTTON_SHOW_PIDS)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_BUTTON_SET_UNICAST_MAC)->ShowWindow(SW_SHOW);


	// Show applicable Performance Statistics.

	GetDlgItem(IDC_STATIC_STATUS)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_Reset)->ShowWindow(SW_SHOW);

	// Show Lock Status

	GetDlgItem(IDC_STATIC_LOCK_STATUS)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_EDIT_LOCK_STATUS)->ShowWindow(SW_SHOW);

	// Show Signal Strength

	//GetDlgItem(IDC_STATIC_SIGNAL_STRENGTH)->ShowWindow(SW_SHOW);
	//GetDlgItem(IDC_EDIT_SIGNAL_STRENGTH)->ShowWindow(SW_SHOW);


	// Get the tuner capbabilities

	LONG lSize = sizeof(tTunerCapabilities);

	hr = m_pB2C2FilterTunerCtrl->GetTunerCapabilities(&m_TunerCapabilities, &lSize);

	if (FAILED(hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. GetTunerCapabilities method failed, error: 0x%8.8x"), hr);
		MessageBox(m_csTemp, "B2C2 Tuner Control", MB_OK);

		return hr;	// *** FUNCTION EXIT POINT
	}

	if (lSize < sizeof(tTunerModulation))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. GetTunerCapabilities return insufficient data, length: %ld"), lSize);
		MessageBox(m_csTemp, "B2C2 Tuner Control", MB_OK);

		return hr;	// *** FUNCTION EXIT POINT
	}

	// Disable Signal to Noise if not supported

	if (m_TunerCapabilities.dwPerformanceMonitoring & SNR_SUPPORTED)
	{
		GetDlgItem(IDC_EDIT_SNR)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_STATIC_SNR)->ShowWindow(SW_SHOW);
	}

	// Disable Signal Quality if not supported

	if (m_TunerCapabilities.dwPerformanceMonitoring & SIGNAL_QUALITY_SUPPORTED)
	{
		GetDlgItem(IDC_STATIC_SIGNAL_QUALITY)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_EDIT_SIGNAL_QUALITY)->ShowWindow(SW_SHOW);
	}

	// Disable Signal Strength if not supported

	if (m_TunerCapabilities.dwPerformanceMonitoring & SIGNAL_STRENGTH_SUPPORTED)
	{
		GetDlgItem(IDC_STATIC_SIGNAL_STRENGTH)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_EDIT_SIGNAL_STRENGTH)->ShowWindow(SW_SHOW);
	}

	// Disable BER disable if not supported

	if (m_TunerCapabilities.dwPerformanceMonitoring & BER_SUPPORTED)
	{
		GetDlgItem(IDC_EDIT_BER)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_STATIC_BER)->ShowWindow(SW_SHOW);
	}

	// Disable Uncorrected Blocks disable if not supported

	if (m_TunerCapabilities.dwPerformanceMonitoring & UNCORRECTED_BLOCK_COUNT_SUPPORTED)
	{
		GetDlgItem(IDC_EDIT_UNCORRECTED_BLOCKS)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_STATIC_UNCORRECTED_BLOCKS)->ShowWindow(SW_SHOW);
	}

	// Disable corrected Blocks disable if not supported

	if (m_TunerCapabilities.dwPerformanceMonitoring & CORRECTED_BLOCK_COUNT_SUPPORTED)
	{
		GetDlgItem(IDC_EDIT_CORRECTED_BLOCKS)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_STATIC_CORRECTED_BLOCKS)->ShowWindow(SW_SHOW);
	}

	// Disable Total Blocks disable if not supported

	if (m_TunerCapabilities.dwPerformanceMonitoring & BLOCK_COUNT_SUPPORTED)
	{
		GetDlgItem(IDC_EDIT_TOTAL_BLOCKS)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_STATIC_TOTAL_BLOCKS)->ShowWindow(SW_SHOW);
	}

	// Ensure current information retreived for the Tuner Settings
	m_pB2C2FilterTunerCtrl->CheckLock();

	
	// Format the dialog appropriately for the tuner type

	GetDlgItem(IDC_BUTTON_APPLY_TUNER_SETTINGS)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_STATIC_TUNER_SETTINGS)->ShowWindow(SW_SHOW);


	switch( m_TunerCapabilities.eModulation)
	{
		case TUNER_TERRESTRIAL:
		{
			GetDlgItem(IDC_STATIC_ATSC_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_EDIT_FREQUENCY)->ShowWindow(SW_SHOW);

			if (!(m_TunerCapabilities.dwAcquisitionCapabilities & ACQUISITION_AUTO_GUARD_INTERVAL))
			{
				GetDlgItem(IDC_STATIC_GUARD_INTERVAL)->ShowWindow(SW_SHOW);
				GetDlgItem(IDC_COMBO_GUARD_INTERVAL)->ShowWindow(SW_SHOW);
			}

			GetDlgItem(IDC_STATIC_BANDWIDTH)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_COMBO_BANDWIDTH)->ShowWindow(SW_SHOW);

			// Enable Tune Button 
			EnableTuneButton(FALSE);

			break;
		}

		case TUNER_ATSC:
		{
			GetDlgItem(IDC_STATIC_ATSC_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_EDIT_FREQUENCY)->ShowWindow(SW_SHOW);

			GetDlgItem(IDC_STATIC_MODULATION)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_COMBO_MODULATION)->ShowWindow(SW_SHOW);

			// Disable Tune Button *** ONLY works for ATSC presently ***
			EnableTuneButton(FALSE);
			
			break;
		}
		case TUNER_CABLE:
		{
			GetDlgItem(IDC_STATIC_ATSC_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_EDIT_FREQUENCY)->ShowWindow(SW_SHOW);
			
			GetDlgItem(IDC_STATIC_SAT_SYMBOL_RATE)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_EDIT_SAT_SYMBOL_RATE)->ShowWindow(SW_SHOW);

			GetDlgItem(IDC_STATIC_MODULATION)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_COMBO_MODULATION)->ShowWindow(SW_SHOW);
			break;
		}
		case TUNER_SATELLITE:
		{
			GetDlgItem(IDC_STATIC_SAT_TRANSPONDER)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_STATIC_SAT_LNB_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_STATIC_SAT_TUNER_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_STATIC_SAT_FEC)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_STATIC_SAT_SYMBOL_RATE)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_STATIC_SAT_POLARITY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_STATIC_SAT_LNB_SELECTION)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_STATIC_SAT_DISEQC)->ShowWindow(SW_SHOW);

			GetDlgItem(IDC_EDIT_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_EDIT_SAT_TUNER_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_EDIT_SAT_SYMBOL_RATE)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_EDIT_SAT_LNB_FREQUENCY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_COMBO_SAT_FEC)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_COMBO_SAT_POLARITY)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_COMBO_SAT_LNB_SELECTION)->ShowWindow(SW_SHOW);
			GetDlgItem(IDC_COMBO_SAT_DISEQC)->ShowWindow(SW_SHOW);

			break;
		}
		default:

			break;
	}


	// Check for IR input support

	nVisibility = (m_TunerCapabilities.dwAcquisitionCapabilities & ACQUISITION_IR_INPUT_SUPPORT) ?
		SW_SHOW : SW_HIDE;
	GetDlgItem(IDC_STATIC_IR_INPUT)->ShowWindow(nVisibility);
	GetDlgItem(IDC_EDIT_IR_INPUT)->ShowWindow(nVisibility);

	if (m_TunerCapabilities.dwAcquisitionCapabilities & ACQUISITION_IR_INPUT_SUPPORT)
	{
		// Start IR data timer
		m_nTimerCheckIRData = SetTimer( TIMER_CHECK_IR_DATA, 
										TIMER_CHECK_IR_DATA_TIME, 
										NULL);
	}

	// Display the Current Tuner Information, Mac address, etc
	UpdateTunerSettings();

	UpdateMacAddressField ();

	// Turn on the updates of the user entry fields
	m_bProcessTunerFields = TRUE;

	BOOL bRetVal = UpdateData( TRUE );

	// Turn off the updates of the user entry fields

	m_bProcessTunerFields = FALSE;

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

void CTunerCtrlDlg::UpdateMacAddressField (void)
{
	// Show adapter MAC address
	HRESULT hr;
	UCHAR ucMacAddress[B2C2_SDK_MAC_ADDR_SIZE];

	// Show Hardware MAC Address

	TRACE( "Call GetHardwareMacAddress ...\n");

	hr = m_pB2C2FilterDataCtrl->GetHardwareMacAddress((UCHAR*)ucMacAddress);

	if(FAILED(hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetHardwareMacAddress failed, error: 0x%8.8x"), hr);
//		MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

		m_csTemp.Format( _T("failed (#%08X)"), hr);
	} 
	else
	{
		m_csTemp.Format( _T("%02x%02x%02x%02x%02x%02x"),
						 ucMacAddress[0],ucMacAddress[1],ucMacAddress[2],
						 ucMacAddress[3],ucMacAddress[4],ucMacAddress[5]);
	}
		
	TRACE( "Got MAC %s\n", m_csTemp);

	GetDlgItem(IDC_EDIT_HARDWARE_MAC_ADDRESS)->SetWindowText( m_csTemp);
	// Show adapter Unicast MAC filter

	TRACE( "Call GetUnicastMacAddress ...\n");

	hr = m_pB2C2FilterDataCtrl->GetUnicastMacAddress((UCHAR*)ucMacAddress);

	if(FAILED(hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetUnicastMacAddress failed, error: 0x%8.8x"), hr);
//		MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

		m_csTemp.Format( _T("failed (#%08X)"), hr);
	} 
	else
	{
		m_csTemp.Format( _T("%02x%02x%02x%02x%02x%02x"),
						 ucMacAddress[0],ucMacAddress[1],ucMacAddress[2],
						 ucMacAddress[3],ucMacAddress[4],ucMacAddress[5]);
	}
		
	TRACE( "Got MAC %s\n", m_csTemp);

	GetDlgItem(IDC_EDIT_CURRENT_MAC_FILTER)->SetWindowText( m_csTemp);
}


// 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 CTunerCtrlDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (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 to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CTunerCtrlDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


// ***************************************************************************************
// Set B2C2 Tuner settings
// ***************************************************************************************

void CTunerCtrlDlg::OnButtonApplyTunerSettings() 
{
	HRESULT	hr;
	BOOL	bRetVal;

	// Paranoia
	ASSERT( m_pB2C2FilterTunerCtrl);

	// Close Audio/Video Streaming Dialogs
	CloseAVStreamingDlgs();

	// Turn on the updates of the user entry fields

	m_bProcessTunerFields = TRUE;

	bRetVal = UpdateData( TRUE );

	if(!bRetVal)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface Frequency retrieval failed"));
		MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;	// *** FUNCTION EXIT POINT
	}

	switch( m_TunerCapabilities.eModulation)
	{
		case TUNER_TERRESTRIAL:
		{
			hr = m_pB2C2FilterTunerCtrl->SetFrequencyKHz((long)(m_fFrequency*1000));
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetFrequency method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// If Auto-Guard Interval is not supported, set the selected Guard Interval

			if (!(m_TunerCapabilities.dwAcquisitionCapabilities & ACQUISITION_AUTO_GUARD_INTERVAL))
			{
				// Get a pointer to the Guard Interval list box.

				CComboBox* pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_GUARD_INTERVAL);

				m_iGuardIntervalIndex = pComboBox->GetCurSel(); 

			
				hr = m_pB2C2FilterTunerCtrl->SetGuardInterval(m_iGuardIntervalIndex);

				if(FAILED(hr))
				{
					m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetGuardInterval method failed, error: 0x%8.8x"), hr);
					MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

					return;	// *** FUNCTION EXIT POINT
				}
			}

			// If Multple bandwidths are supported, set the selected Bandwidth

//			if (!(m_TunerCapabilities.dwAcquisitionCapabilities & ACQUISITION_AUTO_GUARD_INTERVAL))
			{
				// Get a pointer to the Guard Interval list box.

				CComboBox* pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_BANDWIDTH);

				int iIndex = iBandwidthIndex[pComboBox->GetCurSel()];

				hr = m_pB2C2FilterTunerCtrl->SetBandwidth( iIndex );

				if(FAILED(hr))
				{
					m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetBandwidth method failed, error: 0x%8.8x"), hr);
					MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

					return;	// *** FUNCTION EXIT POINT
				}
			}

			break;
		}

		case TUNER_ATSC:
	
			hr = m_pB2C2FilterTunerCtrl->SetFrequencyKHz((long)m_fFrequency*1000);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetFrequency method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			break;

		case TUNER_CABLE:
	
			CComboBox* pComboBox;

			// Get a pointer to the Modualtion list box, get the index, set the modulation.

			pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_MODULATION);

			m_nModulationIndex = pComboBox->GetCurSel(); 

			hr = m_pB2C2FilterTunerCtrl->SetModulation (nModulation[m_nModulationIndex]);

			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetModulation method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set Frequency

			hr = m_pB2C2FilterTunerCtrl->SetFrequency((long)m_fFrequency*1000);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetFrequency method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set SymbolRate

			hr = m_pB2C2FilterTunerCtrl->SetSymbolRate(m_lSymbolRate);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetSymbolRate method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			break;

		case TUNER_SATELLITE:
		{
			// Get indexes to lists.

			CComboBox* pComboBox;

			// Get a pointer to the Diseqc list box.

			pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_DISEQC);

			m_nSatDiseqcIndex = pComboBox->GetCurSel(); 

			// Get a pointer to the FEC list box.

			pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_FEC);

			m_nSatFECIndex = pComboBox->GetCurSel(); 

			// Get a pointer to the FEC list box.

			pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_LNB_SELECTION);

			m_nSatLnbSelectionIndex = pComboBox->GetCurSel(); 

			// Get a pointer to the Polarity list box.

			pComboBox = (CComboBox*) GetDlgItem(IDC_COMBO_SAT_POLARITY);

			m_nSatPolarityIndex = pComboBox->GetCurSel();
			
			// Calulate the tuner frequency

			m_lSatTunerFrequency = (long) m_fFrequency - m_lSatLnbFrequency;

			// Set tuner values

			// Set Frequency

			hr = m_pB2C2FilterTunerCtrl->SetFrequencyKHz((long) (m_fFrequency * 1000.0));
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetFrequency method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set SymbolRate

			hr = m_pB2C2FilterTunerCtrl->SetSymbolRate(m_lSymbolRate);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetSymbolRate method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set LNB Frequency

			hr = m_pB2C2FilterTunerCtrl->SetLnbFrequency(m_lSatLnbFrequency);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetLnbFrequency method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set FEC

			hr = m_pB2C2FilterTunerCtrl->SetFec(nFEC[m_nSatFECIndex]);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetFec method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set Polarity

			hr = m_pB2C2FilterTunerCtrl->SetPolarity(nPolarity[m_nSatPolarityIndex]);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetPolarity method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set LNB Selection

			hr = m_pB2C2FilterTunerCtrl->SetLnbKHz(nLnbSelection[m_nSatLnbSelectionIndex]);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetLnbKHz method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Set DiSEqC

			hr = m_pB2C2FilterTunerCtrl->SetDiseqc(nDiseqc[m_nSatDiseqcIndex]);
			
			if(FAILED(hr))
			{
				m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface SetDiseqc method failed, error: 0x%8.8x"), hr);
				MessageBox(m_csTemp, "B2C2 TunerCtrl", MB_OK);

				return;	// *** FUNCTION EXIT POINT
			}

			// Update the frequency

			bRetVal = UpdateData( FALSE );

			// Turn off the updates of the user entry fields

			m_bProcessTunerFields = FALSE;

			break;
		}
		default:

			break;
	}

	// Send settings to tuner.

	hr = m_pB2C2FilterTunerCtrl->SetTunerStatus();

	EnableTuneButton(FALSE);


}

// ***************************************************************************************
// Set B2C2 MPEG2 Filter Data PID
// ***************************************************************************************

void CTunerCtrlDlg::OnButtonAddPid() 
{
	long	lPIDArray[1];
	HRESULT	hr;
	BOOL	bRetVal;
	static bool bFirstTime = TRUE;

	// Paranoia
	ASSERT( m_pB2C2FilterDataCtrl);

	// Turn on the updates of the user entry fields

	m_bProcessPidFields = TRUE;

	bRetVal = UpdateData( TRUE );

	// Turn off the updates of the user entry fields

	m_bProcessPidFields = FALSE;

	if(!bRetVal)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface PID retrieval failed"));
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;	// *** FUNCTION EXIT POINT
	}

	if (m_lPID != 0)
	{
		lPIDArray[0] = m_lPID;

		hr = m_pB2C2FilterDataCtrl->AddIpPIDs(1, lPIDArray);
		if(FAILED(hr))
		{
			m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface AddPIDs method failed, error: 0x%8.8x"), hr);
			MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
		}
		else
		{
			if (bFirstTime == TRUE)
			{
				// Reset TS & IP quality stats on first PID add.

				hr = m_pB2C2FilterDataCtrl->ResetDataReceptionStats();

				if(FAILED(hr))
				{
					m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface ResetDataReceptionStats method failed, error: 0x%8.8x"), hr);
					MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
				}
				else
				{
					bFirstTime = FALSE;
				}
			}
		}
	}
}

// ***************************************************************************************
// Remove B2C2 MPEG2 Filter Data PID
// ***************************************************************************************

void CTunerCtrlDlg::OnButtonDelPid() 
{
	long	lPIDArray[1];
	HRESULT	hr;
	BOOL	bRetVal;

	// Turn on the updates of the user entry fields

	m_bProcessPidFields = TRUE;

	bRetVal = UpdateData( TRUE );

	// Turn off the updates of the user entry fields

	m_bProcessPidFields = FALSE;

	if(!bRetVal)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface PID retrieval failed"));
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;	// *** FUNCTION EXIT POINT
	}

	if (m_lPID != 0)
	{
		lPIDArray[0] = m_lPID;

		hr = m_pB2C2FilterDataCtrl->DeleteIpPIDs(1, lPIDArray);
		if(FAILED(hr))
		{
			m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface Delete PIDs method failed, error: 0x%8.8x"), hr);
			MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
		}
	}
}

void CTunerCtrlDlg::OnTimer(UINT nIDEvent) 
{
	HRESULT	hr;
	long	lUncorrectedBlocks;
	long	lTotalBlocks;

	ASSERT( m_pB2FilterGraph);
	if (m_pB2FilterGraph &&
		m_pB2FilterGraph->IsInitialized() )	// Device detected?
	{
		if (nIDEvent == TIMER_CHECK_PARAMETERS)
		{
			// Paranoia
			ASSERT( m_pB2C2FilterTunerCtrl);
			ASSERT( m_pB2C2FilterDataCtrl);
			ASSERT( m_pB2C2FilterAVCtrl);

			// Check for lock.and reset parameter buffer

			hr = m_pB2C2FilterTunerCtrl->CheckLock();

			if( FAILED(hr) )
			{
				m_bTunerLocked = FALSE;

				// Clear Performance Statistics for new frequency

				ZeroPerformanceStatistics();	
			}
			else
			{
				m_bTunerLocked = TRUE;

				// Get Signal Strength data

				if (m_TunerCapabilities.dwPerformanceMonitoring & SIGNAL_STRENGTH_SUPPORTED)
				{
					hr = m_pB2C2FilterTunerCtrl->GetSignalStrength(&m_lSignalStrength);

					if(FAILED(hr))
					{
						m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface get fSignalStrength failed, error: 0x%8.8x"), hr);
						MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
					}
				}

				// Get Signal Quality data

				if (m_TunerCapabilities.dwPerformanceMonitoring & SIGNAL_QUALITY_SUPPORTED)
				{
					hr = m_pB2C2FilterTunerCtrl->GetSignalQuality(&m_lSignalQuality);

					if(FAILED(hr))
					{
						m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface get fSignalStrength failed, error: 0x%8.8x"), hr);
						MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
					}
				}

				// Get Signal to Noise data

				if (m_TunerCapabilities.dwPerformanceMonitoring & SNR_SUPPORTED)
				{
					hr = m_pB2C2FilterTunerCtrl->GetSNR(&m_fSNR);
					if(FAILED(hr))
					{
						m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl.Interface get fSNR failed, error: 0x%8.8x"), hr);
						MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
					}
				}

				// Get BER data

				if (m_TunerCapabilities.dwPerformanceMonitoring & BER_SUPPORTED)
				{
					hr = m_pB2C2FilterTunerCtrl->GetPreErrorCorrectionBER(&m_fBER, FALSE);
					if(FAILED(hr))
					{
						m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface get fBER failed, error: 0x%8.8x"), hr);
						MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
					}
				}

				// Get Uncorrected Blocks data

				if (m_TunerCapabilities.dwPerformanceMonitoring & UNCORRECTED_BLOCK_COUNT_SUPPORTED)
				{
					hr = m_pB2C2FilterTunerCtrl->GetUncorrectedBlocks(&lUncorrectedBlocks);
					if(FAILED(hr))
					{
						m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface get UncorrectedBlocks failed, error: 0x%8.8x"), hr);
						MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
					}
					m_lUncorrectedBlocksAccumulated += lUncorrectedBlocks;
				}

				// Get Total Blocks data

				if (m_TunerCapabilities.dwPerformanceMonitoring & BLOCK_COUNT_SUPPORTED)
				{
					hr = m_pB2C2FilterTunerCtrl->GetTotalBlocks(&lTotalBlocks);
					if(FAILED(hr))
					{
						m_csTemp.Format( _T("B2C2 MPEG2 Filter Tuner Ctrl. Interface get TotalBlocks failed, error: 0x%8.8x"), hr);
						MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
					}
					m_lTotalBlocksAccumulated += lTotalBlocks;
				}

				// Get TS & IP qualities.

				hr = m_pB2C2FilterDataCtrl->GetDataReceptionStats(&m_lIpQuality, &m_lTsQuality);

				if(FAILED(hr))
				{
					m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetDataReceptionStats method failed, error: 0x%8.8x"), hr);
					MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
				}
			}

			// Update the Performance Statistics display.

			UpdatePerformanceStatistics();

			switch( m_TunerCapabilities.eModulation)
			{
				case TUNER_ATSC:
				{
					long lTmp;

					m_pB2C2FilterTunerCtrl->GetModulation(&lTmp);
					((CComboBox*) GetDlgItem(IDC_COMBO_MODULATION))->SetCurSel( lTmp - QAM_4);
				}
			}
		}
		else if (nIDEvent == TIMER_CHECK_IR_DATA)
		{
			// Get IR input
			if (m_TunerCapabilities.dwAcquisitionCapabilities & ACQUISITION_IR_INPUT_SUPPORT)
			{
				m_dwIRDataCount = MAX_IR_DATA;
				hr = m_pB2C2FilterAVCtrl->GetIRData((long *)&m_ucIRData[0], (long *)&m_dwIRDataCount);

				if(hr != S_OK)
				{
					m_dwIRDataCount = 0;

					// Stop the IR data timer
					if (m_nTimerCheckIRData != 0)
					{
						KillTimer(m_nTimerCheckIRData );
						m_nTimerCheckIRData = 0;
					}

					m_csTemp.Format( _T("B2C2 MPEG2 Filter AV Ctrl. Interface GetIRData method failed, error: 0x%8.8x"), hr);
					MessageBox( m_csTemp, "B2C2 AVCtrl", MB_OK);

					// Restart the IR data timer
					m_nTimerCheckIRData = SetTimer( TIMER_CHECK_IR_DATA, 
													TIMER_CHECK_IR_DATA_TIME, 
													NULL);
				}
				else
				{
					// Display IR input or status
					char		strIRText[120];
					COLORREF	bgColor;
					bool		bIRChange = false;

					if (m_dwIRDataCount != 0)
					{
						int nIndex;

						// Stop the clear IR data timer
						if (m_nTimerClearIRData != 0)
						{
							KillTimer(m_nTimerClearIRData );
							m_nTimerClearIRData = 0;
						}

						bgColor = GREEN;
						strIRText[0] = 0;
						for (nIndex = 0;
							 (((DWORD)nIndex < m_dwIRDataCount) && (strlen(strIRText) <= 100));
							 nIndex++)
						{
							if ((m_ucPreviousIRData[0] == m_ucIRData[nIndex * 2]) &&
								(m_ucPreviousIRData[1] == m_ucIRData[nIndex * 2 + 1]))
							{
								m_nIRDataDuplicateCount++;

								// if this is the first entry of this display or
								// all the the entries have been the same,
								// display the data and the repeat count.
								if ((strlen(strIRText) == 0) || !bIRChange)
								{
									sprintf(strIRText, "0x%02x%02x (%d)",
										m_ucIRData[nIndex * 2], m_ucIRData[nIndex * 2 + 1],
										m_nIRDataDuplicateCount);
								}
								// if the the entries have changed,
								// add a repeat count.
								else
								{
									sprintf(strIRText, "%s (%d)",
										strIRText, m_nIRDataDuplicateCount);
								}
							}
							else
							{
								sprintf(strIRText, "%s 0x%02x%02x",
									strIRText, m_ucIRData[nIndex * 2], m_ucIRData[nIndex * 2 + 1]);

								// if this is not the first entry of this display,
								// and it is not the same as the previous entry,
								// indicate a change during the display.
								if (nIndex > 0)
								{
									bIRChange = true;
								}
								m_nIRDataDuplicateCount = 1;
								m_ucPreviousIRData[0] = m_ucIRData[nIndex * 2];
								m_ucPreviousIRData[1] = m_ucIRData[nIndex * 2 + 1];
							}
						}

						m_nTimerClearIRData = SetTimer( TIMER_CLEAR_IR_DATA, 
														TIMER_CLEAR_IR_DATA_TIME, 
														NULL);

						CWnd* pWnd = GetDlgItem(IDC_EDIT_IR_INPUT);

						if (pWnd)
						{
							CRect	rect;
							CDC* pDC = pWnd->GetDC();

							pWnd->GetClientRect(&rect);

							pDC->FillSolidRect( rect, bgColor);
							pDC->SetBkColor( bgColor);
							pDC->SetTextColor( BLACK );
							pDC->DrawText( strIRText, -1, rect, DT_CENTER );
							
							pWnd->UpdateWindow();
							pWnd->ReleaseDC( pDC );
						}
					}
				}
			}
		}
		else if (nIDEvent == TIMER_CLEAR_IR_DATA)
		{
			// Get IR input
			if (m_TunerCapabilities.dwAcquisitionCapabilities & ACQUISITION_IR_INPUT_SUPPORT)
			{
				// Clear IR data display
				if (m_nTimerClearIRData != 0)
				{
					// Display IR input or status
					char		strIRText[120];
					COLORREF	bgColor;

					// Stop the clear IR data timer
					KillTimer(m_nTimerClearIRData );
					m_nTimerClearIRData = 0;

					bgColor = RED;
					strcpy(strIRText,"No Input");

					CWnd* pWnd = GetDlgItem(IDC_EDIT_IR_INPUT);

					if (pWnd)
					{
						CRect	rect;
						CDC* pDC = pWnd->GetDC();

						pWnd->GetClientRect(&rect);

						pDC->FillSolidRect( rect, bgColor);
						pDC->SetBkColor( bgColor);
						pDC->SetTextColor( BLACK );
						pDC->DrawText( strIRText, -1, rect, DT_CENTER );
						
						pWnd->UpdateWindow();
						pWnd->ReleaseDC( pDC );
					}
				}
			}
		}
	} //if (m_pB2FilterGraph && m_pB2FilterGraph->IsInitialized())

	CDialog::OnTimer(nIDEvent);
}

void CTunerCtrlDlg::CallSysFreeString()
{
}

BOOL CTunerCtrlDlg::DestroyWindow() 
{

	// Disable Timers

	KillTimer(m_nTimerCheckParameters );
	if (m_nTimerCheckIRData != 0)
	{
		KillTimer(m_nTimerCheckIRData );
	}

//	CallSysFreeString();

	// Unregister the Device Notification

	ReleaseNotification ();

	// Release B2C2 Filter
	
//	ReleaseB2C2Filter();

	// Delete adapter class
	if( m_pB2FilterGraph)
	{
		delete m_pB2FilterGraph;
		m_pB2FilterGraph = NULL;
	}
	
	return CDialog::DestroyWindow();
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::OnReset() 

	Button handler to reset all performance statistic values
*/
void CTunerCtrlDlg::OnReset() 
{
	// Clear Performance Statistics

	ZeroPerformanceStatistics();

	// Update the Tuner Status display.

	UpdatePerformanceStatistics();
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::UpdatePerformanceStatistics() 

	Updates display for all Performance Statistics
*/
void CTunerCtrlDlg::UpdatePerformanceStatistics(void)
{
	// Display Lock Status
	LPCTSTR		strLockText;
	COLORREF	bgColor;

	if( !m_bTunerLocked )
	{
		bgColor = RED;
		strLockText = _T("NO LOCK");
	}
	else
	{
		bgColor = GREEN;
		strLockText = _T("LOCK");
	}

	CWnd* pWnd = GetDlgItem(IDC_EDIT_LOCK_STATUS);
	if(pWnd)
	{
		CRect	rect;
		CDC* pDC = pWnd->GetDC();
		pWnd->GetClientRect(&rect);

		pDC->FillSolidRect( rect, bgColor);
		pDC->SetBkColor( bgColor);
		pDC->SetTextColor( BLACK );
		pDC->DrawText( strLockText, -1, rect, DT_CENTER );
		
		pWnd->UpdateWindow();
		pWnd->ReleaseDC( pDC );
	}

	// Display Signal Strength

	m_csTemp.Format( _T("%d"), m_lSignalStrength);
	GetDlgItem(IDC_EDIT_SIGNAL_STRENGTH)->SetWindowText( m_csTemp);

	// Display Signal Strength

	m_csTemp.Format( _T("%d"), m_lSignalQuality);
	GetDlgItem(IDC_EDIT_SIGNAL_QUALITY)->SetWindowText( m_csTemp);

	// Display SNR

	m_csTemp.Format( _T("%3.1f"), m_fSNR);
	GetDlgItem(IDC_EDIT_SNR)->SetWindowText( m_csTemp);

	// Display BER

	m_csTemp.Format( _T("%e"), m_fBER);
	GetDlgItem(IDC_EDIT_BER)->SetWindowText( m_csTemp);

	// Display Uncorrected Blocks

	m_csTemp.Format( _T("%d"), m_lUncorrectedBlocksAccumulated);
	GetDlgItem(IDC_EDIT_UNCORRECTED_BLOCKS)->SetWindowText( m_csTemp);

	// Display Total Blocks

	m_csTemp.Format( _T("%d"), m_lTotalBlocksAccumulated);
	GetDlgItem(IDC_EDIT_TOTAL_BLOCKS)->SetWindowText( m_csTemp);

	// Display IP Quality

	m_csTemp.Format( _T("%d"), m_lIpQuality);
	GetDlgItem(IDC_EDIT_IP_QUALITY)->SetWindowText( m_csTemp);

	// Display TS Quality

	m_csTemp.Format( _T("%d"), m_lTsQuality);
	GetDlgItem(IDC_EDIT_TS_QUALITY)->SetWindowText( m_csTemp);
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::EnableTuneButton() 

	Enable/Disable Tune button
*/
void CTunerCtrlDlg::EnableTuneButton(BOOL bEnable)
{
	// Disable Tune Button *** ONLY works for ATSC & TERRESTRAIL presently ***

	switch( m_TunerCapabilities.eModulation)
	{
		case TUNER_ATSC:
		case TUNER_TERRESTRIAL:
		{
			GetDlgItem(IDC_BUTTON_APPLY_TUNER_SETTINGS)->EnableWindow(bEnable);

			break;
		}
		default:
		{
//			EnableTuneButton(TRUE);
			GetDlgItem(IDC_BUTTON_APPLY_TUNER_SETTINGS)->EnableWindow(TRUE);
			break;
		}
	}
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::OnChangeEditFrequency() 

	Handler for Change to Frequency edit box to enable Tune button.
*/
void CTunerCtrlDlg::OnChangeEditFrequency() 
{
	// Enable Tune Button

	EnableTuneButton(TRUE);
}

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

void CTunerCtrlDlg::OnCbnSelchangeComboBandwidth()
{
	// Enable Tune Button

	EnableTuneButton(TRUE);
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::ZeroPerformanceStatistics() 

	Set all performance statistics to zero ... used for initialization, reset
	and frequency changes.
*/
void CTunerCtrlDlg::ZeroPerformanceStatistics() 
{
	m_lSignalStrength = 0;
	m_lSignalQuality = 0;
	m_lSignalLevel = 0;
	m_fSNR = 0.0f;
	m_fBER = 0.0f;

	m_lCorrectedBlocksAccumulated = 0;
	m_lUncorrectedBlocksAccumulated = 0;
	m_lTotalBlocksAccumulated = 0;

	m_lTsQuality = 0;
	m_lIpQuality = 0;
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::UpdateTunerSettings() 

	Updates display for all Performance Statistics
*/
void CTunerCtrlDlg::UpdateTunerSettings(void)
{
	// Common to all tuners:
	long lTmp;
	m_pB2C2FilterTunerCtrl->GetFrequency( &lTmp);
	m_fFrequency = (float) lTmp;
	
	switch( m_TunerCapabilities.eModulation)
	{
		case TUNER_TERRESTRIAL:
		{
			// Update GuardInterval

			m_pB2C2FilterTunerCtrl->GetGuardInterval( &lTmp);
			m_iGuardIntervalIndex = lTmp;

			// Update Bandwidth

			m_pB2C2FilterTunerCtrl->GetBandwidth( &lTmp);

			for (int iIndex = 0 ; iIndex < BANDWIDTH_COUNT; iIndex++)
			{
				if ( lTmp == iBandwidthIndex[iIndex] )
				{
					m_iBandwidthIndex = iIndex;
					break;
				}
			}
		}
		case TUNER_ATSC:
		{
			m_pB2C2FilterTunerCtrl->GetModulation(&lTmp);
			((CComboBox*) GetDlgItem(IDC_COMBO_MODULATION))->SetCurSel( lTmp - QAM_4);

			break;
		}
		case TUNER_CABLE:
		{
			m_pB2C2FilterTunerCtrl->GetSymbolRate(&m_lSymbolRate);

			m_pB2C2FilterTunerCtrl->GetModulation(&lTmp);
			((CComboBox*) GetDlgItem(IDC_COMBO_MODULATION))->SetCurSel( lTmp - QAM_4);

			break;
		}
		case TUNER_SATELLITE:
		{
			m_pB2C2FilterTunerCtrl->GetSymbolRate(&m_lSymbolRate);

			m_pB2C2FilterTunerCtrl->GetLnbFrequency(&m_lSatLnbFrequency);

			m_lSatTunerFrequency = (long) m_fFrequency - m_lSatLnbFrequency;

			m_pB2C2FilterTunerCtrl->GetFec( &lTmp);
			((CComboBox*) GetDlgItem(IDC_COMBO_SAT_FEC))->SetCurSel( lTmp - FEC_1_2);

			m_pB2C2FilterTunerCtrl->GetPolarity( &lTmp);
			((CComboBox*) GetDlgItem(IDC_COMBO_SAT_POLARITY))->SetCurSel( lTmp);

			m_pB2C2FilterTunerCtrl->GetLnbKHz( &lTmp);
			((CComboBox*) GetDlgItem(IDC_COMBO_SAT_LNB_SELECTION))->SetCurSel( lTmp);

			m_pB2C2FilterTunerCtrl->GetDiseqc( &lTmp);
			((CComboBox*) GetDlgItem(IDC_COMBO_SAT_DISEQC))->SetCurSel( lTmp);

			break;
		}
	}

	UpdateData(FALSE);
}

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

void CTunerCtrlDlg::OnButtonShowPids() 
{
	HRESULT hr; 
	CString csMessage;
	
	// Get Maximum number of IP PIDs
	long lOpen;
	long lRunning;
	long lCount;

	// Paranoia
	ASSERT( m_pB2C2FilterDataCtrl);

	hr = m_pB2C2FilterDataCtrl->GetMaxIpPIDCount( &lCount);

	if( FAILED( hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxIpPIDCount method failed, error: 0x%8.8x"), hr);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	// Validate MAX number of IP PIDs

	if( lCount <= 0)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxIpPIDCount returned %ld"), lCount);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	// Create PIDs array
	long *plPIDArray = new long[lCount];

	ASSERT( plPIDArray);
	if( !plPIDArray)
	{
		AfxThrowMemoryException();
	}

	// Get IP PIDs.

	hr = m_pB2C2FilterDataCtrl->GetIpState( &lOpen, &lRunning, &lCount, plPIDArray);

	if(FAILED(hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetDataReceptionStats method failed, error: 0x%8.8x"), hr);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
	}

	csMessage.Format( _T("%d Active PID%s%s\n\n"), 
					  lCount, 
					  lCount > 1 ? _T("s") : _T(""),
					  lCount > 0 ? _T(":") : _T(""));

	for (int x = 0 ; x < lCount ; x++) 
	{
		m_csTemp.Format( _T("%d\n"), plPIDArray[x]);
		csMessage += m_csTemp;
	}

	// Delete PIDs array
	if( plPIDArray)
	{
		delete [] plPIDArray;
		plPIDArray = NULL;
	}

	AfxMessageBox( csMessage);
}



void CTunerCtrlDlg::OnBnClickedButtonShowTsPids()
{
	HRESULT hr; 
	CString csMessage;
	
	// Get Maximum number of IP PIDs
	long lOpen;
	long lRunning;
	long lCount;

	// Paranoia
	ASSERT( m_pB2C2FilterDataCtrl);

	hr = m_pB2C2FilterDataCtrl->GetMaxPIDCount( &lCount);

	if( FAILED( hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxPIDCount method failed, error: 0x%8.8x"), hr);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	// Validate MAX number of Global PIDs

	if( lCount <= 0)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxPIDCount returned %ld"), lCount);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	// Create PIDs array
	long *plPIDArray = new long[lCount];

	ASSERT( plPIDArray);
	if( !plPIDArray)
	{
		AfxThrowMemoryException();
	}

	// Get Global PIDs.

	hr = m_pB2C2FilterDataCtrl->GetTsState( &lOpen, &lRunning, &lCount, plPIDArray);

	if(FAILED(hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetTsState method failed, error: 0x%8.8x"), hr);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
	}

	csMessage.Format( _T("%d Active PID%s%s\n\n"), 
					  lCount, 
					  lCount > 1 ? _T("s") : _T(""),
					  lCount > 0 ? _T(":") : _T(""));

	for (int x = 0 ; x < lCount ; x++) 
	{
		m_csTemp.Format( _T("%d\n"), plPIDArray[x]);
		csMessage += m_csTemp;
	}

	// Delete PIDs array
	if( plPIDArray)
	{
		delete [] plPIDArray;
		plPIDArray = NULL;
	}

	AfxMessageBox( csMessage);
}


void CTunerCtrlDlg::OnBnClickedButtonShowAllPids() 
{
	HRESULT hr; 
	CString csMessage;
	
	// Get Maximum number of IP PIDs
	long lOpen;
	long lRunning;
	long lCount;
	long lCountTs;
	long *plPIDArray;
	long *plPIDArrayTs;

	// Paranoia
	ASSERT( m_pB2C2FilterDataCtrl);

	hr = m_pB2C2FilterDataCtrl->GetMaxIpPIDCount( &lCount);

	if( FAILED( hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxIpPIDCount method failed, error: 0x%8.8x"), hr);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	// Validate MAX number of IP PIDs

	if( lCount < 0)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxIpPIDCount returned %ld"), lCount);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	hr = m_pB2C2FilterDataCtrl->GetMaxPIDCount( &lCountTs);

	if( FAILED( hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxPIDCount method failed, error: 0x%8.8x"), hr);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	// Validate MAX number of Global PIDs

	if( lCountTs < 0)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetMaxPIDCount returned %ld"), lCount);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	if( (lCount + lCountTs) == 0)
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. PID count = 0"));
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);

		return;
	}

	if (lCount > 0)
	{
		// Create PIDs array
		plPIDArray = new long[lCount];

		ASSERT( plPIDArray);

		if ( !plPIDArray)
		{
			AfxThrowMemoryException();
		}

		// Get IP PIDs.

		hr = m_pB2C2FilterDataCtrl->GetIpState( &lOpen, &lRunning, &lCount, plPIDArray);

		if (FAILED(hr))
		{
			m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetDataReceptionStats method failed, error: 0x%8.8x"), hr);
			MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
		}
	}

// Now get the TS PIDs

	if (lCountTs > 0)
	{
		// Create PIDs array
		plPIDArrayTs = new long[lCountTs];

		ASSERT( plPIDArrayTs);

		if( !plPIDArrayTs)
		{
			AfxThrowMemoryException();
		}

		// Get Global PIDs.

		hr = m_pB2C2FilterDataCtrl->GetTsState( &lOpen, &lRunning, &lCountTs, plPIDArrayTs);

		if(FAILED(hr))
		{
			m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface GetTsState method failed, error: 0x%8.8x"), hr);
			MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
		}
	}

	csMessage.Format( _T("%d Active PID%s%s\n\n"), 
					  lCount + lCountTs, 
					  lCount + lCountTs > 1 ? _T("s") : _T(""),
					  lCount + lCountTs > 0 ? _T(":") : _T(""));

	for (int x = 0 ; x < lCount ; x++) 
	{
		m_csTemp.Format( _T("%d\n"), plPIDArray[x]);
		csMessage += m_csTemp;
	}

	// Delete PIDs array
	if( plPIDArray)
	{
		delete [] plPIDArray;
		plPIDArray = NULL;
	}

	for (int x = 0 ; x < lCountTs ; x++) 
	{
		m_csTemp.Format( _T("%d\n"), plPIDArrayTs[x]);
		csMessage += m_csTemp;
	}

	// Delete PIDs array
	if( plPIDArray)
	{
		delete [] plPIDArrayTs;
		plPIDArrayTs = NULL;
	}

	AfxMessageBox( csMessage);
}



void CTunerCtrlDlg::OnButtonSetUnicastMac() 
{
	HRESULT hr;

	// Paranoia
	ASSERT( m_pB2C2FilterDataCtrl);

	CString strMacAddress;
	GetDlgItem(IDC_EDIT_NEW_UNICAST_MAC)->GetWindowText(strMacAddress);	

	int iMacAddress[8] = {NULL};
	UCHAR ucMacAddress[8];

	sscanf(strMacAddress.operator LPCSTR(),"%2x%2x%2x%2x%2x%2x",&iMacAddress[0],&iMacAddress[1],&iMacAddress[2],&iMacAddress[3],
			&iMacAddress[4],&iMacAddress[5]);

	ucMacAddress[0] = (UCHAR) iMacAddress[0];
	ucMacAddress[1] = (UCHAR) iMacAddress[1];
	ucMacAddress[2] = (UCHAR) iMacAddress[2];
	ucMacAddress[3] = (UCHAR) iMacAddress[3];
	ucMacAddress[4] = (UCHAR) iMacAddress[4];
	ucMacAddress[5] = (UCHAR) iMacAddress[5];

	hr = m_pB2C2FilterDataCtrl->SetUnicastMacAddress((UCHAR*)ucMacAddress);

	if(FAILED(hr))
	{
		m_csTemp.Format( _T("B2C2 MPEG2 Filter Data Ctrl. Interface SetUnicastMacAddress failed, error: 0x%8.8x"), hr);
		MessageBox( m_csTemp, "B2C2 TunerCtrl", MB_OK);
	}

	// Get the mac address, update in dialog
	UpdateMacAddressField ();
}




/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::InitializeNotification() 

	Registers this windows class for receiving a device notification message 
*/
void CTunerCtrlDlg::InitializeNotification()
{
#if defined _B2C2_USE_DEVICE_NOTIFICATION

	ASSERT( m_pB2FilterGraph);
	if( m_pB2FilterGraph)
	{
		VERIFY( m_pB2FilterGraph->RegisterDeviceNotification( GetSafeHwnd()));
	}

#endif //defined _B2C2_USE_DEVICE_NOTIFICATION
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::ReleaseNotification() 

	Un-registers this windows class for receiving a device notification message 
*/
void CTunerCtrlDlg::ReleaseNotification()
{
#if defined _B2C2_USE_DEVICE_NOTIFICATION

	ASSERT( m_pB2FilterGraph);
	if( !m_pB2FilterGraph)
	{
		return;
	}

	if( !m_pB2FilterGraph->UnregisterDeviceNotification())
	{
		TRACE( _T("UnregisterDeviceNotification failed! (#%lu)\n"), m_pB2FilterGraph->GetLastError());
	}

#endif //defined _B2C2_USE_DEVICE_NOTIFICATION
}

/*----------------------------------------------------------------------------*/
/*	FUNCTION: CTunerCtrlDlg::ReleaseNotification() 

	Handles the Change notification message.
*/
void CTunerCtrlDlg::OnDeviceChange(WPARAM wChangeEvent, LPARAM lData)
{
	if (!m_pB2FilterGraph)
	{
		ASSERT (FALSE);
		return;
	}

#if defined _B2C2_USE_DEVICE_NOTIFICATION

	if (   !m_pB2FilterGraph->IsInitialized()							// Device detected?
		&& m_pB2FilterGraph->IsDeviceArrival(wChangeEvent, lData) )
	{
		InitializeB2C2Filter();
	}

	if (   m_pB2FilterGraph->IsInitialized()
		&& m_pB2FilterGraph->IsDeviceRemoveComplete(wChangeEvent, lData))
	{
		ReleaseB2C2Filter();
	}

#endif //defined _B2C2_USE_DEVICE_NOTIFICATION
}

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


void CTunerCtrlDlg::OnBnClickedPlayAudioVideo()
{
	UpdateData( TRUE );

	// Put parameters into outbound structure
//	m_TuningParameters.lFrequencyKhz = (int) (m_fFrequency * 1000); 
//	m_TuningParameters.iVideoPID = m_iVideoPID; 
//	m_TuningParameters.iAudioPID = m_iAudioPID; 

	CAVPlaybackDlg AVPlaybackDlg;

	AVPlaybackDlg.PassAudioVideoPID(m_iAudioPID,m_iVideoPID);
	AVPlaybackDlg.PassAutoDeleteTimeshift(m_bAutoDeleteTimeshift);
	AVPlaybackDlg.PassAutoStartTimeshift(m_bAutoStartTimeshift);

	AVPlaybackDlg.PassB2C2MPEG2Adapter(m_pB2FilterGraph);

//	m_pMainWnd = &dlg;


	int nResponse = AVPlaybackDlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with OK
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with Cancel
	}

}


void CTunerCtrlDlg::OnBnClickedButtonStream()
{
	int x;

	UpdateData( TRUE );

	// Find a free Mutlicast Dialog entry

	tMulticastInfo* pMulticastInfo;

	for (x = 0 ; x < 20 ; x++ )
	{
		if (MulticastInfo[x].m_pAVStreamingDlg == NULL)
		{
			pMulticastInfo = &MulticastInfo[x];
			break;
		}
	}
	if (x == 20)
	{
		return;
	}


	// Copy Multicast Information from User Fields into Multicast Information structure

	unsigned char ucField1;
	unsigned char ucField2;
	unsigned char ucField3;
	unsigned char ucField4;

	ZeroMemory( pMulticastInfo, sizeof (tMulticastInfo));

	m_NetworkAdapterCtrl.GetAddress(ucField1,ucField2,ucField3,ucField4);
	sprintf(pMulticastInfo->szNetworkAdapter,"%d.%d.%d.%d",ucField1,ucField2,ucField3,ucField4);

	m_MulticastAddressCtrl.GetAddress(ucField1,ucField2,ucField3,ucField4);
	sprintf(pMulticastInfo->szMulticastAddress,"%d.%d.%d.%d",ucField1,ucField2,ucField3,ucField4);

	pMulticastInfo->wMulticastPort = (WORD) m_dwMulticastPort;

	if (m_dwMulticastPID1 != 0x1fff) 
	{
        pMulticastInfo->alPIDList[pMulticastInfo->lPIDCount++] = m_dwMulticastPID1;
	}
	if (m_dwMulticastPID2 != 0x1fff) 
	{
        pMulticastInfo->alPIDList[pMulticastInfo->lPIDCount++] = m_dwMulticastPID2;
	}
	if (m_dwMulticastPID3 != 0x1fff) 
	{
        pMulticastInfo->alPIDList[pMulticastInfo->lPIDCount++] = m_dwMulticastPID3;
	}
	if (m_dwMulticastPID4 != 0x1fff) 
	{
        pMulticastInfo->alPIDList[pMulticastInfo->lPIDCount++] = m_dwMulticastPID4;
	}
	if (m_dwMulticastPID5 != 0x1fff) 
	{
        pMulticastInfo->alPIDList[pMulticastInfo->lPIDCount++] = m_dwMulticastPID5;
	}

	// Create the Dialog class
	pMulticastInfo->m_pAVStreamingDlg = new CAVStreamingDlg();

	// Pass required information to Dialog
	pMulticastInfo->m_pAVStreamingDlg->PassMulticastInfo(pMulticastInfo);
	pMulticastInfo->m_pAVStreamingDlg->PassB2C2MPEG2Adapter(m_pB2FilterGraph);

	// Create the Dialog itself
    BOOL bStatus = pMulticastInfo->m_pAVStreamingDlg->Create(IDD_AV_STREAMING_DIALOG,this);

	// Check if Create failed.
	if(!bStatus)
	{
        AfxMessageBox("Error creating Dialog");
	}
	else
	{
		pMulticastInfo->m_pAVStreamingDlg->ShowWindow(SW_SHOW);
	}
}


void CTunerCtrlDlg::CloseAVStreamingDlgs( void )
{
	int x;

	for (x = 0 ; x < 20 ; x++ )
	{
		if (MulticastInfo[x].m_pAVStreamingDlg )
		{
			MulticastInfo[x].m_pAVStreamingDlg->DestroyWindow();
		}
	}
	if (x == 20)
	{
		return;
	}
}

void CTunerCtrlDlg::OnBnClickedButtonGoEast()
{
	BYTE ucDiSEqCCommand[4] = { 0xE0, 0x31, 0x68, 0x00 };

	HRESULT hr;

	hr = m_pB2C2FilterTunerCtrl ->SendDiSEqCCommand(4, ucDiSEqCCommand);
}

void CTunerCtrlDlg::OnBnClickedButtonStop()
{
	BYTE ucDiSEqCCommand[3] = { 0xE0, 0x31, 0x60 };

	HRESULT hr;

	hr = m_pB2C2FilterTunerCtrl ->SendDiSEqCCommand(3, ucDiSEqCCommand);
}

void CTunerCtrlDlg::OnBnClickedButtonGoWest()
{
	BYTE ucDiSEqCCommand[4] = { 0xE0, 0x31, 0x69, 0x00 };

	HRESULT hr;

	hr = m_pB2C2FilterTunerCtrl ->SendDiSEqCCommand(4, ucDiSEqCCommand);
}

void CTunerCtrlDlg::OnBnClickedStaticRecordTs()
{
	// TODO: Add your control notification handler code here
}

void CTunerCtrlDlg::OnBnClickedButtonRecord()
{
	UpdateData( TRUE );

	tRecordingInfo* pRecordingInfo = &RecordingInfo;

	// Create the Dialog class
	m_pTSRecordingDlg = new CTSRecordingDlg();

	pRecordingInfo->lFileSizeLimit = m_lRecordingFileSizeLimit;
	pRecordingInfo->lTimeLimit = m_lRecordingTimeLimit;

	// Pass required information to Dialog
	m_pTSRecordingDlg->PassRecordingInfo(pRecordingInfo);
	m_pTSRecordingDlg->PassB2C2MPEG2Adapter(m_pB2FilterGraph);

//	CString csMessage;
//	csMessage.Format( _T("File Size Limit: %d\n"), m_lRecordingFileSizeLimit );
//	AfxMessageBox(csMessage);

//	csMessage.Format( _T("Time Limit: %d\n"), m_lRecordingTimeLimit );
//	AfxMessageBox(csMessage);


	// Create the Dialog itself
    BOOL bStatus = m_pTSRecordingDlg->Create(IDD_TS_RECORDING_DIALOG,this);

	// Check if Create failed.
	if(!bStatus)
	{
        AfxMessageBox("Error creating Dialog");
	}
	else
	{
		m_pTSRecordingDlg->ShowWindow(SW_SHOW);
	}
}


