<commit_before>
/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
OTHER DEALINGS IN THE SOFTWARE.
*/

#include <cstdlib>

#include "config.h"
#include "device.h"
#include "args.h"
#include "disk_file.h"
#include "disk_filesystem.h"
#include "json_parser.h"
#include "keyboard.h"
#include "log.h"
#include "lua_environment.h"
#include "memory.h"
#include "mouse.h"
#include "os.h"
#include "os_window.h"
#include "resource_manager.h"
#include "string_setting.h"
#include "string_utils.h"
#include "touch.h"
#include "types.h"
#include "bundle.h"
#include "temp_allocator.h"
#include "resource_package.h"
#include "console_server.h"
#include "world.h"
#include "lua_stack.h"
#include "world_manager.h"
#include "network_filesystem.h"
#include "lua_system.h"
#include "debug_line.h"
#include "material_manager.h"
#include "gui.h"

#if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
	#include "bundle_compiler.h"
#endif

#if CROWN_PLATFORM_ANDROID
	#include "apk_filesystem.h"
#endif

#define MAX_SUBSYSTEMS_HEAP 8 * 1024 * 1024

namespace crown
{
//-----------------------------------------------------------------------------
Device::Device()
	: m_allocator(default_allocator(), MAX_SUBSYSTEMS_HEAP)

	, m_argc(0)
	, m_argv(NULL)

	, m_fileserver(0)
	, m_console_port(10001)

	, m_is_init(false)
	, m_is_running(false)
	, m_is_paused(false)

	, m_frame_count(0)

	, m_last_time(0)
	, m_current_time(0)
	, m_last_delta_time(0.0f)
	, m_time_since_start(0.0)

	, m_filesystem(NULL)
	, m_lua_environment(NULL)
	, m_renderer(NULL)

	, m_bundle_compiler(NULL)
	, m_console(NULL)
	, m_resource_manager(NULL)
	, m_resource_bundle(NULL)

	, m_world_manager(NULL)
{
	// Bundle dir is current dir by default.
	os::getcwd(m_bundle_dir, MAX_PATH_LENGTH);
	string::strncpy(m_source_dir, "", MAX_PATH_LENGTH);
	string::strncpy(m_boot_file, "lua/game", MAX_PATH_LENGTH);
}

//-----------------------------------------------------------------------------
Device::~Device()
{
}

//-----------------------------------------------------------------------------
void Device::init()
{
	// Initialize
	CE_LOGI("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);

	CE_LOGD("Creating filesystem...");
	// Default bundle filesystem
	#if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
		if (m_fileserver == 1)
		{
			m_filesystem = CE_NEW(m_allocator, NetworkFilesystem)(NetAddress(127, 0, 0, 1), 10001);
		}
		else
		{
			m_filesystem = CE_NEW(m_allocator, DiskFilesystem)(m_bundle_dir);
		}
	#elif CROWN_PLATFORM_ANDROID
		if (m_fileserver == 1)
		{
			m_filesystem = CE_NEW(m_allocator, NetworkFilesystem)(NetAddress(192, 168, 0, 7), 10001);
		}
		else
		{
			m_filesystem = CE_NEW(m_allocator, ApkFilesystem)();
		}
	#endif

	m_resource_bundle = Bundle::create(m_allocator, *m_filesystem);

	// Create resource manager
	CE_LOGD("Creating resource manager...");
	m_resource_manager = CE_NEW(m_allocator, ResourceManager)(*m_resource_bundle);

	// Create world manager
	CE_LOGD("Creating world manager...");
	m_world_manager = CE_NEW(m_allocator, WorldManager)();

	// Create window
	CE_LOGD("Creating main window...");
	m_window = CE_NEW(m_allocator, OsWindow);

	// Create input devices
	m_keyboard = CE_NEW(m_allocator, Keyboard);
	m_mouse = CE_NEW(m_allocator, Mouse);
	m_touch = CE_NEW(m_allocator, Touch);

	// Create renderer
	CE_LOGD("Creating renderer...");
	graphics_system::init();
	debug_line::init();
	Gui::init();

	CE_LOGD("Creating material manager...");
	material_manager::init();

	CE_LOGD("Creating lua system...");
	lua_system::init();
	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)(lua_system::state());

	CE_LOGD("Creating physics...");
	physics_system::init();

	CE_LOGD("Creating audio...");
	audio_system::init();

	CE_LOGD("Crown Engine initialized.");
	CE_LOGD("Initializing Game...");

	m_is_init = true;
	start();

	// Execute lua boot file
	m_lua_environment->load_and_execute(m_boot_file);
	m_lua_environment->call_global("init", 0);

	CE_LOGD("Total allocated size: %ld", m_allocator.allocated_size());
}

//-----------------------------------------------------------------------------
void Device::shutdown()
{
	CE_ASSERT(is_init(), "Engine is not initialized");

	// Shutdowns the game
	m_lua_environment->call_global("shutdown", 0);

	CE_LOGD("Releasing audio...");
	audio_system::shutdown();

	CE_LOGD("Releasing physics...");
	physics_system::shutdown();

	CE_LOGD("Releasing lua system...");
	lua_system::shutdown();
	if (m_lua_environment)
	{
		CE_DELETE(m_allocator, m_lua_environment);
	}

	CE_LOGD("Releasing input devices...");
	CE_DELETE(m_allocator, m_touch);
	CE_DELETE(m_allocator, m_mouse);
	CE_DELETE(m_allocator, m_keyboard);

	CE_LOGD("Releasing material manager...");
	material_manager::shutdown();

	CE_LOGD("Releasing renderer...");
	debug_line::shutdown();
	graphics_system::shutdown();

	CE_LOGD("Releasing world manager...");
	CE_DELETE(m_allocator, m_world_manager);

	CE_LOGD("Releasing resource manager...");
	if (m_resource_manager)
	{
		CE_DELETE(m_allocator, m_resource_manager);
	}

	if (m_resource_bundle)
	{
		Bundle::destroy(m_allocator, m_resource_bundle);
	}

	CE_LOGD("Releasing filesystem...");
	if (m_filesystem)
	{
		CE_DELETE(m_allocator, m_filesystem);
	}

	m_allocator.clear();
	m_is_init = false;
}

//-----------------------------------------------------------------------------
bool Device::is_init() const
{
	return m_is_init;
}

//-----------------------------------------------------------------------------
bool Device::is_paused() const
{
	return m_is_paused;
}

//-----------------------------------------------------------------------------
Filesystem* Device::filesystem()
{
	return m_filesystem;
}

//-----------------------------------------------------------------------------
ResourceManager* Device::resource_manager()
{
	return m_resource_manager;
}

//-----------------------------------------------------------------------------
LuaEnvironment* Device::lua_environment()
{
	return m_lua_environment;
}

//-----------------------------------------------------------------------------
OsWindow* Device::window()
{
	return m_window;
}

//-----------------------------------------------------------------------------
Renderer* Device::renderer()
{
	return NULL;
}

//-----------------------------------------------------------------------------
Keyboard* Device::keyboard()
{
	return m_keyboard;
}

//-----------------------------------------------------------------------------
Mouse* Device::mouse()
{
	return m_mouse;
}

//-----------------------------------------------------------------------------
Touch* Device::touch()
{
	return m_touch;
}

//-----------------------------------------------------------------------------
Accelerometer* Device::accelerometer()
{
	return NULL;
}

//-----------------------------------------------------------------------------
void Device::start()
{
	CE_ASSERT(m_is_init, "Cannot start uninitialized engine.");

	m_is_running = true;
	m_last_time = os::clocktime();
}

//-----------------------------------------------------------------------------
void Device::stop()
{
	CE_ASSERT(m_is_init, "Cannot stop uninitialized engine.");

	m_is_running = false;
}

//-----------------------------------------------------------------------------
void Device::pause()
{
	m_is_paused = true;
	CE_LOGI("Engine paused.");
}

//-----------------------------------------------------------------------------
void Device::unpause()
{
	m_is_paused = false;
	CE_LOGI("Engine unpaused.");
}

//-----------------------------------------------------------------------------
bool Device::is_running() const
{
	return m_is_running;
}

//-----------------------------------------------------------------------------
uint64_t Device::frame_count() const
{
	return m_frame_count;
}

//-----------------------------------------------------------------------------
float Device::last_delta_time() const
{
	return m_last_delta_time;
}

//-----------------------------------------------------------------------------
double Device::time_since_start() const
{
	return m_time_since_start;
}

//-----------------------------------------------------------------------------
void Device::frame()
{
	m_current_time = os::clocktime();
	const int64_t time = m_current_time - m_last_time;
	m_last_time = m_current_time;
	const double freq = (double) os::clockfrequency();
	m_last_delta_time = time * (1.0 / freq);
	m_time_since_start += m_last_delta_time;

	if (!m_is_paused)
	{
		m_resource_manager->complete_requests();
		m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time());
	}

	lua_system::clear_temporaries();
	m_frame_count++;
}

//-----------------------------------------------------------------------------
void Device::update_world(World* world, float dt)
{
	world->update(dt);
}

//-----------------------------------------------------------------------------
void Device::render_world(World* world, Camera* camera)
{
	world->render(camera);
}

//-----------------------------------------------------------------------------
WorldId Device::create_world()
{
	return m_world_manager->create_world();
}

//-----------------------------------------------------------------------------
void Device::destroy_world(WorldId world)
{
	m_world_manager->destroy_world(world);
}

//-----------------------------------------------------------------------------
ResourcePackage* Device::create_resource_package(const char* name)
{
	return CE_NEW(default_allocator(), ResourcePackage)(name, *m_resource_manager);
}

//-----------------------------------------------------------------------------
void Device::destroy_resource_package(ResourcePackage* package)
{
	CE_DELETE(default_allocator(), package);
}

//-----------------------------------------------------------------------------
void Device::reload(const char* , const char* )
{
/*
	#if defined(LINUX) || defined(WINDOWS)
		TempAllocator4096 temp;
		DynamicString filename(temp);
		filename += name;
		filename += '.';
		filename += type;

		if (!m_bundle_compiler->compile(m_bundle_dir, m_source_dir, filename.c_str()))
		{
			CE_LOGD("Compilation failed.");
			return;
		}

		ResourceId old_res_id(type, name);
		const void* old_res = m_resource_manager->get(old_res_id);
		m_resource_manager->unload(old_res_id, true);

		ResourceId res_id = m_resource_manager->load(type, name);
		m_resource_manager->flush();
		const void* new_res = m_resource_manager->get(res_id);

		uint32_t type_hash = string::murmur2_32(type, string::strlen(type), 0);

		switch (type_hash)
		{
			case UNIT_TYPE:
			{
				CE_LOGD("Reloading unit: %s", name);
				/// Reload unit in all worlds
				for (uint32_t i = 0; i < id_array::size(m_world_manager->worlds()); i++)
				{
					m_world_manager->worlds()[i]->reload_units((UnitResource*) old_res, (UnitResource*) new_res);
				}
				break;
			}
			case SOUND_TYPE:
			{
				CE_LOGD("Reloading sound: %s", name);
				for (uint32_t i = 0; i < id_array::size(m_world_manager->worlds()); i++)
				{
					m_world_manager->worlds()[i]->sound_world()->reload_sounds((SoundResource*) old_res, (SoundResource*) new_res);
				}
				break;
			}
			default:
			{
				CE_ASSERT(false, "Oops, unknown resource type: %s", type);
				break;
			}
		}
	#endif
*/
}

static Device* g_device;
void set_device(Device* device)
{
	g_device = device;
}

Device* device()
{
	return g_device;
}

} // namespace crown
<commit_msg>Remove log<commit_after>
/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
OTHER DEALINGS IN THE SOFTWARE.
*/

#include <cstdlib>

#include "config.h"
#include "device.h"
#include "args.h"
#include "disk_file.h"
#include "disk_filesystem.h"
#include "json_parser.h"
#include "keyboard.h"
#include "log.h"
#include "lua_environment.h"
#include "memory.h"
#include "mouse.h"
#include "os.h"
#include "os_window.h"
#include "resource_manager.h"
#include "string_setting.h"
#include "string_utils.h"
#include "touch.h"
#include "types.h"
#include "bundle.h"
#include "temp_allocator.h"
#include "resource_package.h"
#include "console_server.h"
#include "world.h"
#include "lua_stack.h"
#include "world_manager.h"
#include "network_filesystem.h"
#include "lua_system.h"
#include "debug_line.h"
#include "material_manager.h"
#include "gui.h"

#if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
	#include "bundle_compiler.h"
#endif

#if CROWN_PLATFORM_ANDROID
	#include "apk_filesystem.h"
#endif

#define MAX_SUBSYSTEMS_HEAP 8 * 1024 * 1024

namespace crown
{
//-----------------------------------------------------------------------------
Device::Device()
	: m_allocator(default_allocator(), MAX_SUBSYSTEMS_HEAP)

	, m_argc(0)
	, m_argv(NULL)

	, m_fileserver(0)
	, m_console_port(10001)

	, m_is_init(false)
	, m_is_running(false)
	, m_is_paused(false)

	, m_frame_count(0)

	, m_last_time(0)
	, m_current_time(0)
	, m_last_delta_time(0.0f)
	, m_time_since_start(0.0)

	, m_filesystem(NULL)
	, m_lua_environment(NULL)
	, m_renderer(NULL)

	, m_bundle_compiler(NULL)
	, m_console(NULL)
	, m_resource_manager(NULL)
	, m_resource_bundle(NULL)

	, m_world_manager(NULL)
{
	// Bundle dir is current dir by default.
	os::getcwd(m_bundle_dir, MAX_PATH_LENGTH);
	string::strncpy(m_source_dir, "", MAX_PATH_LENGTH);
	string::strncpy(m_boot_file, "lua/game", MAX_PATH_LENGTH);
}

//-----------------------------------------------------------------------------
Device::~Device()
{
}

//-----------------------------------------------------------------------------
void Device::init()
{
	// Initialize
	CE_LOGI("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);

	CE_LOGD("Creating filesystem...");
	// Default bundle filesystem
	#if CROWN_PLATFORM_LINUX || CROWN_PLATFORM_WINDOWS
		if (m_fileserver == 1)
		{
			m_filesystem = CE_NEW(m_allocator, NetworkFilesystem)(NetAddress(127, 0, 0, 1), 10001);
		}
		else
		{
			m_filesystem = CE_NEW(m_allocator, DiskFilesystem)(m_bundle_dir);
		}
	#elif CROWN_PLATFORM_ANDROID
		if (m_fileserver == 1)
		{
			m_filesystem = CE_NEW(m_allocator, NetworkFilesystem)(NetAddress(192, 168, 0, 7), 10001);
		}
		else
		{
			m_filesystem = CE_NEW(m_allocator, ApkFilesystem)();
		}
	#endif

	m_resource_bundle = Bundle::create(m_allocator, *m_filesystem);

	// Create resource manager
	CE_LOGD("Creating resource manager...");
	m_resource_manager = CE_NEW(m_allocator, ResourceManager)(*m_resource_bundle);

	// Create world manager
	CE_LOGD("Creating world manager...");
	m_world_manager = CE_NEW(m_allocator, WorldManager)();

	// Create window
	CE_LOGD("Creating main window...");
	m_window = CE_NEW(m_allocator, OsWindow);

	// Create input devices
	m_keyboard = CE_NEW(m_allocator, Keyboard);
	m_mouse = CE_NEW(m_allocator, Mouse);
	m_touch = CE_NEW(m_allocator, Touch);

	// Create renderer
	CE_LOGD("Creating renderer...");
	graphics_system::init();
	debug_line::init();
	Gui::init();

	CE_LOGD("Creating material manager...");
	material_manager::init();

	CE_LOGD("Creating lua system...");
	lua_system::init();
	m_lua_environment = CE_NEW(m_allocator, LuaEnvironment)(lua_system::state());

	CE_LOGD("Creating physics...");
	physics_system::init();

	CE_LOGD("Creating audio...");
	audio_system::init();

	CE_LOGD("Crown Engine initialized.");
	CE_LOGD("Initializing Game...");

	m_is_init = true;
	start();

	// Execute lua boot file
	m_lua_environment->load_and_execute(m_boot_file);
	m_lua_environment->call_global("init", 0);
}

//-----------------------------------------------------------------------------
void Device::shutdown()
{
	CE_ASSERT(is_init(), "Engine is not initialized");

	// Shutdowns the game
	m_lua_environment->call_global("shutdown", 0);

	CE_LOGD("Releasing audio...");
	audio_system::shutdown();

	CE_LOGD("Releasing physics...");
	physics_system::shutdown();

	CE_LOGD("Releasing lua system...");
	lua_system::shutdown();
	if (m_lua_environment)
	{
		CE_DELETE(m_allocator, m_lua_environment);
	}

	CE_LOGD("Releasing input devices...");
	CE_DELETE(m_allocator, m_touch);
	CE_DELETE(m_allocator, m_mouse);
	CE_DELETE(m_allocator, m_keyboard);

	CE_LOGD("Releasing material manager...");
	material_manager::shutdown();

	CE_LOGD("Releasing renderer...");
	debug_line::shutdown();
	graphics_system::shutdown();

	CE_LOGD("Releasing world manager...");
	CE_DELETE(m_allocator, m_world_manager);

	CE_LOGD("Releasing resource manager...");
	if (m_resource_manager)
	{
		CE_DELETE(m_allocator, m_resource_manager);
	}

	if (m_resource_bundle)
	{
		Bundle::destroy(m_allocator, m_resource_bundle);
	}

	CE_LOGD("Releasing filesystem...");
	if (m_filesystem)
	{
		CE_DELETE(m_allocator, m_filesystem);
	}

	m_allocator.clear();
	m_is_init = false;
}

//-----------------------------------------------------------------------------
bool Device::is_init() const
{
	return m_is_init;
}

//-----------------------------------------------------------------------------
bool Device::is_paused() const
{
	return m_is_paused;
}

//-----------------------------------------------------------------------------
Filesystem* Device::filesystem()
{
	return m_filesystem;
}

//-----------------------------------------------------------------------------
ResourceManager* Device::resource_manager()
{
	return m_resource_manager;
}

//-----------------------------------------------------------------------------
LuaEnvironment* Device::lua_environment()
{
	return m_lua_environment;
}

//-----------------------------------------------------------------------------
OsWindow* Device::window()
{
	return m_window;
}

//-----------------------------------------------------------------------------
Renderer* Device::renderer()
{
	return NULL;
}

//-----------------------------------------------------------------------------
Keyboard* Device::keyboard()
{
	return m_keyboard;
}

//-----------------------------------------------------------------------------
Mouse* Device::mouse()
{
	return m_mouse;
}

//-----------------------------------------------------------------------------
Touch* Device::touch()
{
	return m_touch;
}

//-----------------------------------------------------------------------------
Accelerometer* Device::accelerometer()
{
	return NULL;
}

//-----------------------------------------------------------------------------
void Device::start()
{
	CE_ASSERT(m_is_init, "Cannot start uninitialized engine.");

	m_is_running = true;
	m_last_time = os::clocktime();
}

//-----------------------------------------------------------------------------
void Device::stop()
{
	CE_ASSERT(m_is_init, "Cannot stop uninitialized engine.");

	m_is_running = false;
}

//-----------------------------------------------------------------------------
void Device::pause()
{
	m_is_paused = true;
	CE_LOGI("Engine paused.");
}

//-----------------------------------------------------------------------------
void Device::unpause()
{
	m_is_paused = false;
	CE_LOGI("Engine unpaused.");
}

//-----------------------------------------------------------------------------
bool Device::is_running() const
{
	return m_is_running;
}

//-----------------------------------------------------------------------------
uint64_t Device::frame_count() const
{
	return m_frame_count;
}

//-----------------------------------------------------------------------------
float Device::last_delta_time() const
{
	return m_last_delta_time;
}

//-----------------------------------------------------------------------------
double Device::time_since_start() const
{
	return m_time_since_start;
}

//-----------------------------------------------------------------------------
void Device::frame()
{
	m_current_time = os::clocktime();
	const int64_t time = m_current_time - m_last_time;
	m_last_time = m_current_time;
	const double freq = (double) os::clockfrequency();
	m_last_delta_time = time * (1.0 / freq);
	m_time_since_start += m_last_delta_time;

	if (!m_is_paused)
	{
		m_resource_manager->complete_requests();
		m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time());
	}

	lua_system::clear_temporaries();
	m_frame_count++;
}

//-----------------------------------------------------------------------------
void Device::update_world(World* world, float dt)
{
	world->update(dt);
}

//-----------------------------------------------------------------------------
void Device::render_world(World* world, Camera* camera)
{
	world->render(camera);
}

//-----------------------------------------------------------------------------
WorldId Device::create_world()
{
	return m_world_manager->create_world();
}

//-----------------------------------------------------------------------------
void Device::destroy_world(WorldId world)
{
	m_world_manager->destroy_world(world);
}

//-----------------------------------------------------------------------------
ResourcePackage* Device::create_resource_package(const char* name)
{
	return CE_NEW(default_allocator(), ResourcePackage)(name, *m_resource_manager);
}

//-----------------------------------------------------------------------------
void Device::destroy_resource_package(ResourcePackage* package)
{
	CE_DELETE(default_allocator(), package);
}

//-----------------------------------------------------------------------------
void Device::reload(const char* , const char* )
{
/*
	#if defined(LINUX) || defined(WINDOWS)
		TempAllocator4096 temp;
		DynamicString filename(temp);
		filename += name;
		filename += '.';
		filename += type;

		if (!m_bundle_compiler->compile(m_bundle_dir, m_source_dir, filename.c_str()))
		{
			CE_LOGD("Compilation failed.");
			return;
		}

		ResourceId old_res_id(type, name);
		const void* old_res = m_resource_manager->get(old_res_id);
		m_resource_manager->unload(old_res_id, true);

		ResourceId res_id = m_resource_manager->load(type, name);
		m_resource_manager->flush();
		const void* new_res = m_resource_manager->get(res_id);

		uint32_t type_hash = string::murmur2_32(type, string::strlen(type), 0);

		switch (type_hash)
		{
			case UNIT_TYPE:
			{
				CE_LOGD("Reloading unit: %s", name);
				/// Reload unit in all worlds
				for (uint32_t i = 0; i < id_array::size(m_world_manager->worlds()); i++)
				{
					m_world_manager->worlds()[i]->reload_units((UnitResource*) old_res, (UnitResource*) new_res);
				}
				break;
			}
			case SOUND_TYPE:
			{
				CE_LOGD("Reloading sound: %s", name);
				for (uint32_t i = 0; i < id_array::size(m_world_manager->worlds()); i++)
				{
					m_world_manager->worlds()[i]->sound_world()->reload_sounds((SoundResource*) old_res, (SoundResource*) new_res);
				}
				break;
			}
			default:
			{
				CE_ASSERT(false, "Oops, unknown resource type: %s", type);
				break;
			}
		}
	#endif
*/
}

static Device* g_device;
void set_device(Device* device)
{
	g_device = device;
}

Device* device()
{
	return g_device;
}

} // namespace crown
<|endoftext|>


<commit_before>#define DEBUG
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

//for connection to server
#include "../sockets/SocketW.h"
bool ready4data = false;//set to true when streaming starts
bool inited = false;
bool stopparsing = false;
timeval lastrec;

FILE * CONN = 0;
#include "parsechunks.cpp" //chunkstream parsing
#include "handshake.cpp" //handshaking
#include "../util/flv_sock.cpp" //FLV parsing with SocketW
#include "../util/ddv_socket.cpp" //DDVTech Socket wrapper

int main(){

  int server_socket = DDV_Listen(1935);
  int status;
  while (server_socket > 0){
    waitpid((pid_t)-1, &status, WNOHANG);
    CONN = DDV_Accept(server_socket);
    pid_t myid = fork();
    if (myid == 0){
      break;
    }else{
      printf("Spawned new process %i for incoming client\n", (int)myid);
    }
  }
  if (server_socket <= 0){
    return 0;
  }

  unsigned int ts;
  unsigned int fts = 0;
  unsigned int ftst;
  SWUnixSocket ss;

  //first timestamp set
  firsttime = getNowMS();

  #ifdef DEBUG
  fprintf(stderr, "Doing handshake...\n");
  #endif
  if (doHandshake()){
    #ifdef DEBUG
    fprintf(stderr, "Handshake succcess!\n");
    #endif
  }else{
    #ifdef DEBUG
    fprintf(stderr, "Handshake fail!\n");
    #endif
    return 0;
  }
  #ifdef DEBUG
  fprintf(stderr, "Starting processing...\n");
  #endif
  while (!ferror(CONN)){
    //only parse input if available or not yet init'ed
    //rightnow = getNowMS();
    if ((!ready4data || (snd_cnt - snd_window_at >= snd_window_size)) && !stopparsing){
      parseChunk();
      fflush(CONN);
    }
    if (ready4data){
      if (!inited){
        //we are ready, connect the socket!
        if (!ss.connect(streamname.c_str())){
          #ifdef DEBUG
          fprintf(stderr, "Could not connect to server!\n");
          #endif
          return 0;
        }
        FLV_Readheader(ss);//read the header, we don't want it
        #ifdef DEBUG
        fprintf(stderr, "Header read, starting to send video data...\n");
        #endif
        inited = true;
      }
      //only send data if previous data has been ACK'ed...
      if (snd_cnt - snd_window_at < snd_window_size){
        if (FLV_GetPacket(ss)){//able to read a full packet?
          ts = FLVbuffer[7] * 256*256*256;
          ts += FLVbuffer[4] * 256*256;
          ts += FLVbuffer[5] * 256;
          ts += FLVbuffer[6];
          if (ts != 0){
            if (fts == 0){fts = ts;ftst = getNowMS();}
            ts -= fts;
            FLVbuffer[7] = ts / (256*256*256);
            FLVbuffer[4] = ts / (256*256);
            FLVbuffer[5] = ts / 256;
            FLVbuffer[6] = ts % 256;
            ts += ftst;
          }else{
            ftst = getNowMS();
            FLVbuffer[7] = ftst / (256*256*256);
            FLVbuffer[4] = ftst / (256*256);
            FLVbuffer[5] = ftst / 256;
            FLVbuffer[6] = ftst % 256;
          }
          SendMedia((unsigned char)FLVbuffer[0], (unsigned char *)FLVbuffer+11, FLV_len-15, ts);
          FLV_Dump();//dump packet and get ready for next
        }
        if ((SWBerr != SWBaseSocket::ok) && (SWBerr != SWBaseSocket::notReady)){
          #ifdef DEBUG
          fprintf(stderr, "No more data! :-(  (%s)\n", SWBerr.get_error().c_str());
          #endif
          return 0;//no more input possible! Fail immediately.
        }
      }
    }
    //send ACK if we received a whole window
    if (rec_cnt - rec_window_at > rec_window_size){
      rec_window_at = rec_cnt;
      SendCTL(3, rec_cnt);//send ack (msg 3)
    }
  }
  #ifdef DEBUG
  fprintf(stderr, "User disconnected.\n");
  #endif
  return 0;
}//main
<commit_msg>Nog een poging...<commit_after>#define DEBUG
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/epoll.h>

//for connection to server
#include "../sockets/SocketW.h"
bool ready4data = false;//set to true when streaming starts
bool inited = false;
bool stopparsing = false;
timeval lastrec;

FILE * CONN = 0;
#include "parsechunks.cpp" //chunkstream parsing
#include "handshake.cpp" //handshaking
#include "../util/flv_sock.cpp" //FLV parsing with SocketW
#include "../util/ddv_socket.cpp" //DDVTech Socket wrapper

int main(){

  int server_socket = DDV_Listen(1935);
  int status;
  while (server_socket > 0){
    waitpid((pid_t)-1, &status, WNOHANG);
    CONN = DDV_Accept(server_socket);
    pid_t myid = fork();
    if (myid == 0){
      break;
    }else{
      printf("Spawned new process %i for incoming client\n", (int)myid);
    }
  }
  if (server_socket <= 0){
    return 0;
  }

  unsigned int ts;
  unsigned int fts = 0;
  unsigned int ftst;
  SWUnixSocket ss;

  //first timestamp set
  firsttime = getNowMS();

  #ifdef DEBUG
  fprintf(stderr, "Doing handshake...\n");
  #endif
  if (doHandshake()){
    #ifdef DEBUG
    fprintf(stderr, "Handshake succcess!\n");
    #endif
  }else{
    #ifdef DEBUG
    fprintf(stderr, "Handshake fail!\n");
    #endif
    return 0;
  }
  #ifdef DEBUG
  fprintf(stderr, "Starting processing...\n");
  #endif

  int retval;
  int poller = epoll_create(1);
  struct epoll_event ev;
  ev.events = EPOLLIN | EPOLLOUT;
  ev.data.fd = fileno(CONN);
  epoll_ctl(poller, EPOLL_CTL_ADD, fileno(CONN), &ev);
  struct epoll_event events[1];

  while (!ferror(CONN)){
    //only parse input if available or not yet init'ed
    //rightnow = getNowMS();
    retval = epoll_wait(poller, events, 1, 1000);
    if (retval){
      fprintf(stderr, "Socket %i is now state %i, in is %i, out is %i\n", events[0].data.fd, events[0].events, EPOLLIN, EPOLLOUT);
      parseChunk();
      fflush(CONN);
    }
    if (ready4data){
      if (!inited){
        //we are ready, connect the socket!
        if (!ss.connect(streamname.c_str())){
          #ifdef DEBUG
          fprintf(stderr, "Could not connect to server!\n");
          #endif
          return 0;
        }
        FLV_Readheader(ss);//read the header, we don't want it
        #ifdef DEBUG
        fprintf(stderr, "Header read, starting to send video data...\n");
        #endif
        inited = true;
      }
      //only send data if previous data has been ACK'ed...
      if (snd_cnt - snd_window_at < snd_window_size){
        if (FLV_GetPacket(ss)){//able to read a full packet?
          ts = FLVbuffer[7] * 256*256*256;
          ts += FLVbuffer[4] * 256*256;
          ts += FLVbuffer[5] * 256;
          ts += FLVbuffer[6];
          if (ts != 0){
            if (fts == 0){fts = ts;ftst = getNowMS();}
            ts -= fts;
            FLVbuffer[7] = ts / (256*256*256);
            FLVbuffer[4] = ts / (256*256);
            FLVbuffer[5] = ts / 256;
            FLVbuffer[6] = ts % 256;
            ts += ftst;
          }else{
            ftst = getNowMS();
            FLVbuffer[7] = ftst / (256*256*256);
            FLVbuffer[4] = ftst / (256*256);
            FLVbuffer[5] = ftst / 256;
            FLVbuffer[6] = ftst % 256;
          }
          SendMedia((unsigned char)FLVbuffer[0], (unsigned char *)FLVbuffer+11, FLV_len-15, ts);
          FLV_Dump();//dump packet and get ready for next
        }
        if ((SWBerr != SWBaseSocket::ok) && (SWBerr != SWBaseSocket::notReady)){
          #ifdef DEBUG
          fprintf(stderr, "No more data! :-(  (%s)\n", SWBerr.get_error().c_str());
          #endif
          return 0;//no more input possible! Fail immediately.
        }
      }
    }
    //send ACK if we received a whole window
    if (rec_cnt - rec_window_at > rec_window_size){
      rec_window_at = rec_cnt;
      SendCTL(3, rec_cnt);//send ack (msg 3)
    }
  }
  #ifdef DEBUG
  fprintf(stderr, "User disconnected.\n");
  #endif
  return 0;
}//main
<|endoftext|>


<commit_before>#include "SmartRail.h"

#include <SerialDebug.h>
#include <VoltageReference.h>
#include <AccelStepper.h>
#include <LiquidCrystal.h>

#define STEP_1_PIN 6
#define STEP_2_PIN 5
#define STEP_3_PIN 4
#define STEP_4_PIN 3

#define X_AXIS_PIN A6
#define Y_AXIS_PIN A7
#define BUTTON_PIN 2

AccelStepper stepper = AccelStepper(AccelStepper::FULL4WIRE, STEP_1_PIN, STEP_3_PIN, STEP_2_PIN, STEP_4_PIN);
VoltageReference vRef = VoltageReference();
LiquidCrystal lcd = LiquidCrystal(12, 11, 10, 9, 8, 7);

uint8_t index = 0;
char* command;
bool commandComplete = false;
float acceleration = 100.0;

void setup() {
	Serial.begin(9600);
	pinMode(X_AXIS_PIN, INPUT);
	pinMode(Y_AXIS_PIN, INPUT);
	pinMode(BUTTON_PIN, INPUT);
	lcd.begin(16, 2);
	lcd.print("ciao mamma");
	stepper.setMaxSpeed(2000.0);
	stepper.setSpeed(500.0);
	stepper.setAcceleration(100.0);
}

void serialEvent() {
	while (Serial.available() && commandComplete == false) {
		char inChar = Serial.read();
		command[index++] = inChar;
		if (inChar == '\n') {
			index = 0;
			commandComplete = true;
		}
	}
}

void manual() {
	int16_t x = analogRead(X_AXIS_PIN) - 512;
	stepper.setSpeed(abs(x));
	if (x > 0)
		stepper.move(1);
	if (x < 0)
		stepper.move(-1);
	if (x != 0)
		DEBUG("speed", stepper.speed());

	int16_t y = analogRead(Y_AXIS_PIN) - 512;
	if (y > 0)
		stepper.setAcceleration(acceleration + 10.0);
	if (y < 0)
		stepper.setAcceleration(acceleration - 10.0);
	if (y != 0)
		DEBUG("acceleration", acceleration);
}

void stepperDemo() {
	stepper.runToNewPosition(2000);
	delay(1000);
	stepper.runToNewPosition(-2000);
	delay(1000);
	stepper.setSpeed(500);
	stepper.moveTo(2000);
	stepper.runSpeedToPosition();
	delay(1000);
	stepper.moveTo(-2000);
	stepper.runSpeedToPosition();
	delay(1000);
}

void loop() {
	lcd.setCursor(0, 1);
	// print the number of seconds since reset:
	lcd.print(millis() / 1000);
}

<commit_msg>implemented manual mode, constant speed and smoothed stepper demo<commit_after>#include "SmartRail.h"

#include <SerialDebug.h>
#include <VoltageReference.h>
#include <AccelStepper.h>
#include <LiquidCrystal.h>
#include <Flash.h>

#define STEP_1_PIN 6
#define STEP_2_PIN 5
#define STEP_3_PIN 4
#define STEP_4_PIN 3

#define X_AXIS_PIN A6
#define Y_AXIS_PIN A7
#define BUTTON_PIN 2

AccelStepper stepper = AccelStepper(AccelStepper::FULL4WIRE, STEP_1_PIN, STEP_3_PIN, STEP_2_PIN, STEP_4_PIN);
VoltageReference vRef = VoltageReference();
LiquidCrystal lcd = LiquidCrystal(12, 11, 10, 9, 8, 7);

#include "i18n/messages.h"
#include "i18n/messages_it.h"

uint8_t index = 0;
char* command;
bool commandComplete = false;
float acceleration = 100.0;
uint16_t xCalibrate, yCalibrate;

#define FUNCTIONS_SIZE 2
volatile uint8_t functionIndex = 0;
volatile bool clicked = true;

inline void welcome() {
	display(welcome_1, 0, LEFT);
	display(welcome_2, 1, RIGHT);
	for (int i = 0; i < 3; i++) {
		delay(300);
		lcd.noDisplay();
		delay(200);
		lcd.display();
	}
}

void calibrateJoystick() {
	delay(50);
	xCalibrate = analogRead(X_AXIS_PIN);
	delay(50);
	yCalibrate = analogRead(Y_AXIS_PIN);
}

void click() {
	functionIndex = (functionIndex + 1) % FUNCTIONS_SIZE;
	clicked = true;
}

void setup() {
	Serial.begin(9600);
	pinMode(X_AXIS_PIN, INPUT);
	pinMode(Y_AXIS_PIN, INPUT);
	pinMode(BUTTON_PIN, INPUT);
	stepper.setMaxSpeed(2000.0);
	stepper.setSpeed(500.0);
	stepper.setAcceleration(100.0);
	lcd.begin(16, 2);
	welcome();
	calibrateJoystick();
	attachInterrupt(0, click, CHANGE);
}

void serialEvent() {
	while (Serial.available() && commandComplete == false) {
		char inChar = Serial.read();
		command[index++] = inChar;
		if (inChar == '\n') {
			index = 0;
			commandComplete = true;
		}
	}
}

void manual() {
	if (clicked) {
		lcd.clear();
		display(manual_mode, 0);
	}
	int16_t x = analogRead(X_AXIS_PIN) - xCalibrate;
	if (x > 50) {
		//DEBUG("LEFT");
		stepper.move(10);
		stepper.setMaxSpeed(1000);
		stepper.setSpeed(abs(x));
	} else if (x < -50) {
		//DEBUG("RIGHT");
		stepper.move(-10);
		stepper.setMaxSpeed(1000);
		stepper.setSpeed(abs(x));
	}

	int16_t y = analogRead(Y_AXIS_PIN) - yCalibrate;
	if (y > 20) {
		acceleration += 10.0;
		stepper.setAcceleration(acceleration);
	} else if (y < -20) {
		acceleration -= 10.0;
		stepper.setAcceleration(acceleration);
	}
	stepper.runSpeedToPosition();
}

void stepperDemo() {
	display(demo_mode, 0);
	display(const_speed_mode, 1);
	stepper.moveTo(4000);
	stepper.setMaxSpeed(500);
	stepper.setSpeed(500);
	DEBUG("cw 1");
	while(stepper.distanceToGo() != 0)
		stepper.runSpeedToPosition();
	delay(1000);

	stepper.moveTo(0);
	stepper.setMaxSpeed(500);
	stepper.setSpeed(500);
	DEBUG("ccw 1");
	while(stepper.distanceToGo() != 0)
		stepper.runSpeedToPosition();
	delay(1000);

	display(smooth_mode, 1);
	stepper.setMaxSpeed(1000);
	stepper.setAcceleration(100.0);
	stepper.setCurrentPosition(0);

	DEBUG("cw 2");
	stepper.runToNewPosition(4000);
	delay(1000);

	DEBUG("ccw 2");
	stepper.runToNewPosition(0);
	delay(1000);
}

void (*functions[])() = {manual, stepperDemo};
void loop() {
	functions[functionIndex]();
	clicked = false;
}

<|endoftext|>


<commit_before>/*
 *      Author: Michael Camilleri
 *
 * Copyright (c) 2016, University Of Edinburgh
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of  nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "exotica/Initialiser.h"

using namespace rapidjson;

namespace exotica
{
  Initialiser_ptr Initialiser::singleton_initialiser_ = NULL;

  void Initialiser::printSupportedClasses()
  {
      HIGHLIGHT("Registered solvers:");
      std::vector<std::string> solvers =  Instance()->solvers_.getDeclaredClasses();
      for(std::string s : solvers)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
      HIGHLIGHT("Registered problems:");
      std::vector<std::string> problems =  Instance()->problems_.getDeclaredClasses();
      for(std::string s : problems)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
      HIGHLIGHT("Registered task definitions:");
      std::vector<std::string> definitions =  Instance()->definitions_.getDeclaredClasses();
      for(std::string s : definitions)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
      HIGHLIGHT("Registered task maps:");
      std::vector<std::string> maps =  Instance()->maps_.getDeclaredClasses();
      for(std::string s : maps)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
  }

  Initialiser::Initialiser() : solvers_("exotica","exotica::MotionSolver"), maps_("exotica","exotica::TaskMap"),
    definitions_("exotica","exotica::TaskDefinition"), problems_("exotica","exotica::PlanningProblem")
  {

  }

  void Initialiser::initialise(const std::string & file_name,
      Server_ptr & server, MotionSolver_ptr & solver,
      PlanningProblem_ptr & problem)
  {
    std::vector<std::string> probs, sols;
    Initialiser::listSolversAndProblems(file_name, probs, sols);
    if (probs.size() > 0 && sols.size() > 0)
    {
        return initialise(file_name, server, solver, problem, probs[0], sols[0]);
    }
    else
    {
        throw_named("No problems or solvers found!");
    }
  }

  void Initialiser::initialiseProblemJSON(PlanningProblem_ptr problem,
      const std::string& constraints)
  {
    {
      Document document;
      if (!document.Parse<0>(constraints.c_str()).HasParseError())
      {
        problem->reinitialise(document, problem);
      }
      else
      {
        throw_named("Can't parse constraints from JSON string!\n"<<document.GetParseError() <<"\n"<<constraints.substr(document.GetErrorOffset(),50));
      }
    }
  }

  void Initialiser::listSolversAndProblems(const std::string & file_name,
      std::vector<std::string>& problems, std::vector<std::string>& solvers)
  {
    xml_file.Clear();
    if (xml_file.LoadFile(file_name.c_str()) != tinyxml2::XML_NO_ERROR)
    {
      xml_file.Clear();
      throw_named("Can't load file!");
    }
    tinyxml2::XMLHandle root_handle(xml_file.RootElement());

    //!< First resolve any includes that exist
    std::string file_path = file_name;
    try
    {
        resolveParent(file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't resolve parent!");
    }
    file_path += "/";
    try
    {
        parseIncludes(root_handle, file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't parse includes!");
    }

    std::vector<std::string> registered_problems;
    PlanningProblem_fac::Instance().listImplementations(registered_problems);
    tinyxml2::XMLHandle problem_handle(root_handle.FirstChildElement());
    problems.clear();
    while (problem_handle.ToElement())
    {
      const char* atr = problem_handle.ToElement()->Attribute("name");
      const char* tp = problem_handle.ToElement()->Name();
      if (atr)
      {
        bool found = false;
        for (std::string& name : registered_problems)
        {
          if (std::string(tp).compare(name) == 0)
          {
            found = true;
            problems.push_back(std::string(atr));
            break;
          }
        }
        if (!found)
        {
          ERROR("Problem '"<<atr<<"' has unrecognized type '"<<tp<<"'");
        }
        problem_handle = problem_handle.NextSibling();
      }
      else
      {
        problem_handle = problem_handle.NextSibling();
        ERROR("Element name was not specified!");
        continue;
      }
    }

    std::vector<std::string> registered_solvers;
    MotionSolver_fac::Instance().listImplementations(registered_solvers);
    tinyxml2::XMLHandle solver_handle(root_handle.FirstChildElement());
    solvers.clear();
    while (solver_handle.ToElement())
    {
      const char* atr = solver_handle.ToElement()->Attribute("name");
      const char* tp = solver_handle.ToElement()->Name();
      if (atr)
      {
        bool found = false;
        for (std::string& name : registered_solvers)
        {
          if (std::string(tp).compare(name) == 0)
          {
            found = true;
            solvers.push_back(std::string(atr));
            break;
          }
        }
        if (!found)
        {
          ERROR("Solver '"<<atr<<"' has unrecognized type '"<<tp<<"'");
        }
        solver_handle = solver_handle.NextSibling();
      }
      else
      {
        solver_handle = solver_handle.NextSibling();
        ERROR("Element name was not specified!");
        continue;
      }
    }
  }

  void Initialiser::initialise(tinyxml2::XMLHandle root_handle,
      Server_ptr & server)
  {
    server = Server::Instance();
    tinyxml2::XMLHandle server_handle(root_handle.FirstChildElement("Server"));
    if (server_handle.ToElement())
    {
      server->initialise(server_handle);
    }
    else
    {
      throw_named("EXOTica Server element is missing in the xml");
    }
  }

  void Initialiser::initialise(tinyxml2::XMLHandle root_handle,
      PlanningProblem_ptr & problem, const std::string & problem_name,
      Server_ptr & server)
  {
    tinyxml2::XMLHandle problem_handle(root_handle.FirstChildElement());
    while (problem_handle.ToElement())
    {
      const char* atr = problem_handle.ToElement()->Attribute("name");
      if (atr)
      {
        if (std::string(atr).compare(problem_name) == 0)
        {

            PlanningProblem_fac::Instance().createObject(problem,problem_handle, server);
            return;
        }
        else
        {
          problem_handle = problem_handle.NextSibling();
          continue;
        }
      }
      else
      {
        problem_handle = problem_handle.NextSibling();
        ERROR("Element name was not specified!");
        continue;
      }
    }

    throw_named("File does not contain the '"<<problem_name<<"' problem definition.");
  }

  void Initialiser::initialise(tinyxml2::XMLHandle root_handle,
      MotionSolver_ptr & solver, const std::string & solver_name,
      Server_ptr & server)
  {
    tinyxml2::XMLHandle solver_handle(root_handle.FirstChildElement());
    while (solver_handle.ToElement())
    {
      if (!solver_name.empty())
      {
        const char* atr = solver_handle.ToElement()->Attribute("name");
        if (atr)
        {
          if (std::string(atr).compare(solver_name) == 0)
          {
            MotionSolver_fac::Instance().createObject(solver, solver_handle,server);
            return;
          }
          else
          {
            solver_handle = solver_handle.NextSibling();
            continue;
          }

        }
        else
        {
          solver_handle = solver_handle.NextSibling();
          ERROR("Element name was not specified!");
          continue;
        }
      }
      else
      {
        throw_named("Empty solver name");
      }
    }

    throw_named("File does not contain the '"<<solver_name<<"' solver.");
  }

  void Initialiser::initialise(const std::string & file_name,
      Server_ptr & server, MotionSolver_ptr & solver,
      PlanningProblem_ptr & problem, const std::string & problem_name,
      const std::string & solver_name)
  {
    // /////////////////////////
    // Create the document
    xml_file.Clear();
    if (xml_file.LoadFile(file_name.c_str()) != tinyxml2::XML_NO_ERROR)
    {
      xml_file.Clear();
      throw_named("Can't load XML!");
    }
    tinyxml2::XMLHandle root_handle(xml_file.RootElement());

    // /////////////////////////
    // First resolve any includes that exist
    std::string file_path = file_name;
    try
    {
        resolveParent(file_path);
    }
    catch(Exception e)
    {
      xml_file.Clear();
      throw_named("Can't resolve parent!");
    }
    file_path += "/";
    try
    {
        parseIncludes(root_handle, file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't parse includes!");
    }

    // /////////////////////////
    // Initialise server
    initialise(root_handle, server);

    // /////////////////////////
    // Initialise problem
    initialise(root_handle, problem, problem_name, server);

    // /////////////////////////
    // Initialise solver
    initialise(root_handle, solver, solver_name, server);
  }

  void Initialiser::initialise(const std::string & file_name,
      Server_ptr & server, std::vector<MotionSolver_ptr> & solver,
      std::vector<PlanningProblem_ptr> & problem,
      std::vector<std::string> & problem_name,
      std::vector<std::string> & solver_name)
  {
    // /////////////////////////
    // Create the document
    xml_file.Clear();
    if (xml_file.LoadFile(file_name.c_str()) != tinyxml2::XML_NO_ERROR)
    {
      xml_file.Clear();
      throw_named("Can't load XML!");
    }
    tinyxml2::XMLHandle root_handle(xml_file.RootElement());

    // /////////////////////////
    // First resolve any includes that exist
    std::string file_path = file_name;
    try
    {
        resolveParent(file_path);
    }
    catch(Exception e)
    {
      xml_file.Clear();
      throw_named("Can't resolve parent!");
    }
    file_path += "/";
    try
    {
        parseIncludes(root_handle, file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't parse includes!");
    }

    // /////////////////////////
    // Initialise server
    initialise(root_handle, server);

    // /////////////////////////
    // Initialise problem
    problem.resize(problem_name.size());
    for (int i = 0; i < problem_name.size(); i++)
    {
      initialise(root_handle, problem[i], problem_name[i], server);
    }

    // /////////////////////////
    // Initialise solver
    solver.resize(solver_name.size());
    for (int i = 0; i < solver_name.size(); i++)
    {
      initialise(root_handle, solver[i], solver_name[i], server);
    }
  }
}
<commit_msg>Reflect plugin lib naming in the Initializer<commit_after>/*
 *      Author: Michael Camilleri
 *
 * Copyright (c) 2016, University Of Edinburgh
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of  nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "exotica/Initialiser.h"
using namespace rapidjson;

namespace exotica
{
  Initialiser_ptr Initialiser::singleton_initialiser_ = NULL;

  void Initialiser::printSupportedClasses()
  {
      HIGHLIGHT("Registered solvers:");
      std::vector<std::string> solvers =  Instance()->solvers_.getDeclaredClasses();
      for(std::string s : solvers)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
      HIGHLIGHT("Registered problems:");
      std::vector<std::string> problems =  Instance()->problems_.getDeclaredClasses();
      for(std::string s : problems)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
      HIGHLIGHT("Registered task definitions:");
      std::vector<std::string> definitions =  Instance()->definitions_.getDeclaredClasses();
      for(std::string s : definitions)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
      HIGHLIGHT("Registered task maps:");
      std::vector<std::string> maps =  Instance()->maps_.getDeclaredClasses();
      for(std::string s : maps)
      {
          HIGHLIGHT(" '"<<s<<"'");
      }
  }

  Initialiser::Initialiser() : solvers_("exotica","exotica::MotionSolver"), maps_("exotica","exotica::TaskMap"),
    definitions_("exotica","exotica::TaskDefinition"), problems_("exotica","exotica::PlanningProblem")
  {

  }

  void Initialiser::initialise(const std::string & file_name,
      Server_ptr & server, MotionSolver_ptr & solver,
      PlanningProblem_ptr & problem)
  {
    std::vector<std::string> probs, sols;
    Initialiser::listSolversAndProblems(file_name, probs, sols);
    if (probs.size() > 0 && sols.size() > 0)
    {
        return initialise(file_name, server, solver, problem, probs[0], sols[0]);
    }
    else
    {
        throw_named("No problems or solvers found!");
    }
  }

  void Initialiser::initialiseProblemJSON(PlanningProblem_ptr problem,
      const std::string& constraints)
  {
    {
      Document document;
      if (!document.Parse<0>(constraints.c_str()).HasParseError())
      {
        problem->reinitialise(document, problem);
      }
      else
      {
        throw_named("Can't parse constraints from JSON string!\n"<<document.GetParseError() <<"\n"<<constraints.substr(document.GetErrorOffset(),50));
      }
    }
  }

  void Initialiser::listSolversAndProblems(const std::string & file_name,
      std::vector<std::string>& problems, std::vector<std::string>& solvers)
  {
    xml_file.Clear();
    if (xml_file.LoadFile(file_name.c_str()) != tinyxml2::XML_NO_ERROR)
    {
      xml_file.Clear();
      throw_named("Can't load file!");
    }
    tinyxml2::XMLHandle root_handle(xml_file.RootElement());

    //!< First resolve any includes that exist
    std::string file_path = file_name;
    try
    {
        resolveParent(file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't resolve parent!");
    }
    file_path += "/";
    try
    {
        parseIncludes(root_handle, file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't parse includes!");
    }

    std::vector<std::string> registered_problems;
    registered_problems = PlanningProblem_fac::Instance().getDeclaredClasses();
    tinyxml2::XMLHandle problem_handle(root_handle.FirstChildElement());
    problems.clear();
    while (problem_handle.ToElement())
    {
      const char* atr = problem_handle.ToElement()->Attribute("name");
      const char* tp = problem_handle.ToElement()->Name();
      if (atr)
      {
        bool found = false;
        for (std::string& name : registered_problems)
        {
          if (std::string(tp).compare(name) == 0)
          {
            found = true;
            problems.push_back(std::string(atr));
            break;
          }
        }
        if (!found)
        {
          ERROR("Problem '"<<atr<<"' has unrecognized type '"<<tp<<"'");
        }
        problem_handle = problem_handle.NextSibling();
      }
      else
      {
        problem_handle = problem_handle.NextSibling();
        ERROR("Element name was not specified!");
        continue;
      }
    }

    std::vector<std::string> registered_solvers;
    registered_solvers = MotionSolver_fac::Instance().getDeclaredClasses();
    tinyxml2::XMLHandle solver_handle(root_handle.FirstChildElement());
    solvers.clear();
    while (solver_handle.ToElement())
    {
      const char* atr = solver_handle.ToElement()->Attribute("name");
      const char* tp = solver_handle.ToElement()->Name();
      if (atr)
      {
        bool found = false;
        for (std::string& name : registered_solvers)
        {
          if (std::string(tp).compare(name) == 0)
          {
            found = true;
            solvers.push_back(std::string(atr));
            break;
          }
        }
        if (!found)
        {
          ERROR("Solver '"<<atr<<"' has unrecognized type '"<<tp<<"'");
        }
        solver_handle = solver_handle.NextSibling();
      }
      else
      {
        solver_handle = solver_handle.NextSibling();
        ERROR("Element name was not specified!");
        continue;
      }
    }
  }

  void Initialiser::initialise(tinyxml2::XMLHandle root_handle,
      Server_ptr & server)
  {
    server = Server::Instance();
    tinyxml2::XMLHandle server_handle(root_handle.FirstChildElement("Server"));
    if (server_handle.ToElement())
    {
      server->initialise(server_handle);
    }
    else
    {
      throw_named("EXOTica Server element is missing in the xml");
    }
  }

  void Initialiser::initialise(tinyxml2::XMLHandle root_handle,
      PlanningProblem_ptr & problem, const std::string & problem_name,
      Server_ptr & server)
  {
    tinyxml2::XMLHandle problem_handle(root_handle.FirstChildElement());
    while (problem_handle.ToElement())
    {
      const char* atr = problem_handle.ToElement()->Attribute("name");
      if (atr)
      {
        if (std::string(atr).compare(problem_name) == 0)
        {

            PlanningProblem_fac::Instance().createObject(problem,problem_handle, server);
            return;
        }
        else
        {
          problem_handle = problem_handle.NextSibling();
          continue;
        }
      }
      else
      {
        problem_handle = problem_handle.NextSibling();
        ERROR("Element name was not specified!");
        continue;
      }
    }

    throw_named("File does not contain the '"<<problem_name<<"' problem definition.");
  }

  void Initialiser::initialise(tinyxml2::XMLHandle root_handle,
      MotionSolver_ptr & solver, const std::string & solver_name,
      Server_ptr & server)
  {
    tinyxml2::XMLHandle solver_handle(root_handle.FirstChildElement());
    while (solver_handle.ToElement())
    {
      if (!solver_name.empty())
      {
        const char* atr = solver_handle.ToElement()->Attribute("name");
        if (atr)
        {
          if (std::string(atr).compare(solver_name) == 0)
          {
            MotionSolver_fac::Instance().createObject(solver, solver_handle,server);
            return;
          }
          else
          {
            solver_handle = solver_handle.NextSibling();
            continue;
          }

        }
        else
        {
          solver_handle = solver_handle.NextSibling();
          ERROR("Element name was not specified!");
          continue;
        }
      }
      else
      {
        throw_named("Empty solver name");
      }
    }

    throw_named("File does not contain the '"<<solver_name<<"' solver.");
  }

  void Initialiser::initialise(const std::string & file_name,
      Server_ptr & server, MotionSolver_ptr & solver,
      PlanningProblem_ptr & problem, const std::string & problem_name,
      const std::string & solver_name)
  {
    // /////////////////////////
    // Create the document
    xml_file.Clear();
    if (xml_file.LoadFile(file_name.c_str()) != tinyxml2::XML_NO_ERROR)
    {
      xml_file.Clear();
      throw_named("Can't load XML!");
    }
    tinyxml2::XMLHandle root_handle(xml_file.RootElement());

    // /////////////////////////
    // First resolve any includes that exist
    std::string file_path = file_name;
    try
    {
        resolveParent(file_path);
    }
    catch(Exception e)
    {
      xml_file.Clear();
      throw_named("Can't resolve parent!");
    }
    file_path += "/";
    try
    {
        parseIncludes(root_handle, file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't parse includes!");
    }

    // /////////////////////////
    // Initialise server
    initialise(root_handle, server);

    // /////////////////////////
    // Initialise problem
    initialise(root_handle, problem, problem_name, server);

    // /////////////////////////
    // Initialise solver
    initialise(root_handle, solver, solver_name, server);
  }

  void Initialiser::initialise(const std::string & file_name,
      Server_ptr & server, std::vector<MotionSolver_ptr> & solver,
      std::vector<PlanningProblem_ptr> & problem,
      std::vector<std::string> & problem_name,
      std::vector<std::string> & solver_name)
  {
    // /////////////////////////
    // Create the document
    xml_file.Clear();
    if (xml_file.LoadFile(file_name.c_str()) != tinyxml2::XML_NO_ERROR)
    {
      xml_file.Clear();
      throw_named("Can't load XML!");
    }
    tinyxml2::XMLHandle root_handle(xml_file.RootElement());

    // /////////////////////////
    // First resolve any includes that exist
    std::string file_path = file_name;
    try
    {
        resolveParent(file_path);
    }
    catch(Exception e)
    {
      xml_file.Clear();
      throw_named("Can't resolve parent!");
    }
    file_path += "/";
    try
    {
        parseIncludes(root_handle, file_path);
    }
    catch (Exception e)
    {
      xml_file.Clear();
      throw_named("Can't parse includes!");
    }

    // /////////////////////////
    // Initialise server
    initialise(root_handle, server);

    // /////////////////////////
    // Initialise problem
    problem.resize(problem_name.size());
    for (int i = 0; i < problem_name.size(); i++)
    {
      initialise(root_handle, problem[i], problem_name[i], server);
    }

    // /////////////////////////
    // Initialise solver
    solver.resize(solver_name.size());
    for (int i = 0; i < solver_name.size(); i++)
    {
      initialise(root_handle, solver[i], solver_name[i], server);
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Accounts and contacts model
 * This file is based on TelepathyQt4Yell Models
 *
 * Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
 * Copyright (C) 2011 Martin Klapetek <martin dot klapetek at gmail dot com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "accounts-model.h"

#include <TelepathyQt4/ContactManager>
#include <TelepathyQt4/PendingReady>

#include "accounts-model-item.h"
#include "contact-model-item.h"

struct AccountsModel::Private
{
    Private(const Tp::AccountManagerPtr &am)
        : mAM(am)
    {
    }

    TreeNode *node(const QModelIndex &index) const;

    Tp::AccountManagerPtr mAM;
    TreeNode *mTree;
};

TreeNode *AccountsModel::Private::node(const QModelIndex &index) const
{
    TreeNode *node = reinterpret_cast<TreeNode *>(index.internalPointer());
    return node ? node : mTree;
}

AccountsModel::AccountsModel(const Tp::AccountManagerPtr &am, QObject *parent)
    : QAbstractItemModel(parent),
      mPriv(new AccountsModel::Private(am))
{
    mPriv->mTree = new TreeNode;
    connect(mPriv->mTree,
            SIGNAL(changed(TreeNode*)),
            SLOT(onItemChanged(TreeNode*)));

    connect(mPriv->mTree,
            SIGNAL(childrenAdded(TreeNode*,QList<TreeNode*>)),
            SLOT(onItemsAdded(TreeNode*,QList<TreeNode*>)));

    connect(mPriv->mTree,
            SIGNAL(childrenRemoved(TreeNode*,int,int)),
            SLOT(onItemsRemoved(TreeNode*,int,int)));

    foreach (Tp::AccountPtr account, mPriv->mAM->allAccounts()) {
        AccountsModelItem *item = new AccountsModelItem(account);
        connect(item, SIGNAL(connectionStatusChanged(QString,int)),
                this, SIGNAL(accountConnectionStatusChanged(QString,int)));
        mPriv->mTree->addChild(item);
    }

    connect(mPriv->mAM.data(),
            SIGNAL(newAccount(Tp::AccountPtr)),
            SLOT(onNewAccount(Tp::AccountPtr)));

    QHash<int, QByteArray> roles;
    roles[ItemRole] = "item";
    roles[IdRole] = "id";
    roles[ValidRole] = "valid";
    roles[EnabledRole] = "enabled";
    roles[ConnectionManagerNameRole] = "connectionManager";
    roles[ProtocolNameRole] = "protocol";
    roles[DisplayNameRole] = "displayName";
    roles[IconRole] = "icon";
    roles[NicknameRole] = "nickname";
    roles[ConnectsAutomaticallyRole] = "connectsAutomatically";
    roles[ChangingPresenceRole] = "changingPresence";
    roles[AutomaticPresenceRole] = "automaticStatus";
    roles[AutomaticPresenceTypeRole] = "automaticStatusType";
    roles[AutomaticPresenceStatusMessageRole] = "automaticStatusMessage";
    roles[CurrentPresenceRole] = "status";
    roles[CurrentPresenceTypeRole] = "statusType";
    roles[CurrentPresenceStatusMessageRole] = "statusMessage";
    roles[RequestedPresenceRole] = "requestedStatus";
    roles[RequestedPresenceTypeRole] = "requestedStatusType";
    roles[RequestedPresenceStatusMessageRole] = "requestedStatusMessage";
    roles[ConnectionStatusRole] = "connectionStatus";
    roles[ConnectionStatusReasonRole] = "connectionStatusReason";
    roles[AliasRole] = "aliasName";
    roles[AvatarRole] = "avatar";
    roles[PresenceStatusRole] = "presenceStatus";
    roles[PresenceTypeRole] = "presenceType";
    roles[PresenceMessageRole] = "presenceMessage";
    roles[SubscriptionStateRole] = "subscriptionState";
    roles[PublishStateRole] = "publishState";
    roles[BlockedRole] = "blocked";
    roles[GroupsRole] = "groups";
    roles[TextChatCapabilityRole] = "textChat";
    roles[MediaCallCapabilityRole] = "mediaCall";
    roles[AudioCallCapabilityRole] = "audioCall";
    roles[VideoCallCapabilityRole] = "videoCall";
    roles[UpgradeCallCapabilityRole] = "upgradeCall";
    roles[FileTransferCapabilityRole] = "fileTransfer";
    setRoleNames(roles);
}

AccountsModel::~AccountsModel()
{
    mPriv->mTree->deleteLater();
    delete mPriv;
}

void AccountsModel::onNewAccount(const Tp::AccountPtr &account)
{
    AccountsModelItem *accountNode = new AccountsModelItem(account);

    connect(accountNode, SIGNAL(connectionStatusChanged(QString,int)),
            this, SIGNAL(accountConnectionStatusChanged(QString,int)));

    onItemsAdded(mPriv->mTree, QList<TreeNode *>() << accountNode);
}

void AccountsModel::onItemChanged(TreeNode *node)
{
    if (node->parent()) {
        //if it is a group item
        if (node->parent() == mPriv->mTree) {
            qobject_cast<AccountsModelItem*>(node)->countOnlineContacts();
        } else {
            qobject_cast<AccountsModelItem*>(node->parent())->countOnlineContacts();
            emit dataChanged(index(node->parent()), index(node->parent()));
        }
    }
    QModelIndex accountIndex = index(node);
    emit dataChanged(accountIndex, accountIndex);
}

void AccountsModel::onItemsAdded(TreeNode *parent, const QList<TreeNode *> &nodes)
{
    QModelIndex parentIndex = index(parent);
    int currentSize = rowCount(parentIndex);
    beginInsertRows(parentIndex, currentSize, currentSize + nodes.size() - 1);
    foreach (TreeNode *node, nodes) {
        parent->addChild(node);
    }
    endInsertRows();
    emit accountCountChanged();
}

void AccountsModel::onItemsRemoved(TreeNode *parent, int first, int last)
{
    QModelIndex parentIndex = index(parent);
    QList<TreeNode *> removedItems;
    beginRemoveRows(parentIndex, first, last);
    for (int i = last; i >= first; i--) {
        parent->childAt(i)->remove();
    }
    endRemoveRows();

    emit accountCountChanged();
}

int AccountsModel::accountCount() const
{
    return mPriv->mTree->size();
}

QObject *AccountsModel::accountItemForId(const QString &id) const
{
    for (int i = 0; i < mPriv->mTree->size(); ++i) {
        AccountsModelItem *item = qobject_cast<AccountsModelItem*>(mPriv->mTree->childAt(i));
        if (!item) {
            continue;
        }

        if (item->data(IdRole) == id) {
            return item;
        }
    }

    return 0;
}

QObject *AccountsModel::contactItemForId(const QString &accountId, const QString &contactId) const
{
    AccountsModelItem *accountItem = qobject_cast<AccountsModelItem*>(accountItemForId(accountId));
    if (!accountItem) {
        return 0;
    }

    for (int i = 0; i < accountItem->size(); ++i) {
        ContactModelItem *item = qobject_cast<ContactModelItem*>(accountItem->childAt(i));
        if (!item) {
            continue;
        }

        if (item->data(IdRole) == contactId) {
            return item;
        }
    }

    return 0;
}

int AccountsModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

int AccountsModel::rowCount(const QModelIndex &parent) const
{
    return mPriv->node(parent)->size();
}

QVariant AccountsModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    return mPriv->node(index)->data(role);
}

Tp::AccountPtr AccountsModel::accountForContactItem(ContactModelItem *contactItem) const
{
    AccountsModelItem *accountItem = qobject_cast<AccountsModelItem*>(contactItem->parent());
    if (accountItem) {
        return accountItem->account();
    } else {
        return Tp::AccountPtr();
    }
}

Qt::ItemFlags AccountsModel::flags(const QModelIndex &index) const
{
    if (index.isValid()) {
        return Qt::ItemIsEnabled;
    }

    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

bool AccountsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid()) {
        mPriv->node(index)->setData(role, value);
    }

    return false;
}

QModelIndex AccountsModel::index(int row, int column, const QModelIndex &parent) const
{
    TreeNode *parentNode = mPriv->node(parent);
    return createIndex(row, column, parentNode->childAt(row));
}

QModelIndex AccountsModel::index(TreeNode *node) const
{
    if (node->parent()) {
        return createIndex(node->parent()->indexOf(node), 0, node);
    } else {
        return QModelIndex();
    }
}

QModelIndex AccountsModel::parent(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return QModelIndex();
    }

    TreeNode *currentNode = mPriv->node(index);
    if (currentNode->parent()) {
        return AccountsModel::index(currentNode->parent());
    } else {
        // no parent: return root node
        return QModelIndex();
    }
}

#include "accounts-model.moc"
<commit_msg>Prevent some crashes caused by array index being out of bounds<commit_after>/*
 * Accounts and contacts model
 * This file is based on TelepathyQt4Yell Models
 *
 * Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
 * Copyright (C) 2011 Martin Klapetek <martin dot klapetek at gmail dot com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "accounts-model.h"

#include <TelepathyQt4/ContactManager>
#include <TelepathyQt4/PendingReady>

#include "accounts-model-item.h"
#include "contact-model-item.h"

struct AccountsModel::Private
{
    Private(const Tp::AccountManagerPtr &am)
        : mAM(am)
    {
    }

    TreeNode *node(const QModelIndex &index) const;

    Tp::AccountManagerPtr mAM;
    TreeNode *mTree;
};

TreeNode *AccountsModel::Private::node(const QModelIndex &index) const
{
    TreeNode *node = reinterpret_cast<TreeNode *>(index.internalPointer());
    return node ? node : mTree;
}

AccountsModel::AccountsModel(const Tp::AccountManagerPtr &am, QObject *parent)
    : QAbstractItemModel(parent),
      mPriv(new AccountsModel::Private(am))
{
    mPriv->mTree = new TreeNode;
    connect(mPriv->mTree,
            SIGNAL(changed(TreeNode*)),
            SLOT(onItemChanged(TreeNode*)));

    connect(mPriv->mTree,
            SIGNAL(childrenAdded(TreeNode*,QList<TreeNode*>)),
            SLOT(onItemsAdded(TreeNode*,QList<TreeNode*>)));

    connect(mPriv->mTree,
            SIGNAL(childrenRemoved(TreeNode*,int,int)),
            SLOT(onItemsRemoved(TreeNode*,int,int)));

    foreach (Tp::AccountPtr account, mPriv->mAM->allAccounts()) {
        AccountsModelItem *item = new AccountsModelItem(account);
        connect(item, SIGNAL(connectionStatusChanged(QString,int)),
                this, SIGNAL(accountConnectionStatusChanged(QString,int)));
        mPriv->mTree->addChild(item);
    }

    connect(mPriv->mAM.data(),
            SIGNAL(newAccount(Tp::AccountPtr)),
            SLOT(onNewAccount(Tp::AccountPtr)));

    QHash<int, QByteArray> roles;
    roles[ItemRole] = "item";
    roles[IdRole] = "id";
    roles[ValidRole] = "valid";
    roles[EnabledRole] = "enabled";
    roles[ConnectionManagerNameRole] = "connectionManager";
    roles[ProtocolNameRole] = "protocol";
    roles[DisplayNameRole] = "displayName";
    roles[IconRole] = "icon";
    roles[NicknameRole] = "nickname";
    roles[ConnectsAutomaticallyRole] = "connectsAutomatically";
    roles[ChangingPresenceRole] = "changingPresence";
    roles[AutomaticPresenceRole] = "automaticStatus";
    roles[AutomaticPresenceTypeRole] = "automaticStatusType";
    roles[AutomaticPresenceStatusMessageRole] = "automaticStatusMessage";
    roles[CurrentPresenceRole] = "status";
    roles[CurrentPresenceTypeRole] = "statusType";
    roles[CurrentPresenceStatusMessageRole] = "statusMessage";
    roles[RequestedPresenceRole] = "requestedStatus";
    roles[RequestedPresenceTypeRole] = "requestedStatusType";
    roles[RequestedPresenceStatusMessageRole] = "requestedStatusMessage";
    roles[ConnectionStatusRole] = "connectionStatus";
    roles[ConnectionStatusReasonRole] = "connectionStatusReason";
    roles[AliasRole] = "aliasName";
    roles[AvatarRole] = "avatar";
    roles[PresenceStatusRole] = "presenceStatus";
    roles[PresenceTypeRole] = "presenceType";
    roles[PresenceMessageRole] = "presenceMessage";
    roles[SubscriptionStateRole] = "subscriptionState";
    roles[PublishStateRole] = "publishState";
    roles[BlockedRole] = "blocked";
    roles[GroupsRole] = "groups";
    roles[TextChatCapabilityRole] = "textChat";
    roles[MediaCallCapabilityRole] = "mediaCall";
    roles[AudioCallCapabilityRole] = "audioCall";
    roles[VideoCallCapabilityRole] = "videoCall";
    roles[UpgradeCallCapabilityRole] = "upgradeCall";
    roles[FileTransferCapabilityRole] = "fileTransfer";
    setRoleNames(roles);
}

AccountsModel::~AccountsModel()
{
    mPriv->mTree->deleteLater();
    delete mPriv;
}

void AccountsModel::onNewAccount(const Tp::AccountPtr &account)
{
    AccountsModelItem *accountNode = new AccountsModelItem(account);

    connect(accountNode, SIGNAL(connectionStatusChanged(QString,int)),
            this, SIGNAL(accountConnectionStatusChanged(QString,int)));

    onItemsAdded(mPriv->mTree, QList<TreeNode *>() << accountNode);
}

void AccountsModel::onItemChanged(TreeNode *node)
{
    if (node->parent()) {
        //if it is a group item
        if (node->parent() == mPriv->mTree) {
            qobject_cast<AccountsModelItem*>(node)->countOnlineContacts();
        } else {
            qobject_cast<AccountsModelItem*>(node->parent())->countOnlineContacts();
            emit dataChanged(index(node->parent()), index(node->parent()));
        }
    }
    QModelIndex accountIndex = index(node);
    emit dataChanged(accountIndex, accountIndex);
}

void AccountsModel::onItemsAdded(TreeNode *parent, const QList<TreeNode *> &nodes)
{
    QModelIndex parentIndex = index(parent);
    int currentSize = rowCount(parentIndex);
    beginInsertRows(parentIndex, currentSize, currentSize + nodes.size() - 1);
    foreach (TreeNode *node, nodes) {
        parent->addChild(node);
    }
    endInsertRows();
    emit accountCountChanged();
}

void AccountsModel::onItemsRemoved(TreeNode *parent, int first, int last)
{
    QModelIndex parentIndex = index(parent);
    QList<TreeNode *> removedItems;
    beginRemoveRows(parentIndex, first, last);
    for (int i = last; i >= first; i--) {
        parent->childAt(i)->remove();
    }
    endRemoveRows();

    emit accountCountChanged();
}

int AccountsModel::accountCount() const
{
    return mPriv->mTree->size();
}

QObject *AccountsModel::accountItemForId(const QString &id) const
{
    for (int i = 0; i < mPriv->mTree->size(); ++i) {
        AccountsModelItem *item = qobject_cast<AccountsModelItem*>(mPriv->mTree->childAt(i));
        if (!item) {
            continue;
        }

        if (item->data(IdRole) == id) {
            return item;
        }
    }

    return 0;
}

QObject *AccountsModel::contactItemForId(const QString &accountId, const QString &contactId) const
{
    AccountsModelItem *accountItem = qobject_cast<AccountsModelItem*>(accountItemForId(accountId));
    if (!accountItem) {
        return 0;
    }

    for (int i = 0; i < accountItem->size(); ++i) {
        ContactModelItem *item = qobject_cast<ContactModelItem*>(accountItem->childAt(i));
        if (!item) {
            continue;
        }

        if (item->data(IdRole) == contactId) {
            return item;
        }
    }

    return 0;
}

int AccountsModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

int AccountsModel::rowCount(const QModelIndex &parent) const
{
    return mPriv->node(parent)->size();
}

QVariant AccountsModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    return mPriv->node(index)->data(role);
}

Tp::AccountPtr AccountsModel::accountForContactItem(ContactModelItem *contactItem) const
{
    AccountsModelItem *accountItem = qobject_cast<AccountsModelItem*>(contactItem->parent());
    if (accountItem) {
        return accountItem->account();
    } else {
        return Tp::AccountPtr();
    }
}

Qt::ItemFlags AccountsModel::flags(const QModelIndex &index) const
{
    if (index.isValid()) {
        return Qt::ItemIsEnabled;
    }

    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

bool AccountsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid()) {
        mPriv->node(index)->setData(role, value);
    }

    return false;
}

QModelIndex AccountsModel::index(int row, int column, const QModelIndex &parent) const
{
    TreeNode *parentNode = mPriv->node(parent);
    Q_ASSERT(parentNode);
    if (row < parentNode->size()) {
        return createIndex(row, column, parentNode->childAt(row));
    }

    return QModelIndex();
}

QModelIndex AccountsModel::index(TreeNode *node) const
{
    if (node->parent()) {
        return createIndex(node->parent()->indexOf(node), 0, node);
    } else {
        return QModelIndex();
    }
}

QModelIndex AccountsModel::parent(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return QModelIndex();
    }

    TreeNode *currentNode = mPriv->node(index);
    if (currentNode->parent()) {
        return AccountsModel::index(currentNode->parent());
    } else {
        // no parent: return root node
        return QModelIndex();
    }
}

#include "accounts-model.moc"
<|endoftext|>