//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//message_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int message_startup()
{
    if (window_helper_register(szMessageMasterName, &message_event)) return 1;
    if (!(message_window = window_helper_create(szMessageMasterName))) return 1;

    //No errors
    return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//controltype_button_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int agenttype_networkmonitor_startup()
{
	//This code stolen from the bb4win SDK example

	//Initialize the usages to 0.0 to start
	for (int i = 0; i < AGENTTYPE_NETWORKMONITOR_NUMINTERFACES; i++)
	{
		for(int j = 0; j < AGENTTYPE_NETWORKMONITOR_NUMTYPES; j++)
		{
			agenttype_networkmonitor_previous_values[i][j] = -1.0;
			agenttype_networkmonitor_values[i][j] = 0.0;
			StrFormatByteSizeOrg(0,agenttype_networkmonitor_textvalues[i][j]);
		}
	}

	//Create the list
	agenttype_networkmonitor_agents = list_create();

	//Register the window class
	agenttype_networkmonitor_windowclassregistered = false;
	if (window_helper_register(agenttype_networkmonitor_timerclass, &agenttype_networkmonitor_event))
	{
		//Couldn't register the window
		BBMessageBox(NULL, "failed on register class", "test", MB_OK);
		return 1;
	}
	agenttype_networkmonitor_windowclassregistered = true;

	//Create the window
	agenttype_networkmonitor_window = window_helper_create(agenttype_networkmonitor_timerclass);
	if (!agenttype_networkmonitor_window)
	{
		//Couldn't create the window
		BBMessageBox(NULL, "failed on window", "test", MB_OK);
		return 1;
	}


		//If we got this far, we can successfully use this function
		//Register this type with the AgentMaster
	agent_registertype(
		"Network Monitor",                   //Friendly name of agent type
		"NetworkMonitor",                    //Name of agent type
		CONTROL_FORMAT_DOUBLE|CONTROL_FORMAT_TEXT,				//Control type
		false,
		&agenttype_networkmonitor_create,
		&agenttype_networkmonitor_destroy,
		&agenttype_networkmonitor_message,
		&agenttype_networkmonitor_notify,
		&agenttype_networkmonitor_getdata,
		&agenttype_networkmonitor_menu_set,
		&agenttype_networkmonitor_menu_context,
		&agenttype_networkmonitor_notifytype
		);

	//No errors
	return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//controltype_button_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int agenttype_systeminfo_startup()
{
	//Create the list
	agenttype_systeminfo_agents = list_create();

	//Register the window class
	agenttype_systeminfo_windowclassregistered = false;
	if (window_helper_register(agenttype_systeminfo_timerclass, &agenttype_systeminfo_event))
	{
		//Couldn't register the window
		BBMessageBox(NULL, L"failed on register class", L"test", MB_OK);
		return 1;
	}
	agenttype_systeminfo_windowclassregistered = true;

	//Create the window
	agenttype_systeminfo_window = window_helper_create(agenttype_systeminfo_timerclass);
	if (!agenttype_systeminfo_window)
	{
		//Couldn't create the window
		BBMessageBox(NULL, L"failed on window", "test", MB_OK);
		return 1;
	}
	
	//initialize
	for (int i = 1; i < SYSTEMINFO_NUMTYPES; i++){
		agenttype_systeminfo_updatevalue(i);
	}

	//If we got this far, we can successfully use this function
	//Register this type with the AgentMaster
	agent_registertype(
		L"System Information",                   //Friendly name of agent type
		L"SystemInfo",                    //Name of agent type
		CONTROL_FORMAT_TEXT,				//Control type
		false,
		&agenttype_systeminfo_create,
		&agenttype_systeminfo_destroy,
		&agenttype_systeminfo_message,
		&agenttype_systeminfo_notify,
		&agenttype_systeminfo_getdata,
		&agenttype_systeminfo_menu_set,
		&agenttype_systeminfo_menu_context,
		&agenttype_systeminfo_notifytype
		);

	//No errors
	return 0;
}
bool AgentType_Mixer_XP::Init ()
{
	bool errorflag = false; //If there's an error
	//Create the reciever window class if neccessary
	//No errors
	s_mixer_controlcount++;
	if (s_mixer_controlcount > 0 && !mixer_recieverregistered)
	{
		if (!window_helper_register(mixer_recieverclass, &agenttype_mixer_recieverevent))
			mixer_recieverregistered = true;
		else
			errorflag = true;
	}

	//Create the reciever window
	m_hwnd_reciever = NULL;
	if (!errorflag)
	{
		m_hwnd_reciever = window_helper_create(mixer_recieverclass);
		if (!m_hwnd_reciever) errorflag = true;
	}

	if (!errorflag)
	{
		//Initialize the mixer values
		if (MMSYSERR_NOERROR != mixerOpen(&m_mixer_handle, m_device, (DWORD_PTR) m_hwnd_reciever, 0, CALLBACK_WINDOW))
			errorflag = true;
	}

	if (!errorflag)
	{
		//Set the control properties
		m_mixer_controldetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
		m_mixer_controldetails.dwControlID = m_control;
		m_mixer_controldetails.cChannels = 1;
		m_mixer_controldetails.cMultipleItems = 0;
		m_mixer_controldetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
	}

	if (errorflag)
	{
		Destroy();
		return false;
	}
	return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//controltype_button_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int agenttype_diskspacemonitor_startup()
{
	//Create the list
	agenttype_diskspacemonitor_agents = list_create();

	//Register the window class
	agenttype_diskspacemonitor_windowclassregistered = false;
	if (window_helper_register(agenttype_diskspacemonitor_timerclass, &agenttype_diskspacemonitor_event))
	{
		//Couldn't register the window
		BBMessageBox(NULL, "failed on register class", "test", MB_OK);
		return 1;
	}
	agenttype_diskspacemonitor_windowclassregistered = true;

	//Create the window
	agenttype_diskspacemonitor_window = window_helper_create(agenttype_diskspacemonitor_timerclass);
	if (!agenttype_diskspacemonitor_window)
	{
		//Couldn't create the window
		BBMessageBox(NULL, "failed on window", "test", MB_OK);
		return 1;
	}

	//If we got this far, we can successfully use this function
	//Register this type with the AgentMaster
	agent_registertype(
		"DiskSpace Monitor",                   //Friendly name of agent type
		"DiskSpaceMonitor",                    //Name of agent type
		CONTROL_FORMAT_SCALE|CONTROL_FORMAT_TEXT,				//Control type
		false,
		&agenttype_diskspacemonitor_create,
		&agenttype_diskspacemonitor_destroy,
		&agenttype_diskspacemonitor_message,
		&agenttype_diskspacemonitor_notify,
		&agenttype_diskspacemonitor_getdata,
		&agenttype_diskspacemonitor_menu_set,
		&agenttype_diskspacemonitor_menu_context,
		&agenttype_diskspacemonitor_notifytype
		);

	//No errors
	return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//controltype_button_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int agenttype_systemmonitor_startup()
{
	//This code stolen from the bb4win SDK example


	OSVERSIONINFO osvinfo;
	ZeroMemory(&osvinfo, sizeof(osvinfo));
	osvinfo.dwOSVersionInfoSize = sizeof (osvinfo);
	GetVersionEx(&osvinfo);
	isnt2kxp =	osvinfo.dwPlatformId == VER_PLATFORM_WIN32_NT;

	//Initialize the usages to 0.0 to start
	for (int i = 0; i < SYSTEMMONITOR_NUMTYPES; i++)
	{
		agenttype_systemmonitor_previous_values[i] = -1.0;
		agenttype_systemmonitor_values[i] = 0.0;
		strcpy(agenttype_systemmonitor_textvalues[i], "0%");
	}

	//Create the list
	agenttype_systemmonitor_agents = list_create();

	//Register the window class
	agenttype_systemmonitor_windowclassregistered = false;
	if (window_helper_register(agenttype_systemmonitor_timerclass, &agenttype_systemmonitor_event))
	{
		//Couldn't register the window
		BBMessageBox(NULL, "failed on register class", "test", MB_OK);
		return 1;
	}
	agenttype_systemmonitor_windowclassregistered = true;

	//Create the window
	agenttype_systemmonitor_window = window_helper_create(agenttype_systemmonitor_timerclass);
	if (!agenttype_systemmonitor_window)
	{
		//Couldn't create the window
		BBMessageBox(NULL, "failed on window", "test", MB_OK);
		return 1;
	}

	//Load the library
	if(isnt2kxp)
	{
		agenttype_systemmonitor_ntdllmodule = NULL;
		agenttype_systemmonitor_ntdllmodule = LoadLibrary("ntdll.dll");

		//Check to make sure it loaded properly
		if (agenttype_systemmonitor_ntdllmodule == NULL)
		{
			//We couldn't load the NTDLL library
			//Return immediately
			return 1;
			BBMessageBox(NULL, "failed on ntdll", "test", MB_OK);
		}

		//Get the NtQuerySystemInformation function
		agenttype_systemmonitor_ntquerysysteminformation = NULL;
		agenttype_systemmonitor_ntquerysysteminformation = (agenttype_systemmonitor_NtQuerySystemInformation) GetProcAddress(agenttype_systemmonitor_ntdllmodule, "NtQuerySystemInformation");

		//Check to make sure we could get the function
		if (agenttype_systemmonitor_ntquerysysteminformation == NULL)
		{
			//Error - couldn't get the function call
			FreeLibrary(agenttype_systemmonitor_ntdllmodule);
			BBMessageBox(NULL, "failed on get proc address", "test", MB_OK);
			return 1;
		}


		// @NOTE: this uses undocumented nt api.  GetSystemInfo is the way to go
		//Get the number of processors
		/*BOOL status;
		SYSTEM_BASIC_INFORMATION basicinformation;
		status = agenttype_systemmonitor_ntquerysysteminformation(agenttype_systemmonitor_SystemBasicInformation, &basicinformation, sizeof(basicinformation), NULL);
		if (status != NO_ERROR)
		{
			//Couldn't get the number of processors
			FreeLibrary(agenttype_systemmonitor_ntdllmodule);
			BBMessageBox(NULL, "failed on processor", "test", MB_OK);
			return 1;
		}*/

		SYSTEM_INFO sysinfo;
		GetSystemInfo( &sysinfo );

		//Record the number of processors
		agenttype_systemmonitor_number_processors = sysinfo.dwNumberOfProcessors;

		//If it is less than 1 or more than 64... assume an error (I don't think any super clusters are running BBI)
		if (agenttype_systemmonitor_number_processors < 1 || agenttype_systemmonitor_number_processors > 64)
		{
			FreeLibrary(agenttype_systemmonitor_ntdllmodule);
			BBMessageBox(NULL, "failed on number of processors", "test", MB_OK);
			return 1;
		}
	}

		//If we got this far, we can successfully use this function
		//Register this type with the AgentMaster
	agent_registertype(
		"System Monitor",                   //Friendly name of agent type
		"SystemMonitor",                    //Name of agent type
		CONTROL_FORMAT_SCALE|CONTROL_FORMAT_TEXT,				//Control type
		false,
		&agenttype_systemmonitor_create,
		&agenttype_systemmonitor_destroy,
		&agenttype_systemmonitor_message,
		&agenttype_systemmonitor_notify,
		&agenttype_systemmonitor_getdata,
		&agenttype_systemmonitor_menu_set,
		&agenttype_systemmonitor_menu_context,
		&agenttype_systemmonitor_notifytype
		);

	//No errors
	return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//agenttype_winamp_startup
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int agenttype_winamp_startup()
{
	//Register the window class
	agenttype_winamp_windowclassregistered = false;
	if (window_helper_register(agenttype_winamp_timerclass, &agenttype_winamp_event))
	{
		//Couldn't register the window
		return 1;
	}
	agenttype_winamp_windowclassregistered = true;

	//Create the window
	agenttype_winamp_window = window_helper_create(agenttype_winamp_timerclass);
	if (!agenttype_winamp_window)
	{
		//Couldn't create the window
		return 1;
	}

	//Create the list
	agenttype_winamp_agents = list_create();

	//Register this type with the ControlMaster
	agent_registertype(
		"Winamp",                           //Friendly name of agent type
		"Winamp",                           //Name of agent type
		CONTROL_FORMAT_TRIGGER,             //Control format
		true,
		&agenttype_winamp_create,
		&agenttype_winamp_destroy,
		&agenttype_winamp_message,
		&agenttype_winamp_notify,
		&agenttype_winamp_getdata,
		&agenttype_winamp_menu_set,
		&agenttype_winamp_menu_context,
		&agenttype_winamp_notifytype
	);

	//Register this type with the ControlMaster
	agent_registertype(
		"Winamp",                           //Friendly name of agent type
		"WinampScale",                      //Name of agent type
		CONTROL_FORMAT_SCALE,               //Control format
		true,
		&agenttype_winamppoller_create,
		&agenttype_winamp_destroy,
		&agenttype_winamp_message,
		&agenttype_winamppoller_notify,
		&agenttype_winamppoller_getdata,
		&agenttype_winamppoller_scale_menu_set,
		&agenttype_winamp_menu_context,
		&agenttype_winamp_notifytype
	);

	//Register this type with the ControlMaster
	agent_registertype(
		"Winamp",                           //Friendly name of agent type
		"WinampBool",                       //Name of agent type
		CONTROL_FORMAT_BOOL,                //Control format
		false,
		&agenttype_winamppoller_create,
		&agenttype_winamp_destroy,
		&agenttype_winamp_message,
		&agenttype_winamppoller_notify,
		&agenttype_winamppoller_getdata,
		&agenttype_winamppoller_bool_menu_set,
		&agenttype_winamp_menu_context,
		&agenttype_winamp_notifytype
	);

	//Register this type with the ControlMaster
	agent_registertype(
		"Winamp",                           //Friendly name of agent type
		"WinampText",                       //Name of agent type
		CONTROL_FORMAT_TEXT,                //Control format
		true,
		&agenttype_winamppoller_create,
		&agenttype_winamp_destroy,
		&agenttype_winamp_message,
		&agenttype_winamppoller_notify,
		&agenttype_winamppoller_getdata,
		&agenttype_winamppoller_text_menu_set,
		&agenttype_winamp_menu_context,
		&agenttype_winamp_notifytype
	);

	//No errors
	return 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//agenttype_mixer_create
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int agenttype_mixer_create(agent *a, char *parameterstring)
{
	//If there's an error
	bool errorflag = false;;

	//Check for error conditions
	if (strlen(parameterstring) >= 30) return false;

	//Break up the parts
	int tokensfound = BBTokenize(parameterstring, mixer_tokenptrs, 4, NULL);

	//Three tokens exactly required
	if (tokensfound != 3) return 1;

	long values[3];
	//Make sure they are all valid integers
	for (int i = 0; i < 3; i++)
	{
		if (!config_set_long(mixer_tokenptrs[i], &values[i])) return 1;
	}

	//Create the details
	agenttype_mixer_details *details = new agenttype_mixer_details;
	a->agentdetails = (void *) details;

	//Copy the values
	details->device = values[0];
	details->line = values[1];
	details->control = values[2];

	//Create the reciever window class if neccessary
	//No errors
	mixer_controlcount++;
	if (mixer_controlcount > 0 && !mixer_recieverregistered)
	{
		if (!window_helper_register(mixer_recieverclass, &agenttype_mixer_recieverevent)) mixer_recieverregistered = true;
		else errorflag = true;
	}

	//Create the reciever window
	details->hwnd_reciever = NULL;
	if (!errorflag)
	{
		details->hwnd_reciever = window_helper_create(mixer_recieverclass);
		if (!details->hwnd_reciever) errorflag = true;
	}

	if (!errorflag)
	{
		//Initialize the mixer values
		if (MMSYSERR_NOERROR != mixerOpen(&details->mixer_handle, details->device, (DWORD_PTR) details->hwnd_reciever, 0, CALLBACK_WINDOW)) errorflag = true;
	}

	if (!errorflag)
	{
		//Set the control properties
		details->mixer_controldetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
		details->mixer_controldetails.dwControlID = details->control;
		details->mixer_controldetails.cChannels = 1;
		details->mixer_controldetails.cMultipleItems = 0;
		details->mixer_controldetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);

		//Set the window property
		SetProp(details->hwnd_reciever, "mixagtptr", a);
	}

	if (errorflag)
	{
		if (details->hwnd_reciever)
			window_helper_destroy(details->hwnd_reciever);

		delete details;
		a->agentdetails = NULL;

		agent_destroy(&a);
		return 1;
	}

	return 0;
}