///////////////////////////////////////////////
//	main.cpp - core code for the application //
///////////////////////////////////////////////

/************************************
  REVISION LOG ENTRY
  Revision By: Chris Gil
  Revised on 23/07/2002 19:40:00
  Version: V
  Comments: Added SNMP 
 ************************************/

/************************************
  REVISION LOG ENTRY
  Revision By: TimA
  Revised on 18/07/2001 11:29:51
  Version: V
  Comments: Modified extinfo, extclient, extdriver, to have connect() function so
			all constructors take no parameters
 ************************************/


/************************************
  REVISION LOG ENTRY
  Revision By: TimA
  Revised on 28/03/2001 14:42:29
  Version: V
  Comments: new comms class specifies the serial port number in the open() function
  now, rather than the constructor
 ************************************/



#include "stdafx.h"
#define EXT
#include "TopStrap_auto.h"

//
//  FUNCTION: WinMain()
//
//  PURPOSE: 
//
//  COMMENTS: main entry point for BNCS Driver "TopStrap_auto"
//
//
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	
	MSG msg;
	HACCEL hAccelTable;
	char acTemp[256];
	HANDLE hMut=NULL;

	lstrcpyn(acTemp,lpCmdLine,255);
	iDevice=atoi(acTemp);
		// Initialize global strings
		LoadString(hInstance, IDS_APP_TITLE, acTemp, MAX_LOADSTRING);
		wsprintf(szTitle,acTemp,iDevice);
		LoadString(hInstance, IDC_APPCLASS, szWindowClass, MAX_LOADSTRING);

		//check to see if an instance is already running
		hMut=CreateMutex(NULL,TRUE,szTitle);
		if (GetLastError()==ERROR_ALREADY_EXISTS)
			return -1; // terminate if it is

		MyRegisterClass(hInstance);

		// Perform application initialization:
		if (!InitInstance (hInstance, nCmdShow)) 
			{
			return FALSE;
			}

		hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TOPSTRAP_AUTO);

		// Main message loop:
		while (GetMessage(&msg, NULL, 0, 0)) 
			{
			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
				{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
				}
			}

	CloseHandle(hMut); // destroy mutex to allow subsequent instance to run
	return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_REG);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_TOPSTRAP_AUTO;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

	hWndMain = CreateWindow(szWindowClass, szTitle, WS_SYSMENU|WS_MINIMIZEBOX ,
      CW_USEDEFAULT, 0, APP_WIDTH, APP_HEIGHT, NULL, NULL, hInstance, NULL);

   if (!hWndMain)
   {
      return FALSE;
   }

#ifdef _DEBUG
   ShowWindow(hWndMain,nCmdShow);
#else
   //ShowWindow(hWndMain,nCmdShow);
   ShowWindow(hWndMain, SW_MINIMIZE);
#endif

   UpdateWindow(hWndMain);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  
//	COMMENTS:
//	
//	WM_COMMAND	- process the application menu
//  WM_DESTROY	- post a quit message and return
//	
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	RECT rctWindow;
	int wmId, wmEvent;
	char szFileName[256], szTmp[32];
	char szSection [MAX_LOADSTRING];
	LoadString(hInst, IDS_SECTION, szSection, MAX_LOADSTRING);

	switch (message) 
	{
		case WM_CREATE:
			return InitApp(hWnd);

		case WM_TIMER: 
			switch ( wParam ) {
				case TX_FLASHING_TIMER_ID: // basically a one second timer to toggle tx, bypass lights on and off 
					//Debug( "flash tx timer " );
					if (bTXFlashingMode==TRUE) {
						intFlashTXCounter--;
						sprintf( szTmp, "%d", intFlashTXCounter );
						SetDlgItemText(hWndDlg, IDC_TX_FLASHCOUNTER, szTmp );
						if (intFlashTXCounter>0 ) {
							// either turn on lights or turn off lights -
							if (bTXLightsOn==TRUE) 
								infoWriteInt(intDeviceMGNOutputs, GPI_FORCE_OFF, intMGN_OUTPUT_TX);
							else
								infoWriteInt(intDeviceMGNOutputs, GPI_FORCE_ON, intMGN_OUTPUT_TX);
						}
						else { // limit reached so kill timer, turn lights on permanently, set vars accordingly
							Debug( "flash tx timer turned off " );
							if (bBypassFlashingMode==FALSE )
								KillTimer( hWndMain, TX_FLASHING_TIMER_ID ); // ONLY turn timer off if not flashing bypass lights too
							intFlashTXCounter = int_MAX_TX_FLASH;
							bTXFlashingMode = FALSE;
							bTXLightsOn=TRUE;
							bTXFullMode = TRUE;
							SetDlgItemText(hWndDlg, IDC_TX_MODE, " TX Red Lghts ON" );
								SetDlgItemText(hWndDlg, IDC_TX_FLASHCOUNTER, "");
							// now send cmd to force on permanmently
							infoWriteInt(intDeviceMGNOutputs, GPI_FORCE_ON, intMGN_OUTPUT_TX);  // revertive from this will now turn on all interlocks
						}
					} // if flashingmode

					// now check for bypass flashing mode
					if (bBypassFlashingMode==TRUE ) {
						if (bBypassLightsOn==TRUE) {
								setMGNBypassList( GPI_FORCE_OFF );
								bBypassLightsOn = FALSE;
						}
						else {
								setMGNBypassList( GPI_FORCE_ON );
								bBypassLightsOn = TRUE;
						}
					}

				break;
			}
		break;

		case WM_SIZE: // if the main window is resized, resize the listbox too
			//Don't resize window with child dialog
			break;

		case WM_COMMAND:
			wmId    = LOWORD(wParam); 
			wmEvent = HIWORD(wParam); 
			// Parse the menu selections:
			switch (wmId)
			{
				case IDM_ABOUT:
				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
				   break;

				case IDM_EXIT:
				   DestroyWindow(hWnd);
				   break;

				case ID_DEBUG_CLEAR:
					SendMessage(hWndList,LB_RESETCONTENT,0,0L);
					break;

				case ID_DEBUG_ON:
					GetWindowRect(hWnd, &rctWindow);
					if (fDebug==TRUE) {
						CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_ON,MF_UNCHECKED);
						sprintf(szFileName, "dev_%03d.ini", iDevice);
						w_p(szFileName, szSection, "DebugMode", "0");
						fDebug=FALSE;

					} 
					else {
						MoveWindow(hWnd, rctWindow.left, rctWindow.top, APP_WIDTH, APP_HEIGHT, TRUE);
						CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_ON,MF_CHECKED);
						sprintf(szFileName, "dev_%03d.ini", iDevice);
						w_p(szFileName, szSection, "DebugMode", "1");
						fDebug=TRUE;

						CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_HIDE,MF_UNCHECKED);
						fDebugHide=FALSE;
					}
					break;

				case ID_DEBUG_HIDE:
					GetWindowRect(hWnd, &rctWindow);
					if (fDebugHide==TRUE) {
						MoveWindow(hWnd, rctWindow.left, rctWindow.top, APP_WIDTH, iChildHeight + 42, TRUE);
						CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_HIDE,MF_CHECKED);
						fDebugHide=FALSE;

						CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_ON,MF_UNCHECKED);
						sprintf(szFileName, "dev_%03d.ini", iDevice);
						w_p(szFileName, szSection, "DebugMode", "0");
						fDebug=FALSE;
					} 
					else {
						MoveWindow(hWnd, rctWindow.left, rctWindow.top, APP_WIDTH, APP_HEIGHT, TRUE);
						CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_HIDE,MF_UNCHECKED);
						fDebugHide=TRUE;

						CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_ON,MF_CHECKED);
						sprintf(szFileName, "dev_%03d.ini", iDevice);
						w_p(szFileName, szSection, "DebugMode", "1");
						fDebug=TRUE;
					}
					break;

				default:
				   return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;

		case WM_DESTROY:
			CloseApp(hWnd);
			PostQuitMessage(0);
			break;

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

//
//  FUNCTION: DlgProcChild()
//
//  PURPOSE: Message handler for child dialog.
//
//  COMMENTS: Displays the interface status
//
// 
LRESULT CALLBACK DlgProcChild(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			return TRUE;
			break;
		default:
			break;
	}
    return FALSE;
}

//
//  FUNCTION: About()
//
//  PURPOSE: Message handler for about box.
//
//  COMMENTS: Displays the compile date info
//				and used to display version info from
//				a version resource
//
// 
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
			{
			LPBYTE   abData;
			DWORD  handle;
			DWORD  dwSize;
			LPBYTE lpBuffer;
			LPSTR szName, szModFileName, szBuf;
			char acBuf[16];
			#define	PATH_LENGTH	256
			
			szName=(LPSTR)malloc(PATH_LENGTH);
			szModFileName=(LPSTR)malloc(PATH_LENGTH);
			szBuf=(LPSTR)malloc(PATH_LENGTH);

			/*get version info*/

			GetModuleFileName(hInst,szModFileName,PATH_LENGTH);

			dwSize = GetFileVersionInfoSize(szModFileName, &handle);

			abData=(LPBYTE)malloc(dwSize);

			GetFileVersionInfo(szModFileName, handle, dwSize, abData);
			
			if (dwSize)
				{
				/* get country translation */
				VerQueryValue((LPVOID)abData, "\\VarFileInfo\\Translation", (LPVOID*)&lpBuffer, (UINT *) &dwSize);
				/* make country code */
				wsprintf(acBuf,"%04X%04X",*(WORD*)lpBuffer,*(WORD*)(lpBuffer+2));

				if (dwSize!=0)
					{
					/* get a versioninfo file version number */
					wsprintf(szName,"\\StringFileInfo\\%s\\FileVersion",(LPSTR)acBuf);
					VerQueryValue((LPVOID)abData, (LPSTR) szName, (LPVOID*)&lpBuffer,(UINT *) &dwSize);
					}

				/* copy version number from byte buffer to a string buffer */
				lstrcpyn(szModFileName,(LPSTR)lpBuffer,(int)dwSize);

				/* copy to the dialog static text box */
				wsprintf(szBuf,"Version %s",szModFileName);
				SetDlgItemText (hDlg, IDC_VERSION, szBuf);
				}
			
			wsprintf(szName,"%s - %s",(LPSTR)__DATE__,(LPSTR)__TIME__);
			SetDlgItemText(hDlg,IDC_COMPID,szName);

			free((PVOID)abData);
			free((PVOID)szName);
			free((PVOID)szModFileName);
			free((PVOID)szBuf);
			}
			return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}

//
//  FUNCTION: InitApp()
//
//  PURPOSE: Things to do when main window is created
//
//  COMMENTS: Called from WM_CREATE message
//			 We create a list box to fill the main window to use as a
//			debugging tool, and configure the serial port and infodriver 
//			connections, as well as a circular fifo buffer
//
//

LRESULT InitApp(HWND hWnd)
{
	/* return 0 if OK, or -1 if an error occurs*/
	RECT rctWindow;
	char szResult[256]="";
	char szSlot[256]="";
	char szBuf[256]="";
	char szTmp[256]="";

	// Init Status Dialogs
	hWndDlg = CreateDialog(hInst, (LPCTSTR)IDD_STATUS, hWnd, (DLGPROC)DlgProcChild);
	GetClientRect(hWndDlg, &rctWindow);
	iChildHeight = rctWindow.bottom - rctWindow.top + 2;

	GetClientRect(hWnd,&rc);
	hWndList=CreateWindow("LISTBOX","",WS_CHILD | WS_VSCROLL | LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS,
			0,iChildHeight,rc.right-rc.left,rc.bottom-rc.top-iChildHeight,
			hWnd,(HMENU)IDW_LIST,hInst,0);
	ShowWindow(hWndList,SW_SHOW);

	LoadIni();

	if (fDebug) {
		MoveWindow(hWnd, rctWindow.left, rctWindow.top, APP_WIDTH, APP_HEIGHT, TRUE);
		CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_ON,MF_CHECKED);
		CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_HIDE,MF_UNCHECKED);
	}
	else {
		MoveWindow(hWnd, rctWindow.left, rctWindow.top, APP_WIDTH, iChildHeight + 42, TRUE);
		CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_ON,MF_UNCHECKED);
		CheckMenuItem(GetSubMenu(GetMenu(hWnd),1),ID_DEBUG_HIDE,MF_CHECKED);
	}

	ei.notify(InfoNotify);
	switch (ei.connect(iDevice)) // connect to infodriver
	{
		case CONNECTED: 
			Debug("Connected OK to infodriver %d",ei.iDevice);
			break;	

		case CANT_FIND_INFODRIVER:
			Debug("Connect failed to infodriver %d",ei.iDevice);
			wsprintf( szTmp, "Failed to connect to infodriver %d",ei.iDevice ); 
			MessageBox( hWnd, szTmp, szTitle, MB_ICONSTOP);
			PostMessage( hWnd, WM_CLOSE, 0, 0 );
			break;

		default:
			Debug("Other Error - code %d",ei.iStatus);
			MessageBox( hWnd, szTmp, szTitle, MB_ICONSTOP);
			PostMessage( hWnd, WM_CLOSE, 0, 0 );
	}
	ei.setcounters(&lTXID, &lRXID);

	ec.notify(CSIClientNotify);
	switch (ec.connect()){
		case CONNECTED: 
			Debug("Connected OK to CSI");
			break;

		case CANT_FIND_CSI:
			Debug("Connect failed to CSI");
			wsprintf( szTmp, "Failed to connect to CSI" ); 
			MessageBox( hWnd, szTmp, szTitle, MB_ICONSTOP);
			PostMessage( hWnd, WM_CLOSE, 0, 0 );
			break;

		default:
			Debug("Other Error - code %d",ec.getstate());
	}

	getAppSettings();
	initStatusDialog();

	//register with the SDI router
	ec.regtallyrange(intDeviceSDI, intSDI_DEST_CCA_LINE, intSDI_DEST_CCA_LINE);
	ec.regtallyrange(intDeviceSDI, intSDI_DEST_CCA_RES1, intSDI_DEST_CCA_RES1, INSERT);
	ec.regtallyrange(intDeviceSDI, intSDI_DEST_BYPASS, intSDI_DEST_BYPASS, INSERT);
	//register with the AES router
//	ec.regtallyrange(intDeviceAES, intAES_DEST_CCA_M1, intAES_DEST_CCA_M1);
//	ec.regtallyrange(intDeviceAES, intAES_DEST_CCA_M2, intAES_DEST_CCA_M2, INSERT);
//	ec.regtallyrange(intDeviceAES, intAES_DEST_CCA_RES1, intAES_DEST_CCA_RES1, INSERT);
//	ec.regtallyrange(intDeviceAES, intAES_DEST_CCA_RES2, intAES_DEST_CCA_RES2, INSERT);
//	ec.regtallyrange(intDeviceAES, intAES_DEST_BYPASS1, intAES_DEST_BYPASS1, INSERT);
//	ec.regtallyrange(intDeviceAES, intAES_DEST_BYPASS2, intAES_DEST_BYPASS2, INSERT);

	//register with the Studer router
//	ec.regtallyrange(intDeviceStuder, intSTUDER_DEST_HWY_BYPASS1, intSTUDER_DEST_HWY_BYPASS1);
//	ec.regtallyrange(intDeviceStuder, intSTUDER_DEST_HWY_BYPASS2, intSTUDER_DEST_HWY_BYPASS2, INSERT);
	// new 1.2
//	ec.regtallyrange(intDeviceStuder, intSTUDER_DEST_INT_PROG_CUT, intSTUDER_DEST_INT_PROG_CUT, INSERT);
//	ec.regtallyrange(intDeviceStuder, intSTUDER_DEST_EXT_PROG_CUT, intSTUDER_DEST_EXT_PROG_CUT, INSERT);

	//register with the MGN GPI outputs
	ec.regtallyrange(intDeviceMGNOutputs, intMGN_OUTPUT_REH, intMGN_OUTPUT_REH);
	ec.regtallyrange(intDeviceMGNOutputs, intMGN_OUTPUT_TX, intMGN_OUTPUT_TX, INSERT);
//Added by Simon
	ec.regtallyrange(intDeviceMGNOutputs, sltMGN_OUTPUT_VENT_OFF, sltMGN_OUTPUT_VENT_OFF,INSERT);
	ec.regtallyrange(intDeviceMGNOutputs, sltMGN_OUTPUT_VTTONE16, sltMGN_OUTPUT_VTTONE16, INSERT);
	ec.regtallyrange(intDeviceMGNOutputs, sltMGN_OUTPUT_VTONE712, sltMGN_OUTPUT_VTONE712,INSERT);
	ec.regtallyrange(intDeviceMGNOutputs, sltMGN_OUTPUT_TONEM1, sltMGN_OUTPUT_TONEM1, INSERT);
	ec.regtallyrange(intDeviceMGNOutputs, sltMGN_OUTPUT_TONERES1, sltMGN_OUTPUT_TONERES1,INSERT);
	ec.regtallyrange(intDeviceMGNOutputs, sltMGN_OUTPUT_INT_CUT, sltMGN_OUTPUT_INT_CUT, INSERT);
	ec.regtallyrange(intDeviceMGNOutputs, sltMGN_OUTPUT_EXT_CUT, sltMGN_OUTPUT_EXT_CUT,INSERT);
	Debug("Got this far");

	//Initialise the REH and TX states to -1 (unknown);
	intRehState = GPI_UNKNOWN;	
	intTXState = GPI_UNKNOWN;	
	intFloorOffState = GPI_UNKNOWN;
	blnRehWasForced	= false;
	bTXFlashingMode = FALSE;  // new ver 1.2
	bTXLightsOn = FALSE;
	bStartTXMode = FALSE;
	bTXFullMode = FALSE;

	bBypassFlashingMode = FALSE;
	bBypassLightsOn = FALSE;
	
	//initialise each state
	intSDIBarsLineState = GPI_OFF;
	intSDIBarsRes1State = GPI_OFF;

	intSDIBypassState = GPI_OFF;
	intSDIBypassState_B = GPI_OFF;
	intSDIBypassState_RES = GPI_OFF;


	intVentOffState = GPI_FORCE_OFF; //Added by SA
	intToneM1State = GPI_FORCE_OFF;
	intToneRes1State = GPI_FORCE_OFF;
	intVTTone16State = GPI_FORCE_OFF;
	intVTTone712State = GPI_FORCE_OFF;
	intINTProgCutState = GPI_FORCE_OFF;
	intEXTProgCutState = GPI_FORCE_OFF;

//	intAESToneM1State = GPI_OFF;
//	intAESToneM2State = GPI_OFF;
//	intAESToneRes1State = GPI_OFF;
//	intAESToneRes2State = GPI_OFF;
//	intAESBypass1State = GPI_OFF;
//	intAESBypass2State = GPI_OFF;
//	intINTProgCutState = GPI_OFF; 
//	intEXTProgCutState = GPI_OFF; 
	intFlashTXButtonState = GPI_OFF; 

	//Assert each state to off status
	sprintf(szSlot, "%d", GPI_OFF);
	ei.setslot(SLOT_BARS_LINE, szSlot);
	ei.setslot(SLOT_BARS_RES1, szSlot);
	ei.setslot(SLOT_TONE_M1, szSlot);
//	ei.setslot(SLOT_TONE_M2, szSlot);
	ei.setslot(SLOT_TONE_RES1, szSlot);
//	ei.setslot(SLOT_TONE_RES2, szSlot);
	ei.setslot(SLOT_AUDIO_BYPASS_ACTION1, szSlot);
	ei.setslot(SLOT_AUDIO_BYPASS_ACTION2, szSlot);
	ei.setslot(SLOT_FLASH_TX, szSlot);
	ei.setslot(SLOT_INT_PROG_CUT, szSlot);
	ei.setslot(SLOT_EXT_PROG_CUT, szSlot);
//Added by Simon
	ei.setslot(SLOT_VENT_OFF, szSlot);
	ei.setslot(SLOT_TONE_VT1_6, szSlot);
	ei.setslot(SLOT_TONE_VT7_12, szSlot);
	ei.setslot(SLOT_TONE_M1, szSlot);
	ei.setslot(SLOT_TONE_RES1, szSlot);
	ei.setslot(SLOT_INT_PROG_CUT,szSlot);
	ei.setslot(SLOT_EXT_PROG_CUT, szSlot);
	//update UI
	updateUI(SLOT_BARS_LINE);
	updateUI(SLOT_BARS_RES1);
	updateUI(SLOT_TONE_M1);
//	updateUI(SLOT_TONE_M2);
	updateUI(SLOT_TONE_RES1);
//	updateUI(SLOT_TONE_RES2);
	updateUI(SLOT_VIDEO_BYPASS_A);
	updateUI(SLOT_AUDIO_BYPASS_ACTION1);
	updateUI(SLOT_AUDIO_BYPASS_ACTION2);
	updateUI(SLOT_FLASH_TX);
	updateUI(SLOT_INT_PROG_CUT);
	updateUI(SLOT_EXT_PROG_CUT);

	intSDILineSourcePreBars = 0;
//	intAESM1SourcePreTone = 0;
//	intAESM2SourcePreTone = 0;
//	intAESRes1SourcePreTone = 0;
//	intAESRes2SourcePreTone = 0;
//	intINTProgCutSrc = 0; 
//	intEXTProgCutSrc = 0; 

	//note sources initialised to current sources on bypass audition destinations
	//note that as the source is either on the studer or aes router 
	//	the tieline usage must also be considered
	//	and the source index must be translated to the tieline router index
//	intAESSourceBypass1 = 0;		//will contain the source routed to dest in intAES_DEST_BYPASS1
//	intAESSourceBypass2 = 0;		//will contain the source routed to dest in intAES_DEST_BYPASS2
//	intStuderSourceBypass1 = 0;		//will contain the source routed to dest in intSTUDER_DEST_HWY_BYPASS1
//	intStuderSourceBypass2 = 0;		//will contain the source routed to dest in intSTUDER_DEST_HWY_BYPASS2

	//get the previous audio bypass sources
//	ei.getslot(SLOT_AUDIO_BYPASS_SRCE1, szResult);
//	intTielineSourceBypass1 = atoi(szResult);
//	ei.getslot(SLOT_AUDIO_BYPASS_SRCE2, szResult);
//	intTielineSourceBypass2 = atoi(szResult);

//	if((intTielineSourceBypass1 < 1) || (intTielineSourceBypass1 >= intTielineRouterSize)){
//		intTielineSourceBypass1 = 1;
//	}
//	if((intTielineSourceBypass2 < 1) || (intTielineSourceBypass2 >= intTielineRouterSize)){
//		intTielineSourceBypass2 = 1;
//	}

	//note preview state  initialised to listening to current bypass source ie BYPASS_PREVIEW_PVW
	// - ensure that revertive is sent and that the desk outputs are routed
	// alternatively BUT WE ARE NOT DOING THIS NOW:
	//	1.	find out what is currently routed to the bypass audition output(s)
	//	2.	if the source is the desk output it suggests that preview is on
	//	3.  if the source is otherwise then preview is off 
	//	4.  AND this source is the currently selected bypass source
//	intAESBypass1PreviewState = BYPASS_PREVIEW_PVW;
//	intAESBypass2PreviewState = BYPASS_PREVIEW_PVW;

	intBypassAVState = GPI_OFF;
	intBypassAudioState = GPI_OFF;
	intBypassVisionState = GPI_OFF;
	
	setFloorOff(0);
	
	//Poll the SDI router
	routerPoll(intDeviceSDI, intSDI_DEST_CCA_LINE, intSDI_DEST_CCA_LINE);
	routerPoll(intDeviceSDI, intSDI_DEST_CCA_RES1, intSDI_DEST_CCA_RES1);
	
	//Poll the AES router
//	routerPoll(intDeviceAES, intAES_DEST_CCA_M1, intAES_DEST_CCA_M1);
//	routerPoll(intDeviceAES, intAES_DEST_CCA_M2, intAES_DEST_CCA_M2);
//	routerPoll(intDeviceAES, intAES_DEST_CCA_RES1, intAES_DEST_CCA_RES1);
//	routerPoll(intDeviceAES, intAES_DEST_CCA_RES2, intAES_DEST_CCA_RES2);
//	routerPoll(intDeviceAES, intAES_DEST_BYPASS1, intAES_DEST_BYPASS1);
//	routerPoll(intDeviceAES, intAES_DEST_BYPASS2, intAES_DEST_BYPASS2);


	//Poll the Studer router
//	routerPoll(intDeviceStuder, intSTUDER_DEST_HWY_BYPASS1, intSTUDER_DEST_HWY_BYPASS1);
//	routerPoll(intDeviceStuder, intSTUDER_DEST_HWY_BYPASS2, intSTUDER_DEST_HWY_BYPASS2);
	//new ver 1.2
//	routerPoll(intDeviceAES, intSTUDER_DEST_INT_PROG_CUT, intSTUDER_DEST_INT_PROG_CUT);
//	routerPoll(intDeviceAES, intSTUDER_DEST_EXT_PROG_CUT, intSTUDER_DEST_EXT_PROG_CUT);

	//Poll the MGN cue director
	infoPoll(intDeviceMGNOutputs, intMGN_OUTPUT_REH, intMGN_OUTPUT_REH);
	infoPoll(intDeviceMGNOutputs, intMGN_OUTPUT_TX, intMGN_OUTPUT_TX);

	//Added by Simon
	infoPoll(intDeviceMGNOutputs, sltMGN_OUTPUT_VENT_OFF, sltMGN_OUTPUT_VENT_OFF);
	infoPoll(intDeviceMGNOutputs, sltMGN_OUTPUT_VTTONE16, sltMGN_OUTPUT_VTTONE16);
	infoPoll(intDeviceMGNOutputs, sltMGN_OUTPUT_VTONE712, sltMGN_OUTPUT_VTONE712);
	infoPoll(intDeviceMGNOutputs, sltMGN_OUTPUT_TONEM1, sltMGN_OUTPUT_TONEM1);
	infoPoll(intDeviceMGNOutputs, sltMGN_OUTPUT_TONERES1, sltMGN_OUTPUT_TONERES1);
	infoPoll(intDeviceMGNOutputs, sltMGN_OUTPUT_INT_CUT, sltMGN_OUTPUT_INT_CUT);
	infoPoll(intDeviceMGNOutputs, sltMGN_OUTPUT_EXT_CUT, sltMGN_OUTPUT_EXT_CUT);
return 0;
}

//
//  FUNCTION: CloseApp()
//
//  PURPOSE: Things to do when main window is destroyed
//
//  COMMENTS: Called from WM_DESTROY message
//			The listbox debug window is a child of the main, so it will be 
//			destroyed automatically. 
//
void CloseApp(HWND hWnd)
{
}


//
//  FUNCTION: LoadIni()
//
//  PURPOSE: Assign (global) variables with values from .ini file
//
//  COMMENTS: The [section] name is gotten from a stringtable resource
//			 which defines it. It is the same name as the application, defined by the wizard
//			
//			
void LoadIni(void)
{
char szFileName[32];
char szSection [MAX_LOADSTRING];

iWorkstation=getWS();

wsprintf(szFileName,"DEV_%03d.ini",iDevice);
LoadString(hInst, IDS_SECTION, szSection, MAX_LOADSTRING);

/* extract debug and log parameters from ini file */
fDebug=atoi(r_p(szFileName,szSection,"DebugMode","1",TRUE));
fDebugHide = fDebug;
fLog=atoi(r_p(szFileName,szSection,"LogMode","0",TRUE));
}

/*!
\returns int The workstation number

\brief Function to get the workstation number

First checks to see if %CC_WORKSTATION% is defined
otherwise returns the WS stored in %WINDIR%\csi.ini

NOTE: 
In BNCSWizard apps the following change should be made to LoadINI()
- Replace:
	iWorkstation=atoi(r_p("CSI.INI","Network","Workstation","0",FALSE));
- With:
	iWorkstation=getWS();
- Also add the following to "app_name.h":
int		getWS(void);
*/
int getWS(void){
	char* szWS = getenv( "CC_WORKSTATION" );
	
	if(szWS){
			return atoi(szWS);
		}
		else{
			return atoi(r_p("CSI.INI","Network","Workstation","0",FALSE));
		}
}

/*!
\returns char* Pointer to data obtained
\param char* file The file to read from
\param char* section The section - [section]
\param char* entry The entry - entry=
\param char* defval The default value to return if not found
\param BOOL fWrite Flag - write the default value to the file

\brief Function to read one item of user data from an INI file

First checks to see if %CC_ROOT% and %CC_SYSTEM% are defined
If so the config files in %CC_ROOT%\%CC_SYSTEM%\config\system are used
Otherwise the config files in %WINDIR% are used
*/
char* r_p(char* file, char* section, char* entry, char* defval, BOOL fWrite)
{
	char szPath[256];	
	char* szCCRoot = getenv( "CC_ROOT" );
	char* szCCSystem = getenv( "CC_SYSTEM" );

	if(szCCRoot && szCCSystem){
		sprintf(szPath, "%s\\%s\\config\\system\\%s", szCCRoot, szCCSystem, file);
	}
	else {
		strcpy(szPath, file);
	}

	GetPrivateProfileString(section, entry, defval, szResult, sizeof(szResult), szPath);
	if (fWrite)
		w_p(file,section,entry,szResult);

	return szResult;
}

/*!
\returns void 
\param char* file The file to read from
\param char* section The section - [section]
\param char* entry The entry - entry=
\param char* setting The value to write - =value

\brief Function to write one item of user data to an INI file
	
First checks to see if %CC_ROOT% and %CC_SYSTEM% are defined
- If so the config files in %CC_ROOT%\%CC_SYSTEM%\config\system are used
- Otherwise the config files in %WINDIR% are used
*/
void w_p(char* file, char* section, char* entry, char* setting)
{
	char szPath[256];	
	char* szCCRoot = getenv( "CC_ROOT" );
	char* szCCSystem = getenv( "CC_SYSTEM" );

	if(szCCRoot && szCCSystem){
		sprintf(szPath, "%s\\%s\\config\\system\\%s", szCCRoot, szCCSystem, file);
	}
	else {
		strcpy(szPath, file);
	}
	WritePrivateProfileString(section, entry, setting, szPath);
}

//
//  FUNCTION: UpdateCounters()
//
//  PURPOSE: Writes current counter values to child dialog
//
//  COMMENTS: 
//				
//			
//			
void UpdateCounters(void) {
	char szBuf[32];
	//Update Infodriver External Message Count
	wsprintf(szBuf, "%08d", lTXID);
	SetDlgItemText(hWndDlg, IDC_IDTX, szBuf);
	wsprintf(szBuf, "%08d", lRXID);
	SetDlgItemText(hWndDlg, IDC_IDRX, szBuf);
}

//
//  FUNCTION: Debug()
//
//  PURPOSE: Writes debug information to the listbox
//
//  COMMENTS: The function works the same way as printf
//				example: Debug("Number=%d",iVal);
//			
//			
void Debug(LPCSTR szFmt, ...)
{
if (fDebug)
	{
	LPSTR szDebug=(LPSTR)malloc(0x10000);
	va_list argptr;

	va_start(argptr,szFmt);
	vsprintf(szDebug,szFmt,argptr);
	va_end(argptr);

	if (strlen(szDebug) > 160)
		szDebug[160]=0; //Truncate long debug messages

	SendMessage(hWndList, LB_ADDSTRING,0,(LPARAM) szDebug);	//Add message
	long lCount = SendMessage(hWndList,LB_GETCOUNT,0,0);	//Get List Count
	if (lCount > MAX_LB_ITEMS)
		{
		SendMessage(hWndList, LB_DELETESTRING, 0, 0);	//Delete item
		lCount--;
		}
	SendMessage(hWndList, LB_SETTOPINDEX, (WPARAM) lCount - 1, 0);	//Set Top Index
	free((PVOID)szDebug);
	}
}

//
//  FUNCTION: Log()
//
//  PURPOSE: Writes information to the log file
//
//  COMMENTS: The function works the same way as printf
//				example: Debug("Number=%d",iVal);
//			
//			
void Log(LPCSTR szFmt, ...)
{
char szLogFile[40];

if (fLog)
	{
	char tBuffer[9];
	char szDate[16];
	FILE *fp;
	LPSTR szLog=(LPSTR)malloc(0x10000);
	va_list argptr;
   struct tm *newtime;
   time_t long_time;

	va_start(argptr,szFmt);
	vsprintf(szLog,szFmt,argptr);
	va_end(argptr);

	time( &long_time );                // Get time as long integer. 
	newtime = localtime( &long_time ); // Convert to local time. 
	_strtime( tBuffer );
	sprintf(szDate, "%04d%02d%02d", newtime->tm_year+1900, newtime->tm_mon+1, newtime->tm_mday);

	wsprintf(szLogFile, "c:\\bncslogs\\%s_child2_%d.log", szDate, iDevice);
	Debug(szLogFile);
	if (fp = fopen(szLogFile, "a"))
	{
		fprintf(fp, tBuffer);
		fprintf(fp, " - ");
		fprintf(fp, szLog);
		fprintf(fp, "\r\n");
		fclose(fp);
	}

	free((PVOID)szLog);
	}
}


//
// Function name	: SplitString
// Description	   : Split a delimited string to an array of pointers to strings
// Return type		: int number of elements returned
//
//----------------------------------------------------------------------------//
// Takes a string and splits it up creating an array of pointers to the start //
// of the sections delimted by the array of specified char delimiters         //
// the delimter characters in "string" are overwritten with NULLs             //
// Usage:                                                                     //
// char szString[] = "1,2|3'4,5,6,7,";                                        //
// char delim[] = {',', '|', '\'', ',', ',', ',', ',',};                      //
// UINT count=7;                                                              //
// char *pElements[7];                                                        //
// int iLen;                                                                  //
//	iLen = SplitString( szString, delim, 7, pElements);                        //
//                                                                            //
// NOTE: This funcion works differently to strtok in that consecutive         //
// delimiters are not overlooked and so a NULL output string is possible      //
// i.e. a string                                                              //
//    hello,,dave                                                             //
// where ,,, is the delimiter will produce 3 output strings the 2nd of which  //
// will be NULL                                                               //
//----------------------------------------------------------------------------//
int SplitString(char *string, char *delim, UINT count, char **outarray )
{
	UINT x;
	UINT y;
	UINT len;										// length of the input string
	static char *szNull = "";				// generic NULL output string
	int delimlen;
	int dp;

	len = strlen( string );
	delimlen = strlen( delim );

	if(!len)										// if the input string is a NULL then set all the output strings to NULL
	{
		for (x = 0 ; x < count; x++ )
			outarray[x] = szNull;
		return 0;
	}

	outarray[0] = string;					// set the 1st output string to the beginning of the string

	for( x = 0,y = 1 ; (x < len) && (y < count); x++ )
	{
		if( delimlen < 2 )
			dp = 1;
		else
			dp = y;
		if(string[x] == delim[dp-1])
		{
			string[ x ] = '\0';
			if((x+1) < len)					// if there is another string following this one....
			{
				outarray[ y ] = &string[x+1];
				y++;								// increment the number of assigned buffer
			}
			else
			{
				outarray[ y ] = szNull;
			}
		}
	}

	x = y;
	while( x < count )
		outarray[x++] = szNull;
	return y;									// return the number of strings allocated
}
