<commit_before>#include "amalgamated_budget.hpp"
#include "account.hpp"
#include "account_impl.hpp"
#include "account_type.hpp"
#include "budget_item_reader.hpp"
#include "draft_journal.hpp"
#include "entry.hpp"
#include "frequency.hpp"
#include "interval_type.hpp"
#include "phatbooks_exceptions.hpp"
#include "repeater.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/static_assert.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <sqloxx/sql_statement.hpp>
#include <algorithm>
#include <cassert>
#include <numeric>
#include <ostream>
#include <utility>
#include <vector>

using boost::scoped_ptr;
using jewel::Decimal;
using sqloxx::SQLStatement;
using std::accumulate;
using std::ostream;
using std::pair;
using std::vector;

namespace gregorian = boost::gregorian;

// For debugging only
#include <jewel/debug_log.hpp>
#include <iostream>
using std::endl;
// End debugging stuff

namespace phatbooks
{

BOOST_STATIC_ASSERT((boost::is_same<Account::Id, AccountImpl::Id>::value));

void
AmalgamatedBudget::setup_tables(PhatbooksDatabaseConnection& dbc)
{
	dbc.execute_sql
	(	"create index budget_item_account_index on budget_items(account_id)"
	);
	dbc.execute_sql
	(	"create table amalgamated_budget_data"
		"("
			"journal_id integer unique not null "
			"references draft_journal_detail, "
			"balancing_account_id integer unique not null "
			"references accounts"
		")"
	);
	DraftJournal instrument(dbc);
	instrument.set_name("AMALGAMATED BUDGET INSTRUMENT");
	instrument.set_whether_actual(false);
	instrument.set_comment("");
	instrument.save();

	Account balancing_account(dbc);
	balancing_account.set_account_type(account_type::pure_envelope);
	balancing_account.set_name("BUDGET IMBALANCE");
	balancing_account.set_description("");
	balancing_account.set_commodity
	(	Commodity::default_commodity(dbc)
	);
	balancing_account.save();

	SQLStatement statement
	(	dbc,
		"insert into amalgamated_budget_data"
		"(journal_id, balancing_account_id) "
		"values(:journal_id, :balancing_account_id)"
	);
	statement.bind(":journal_id", instrument.id());
	statement.bind(":balancing_account_id", balancing_account.id());
	statement.step_final();

	return;
}

AmalgamatedBudget::AmalgamatedBudget
(	PhatbooksDatabaseConnection& p_database_connection
):
	m_is_loaded(false),
	m_database_connection(p_database_connection),
	m_frequency(1, interval_type::days),
	m_map(new Map),
	m_instrument(0),
	m_balancing_account(0)
{
}

AmalgamatedBudget::~AmalgamatedBudget()
{
	delete m_instrument;
	m_instrument = 0;

	delete m_balancing_account;
	m_balancing_account = 0;
}

void
AmalgamatedBudget::load() const
{
	if (m_is_loaded)
	{
		return;
	}
	assert (!m_is_loaded);
	load_balancing_account();
	load_instrument();
	load_map();
	m_is_loaded = true;
	return;
}

Frequency
AmalgamatedBudget::frequency() const
{
	load();
	assert (m_frequency.num_steps() == 1);
	return m_frequency;
}

void
AmalgamatedBudget::set_frequency(Frequency const& p_frequency)
{
	load();
	m_frequency = p_frequency;
	regenerate();
	return;
}

Decimal
AmalgamatedBudget::budget(AccountImpl::Id p_account_id) const
{
	load();
	Map::const_iterator it = m_map->find(p_account_id);
	assert (it != m_map->end());
	return it->second;
}

namespace
{
	Decimal map_entry_accumulation_aux
	(	Decimal const& dec,
		pair<AccountImpl::Id, Decimal> const& rhs
	)
	{
		return dec + rhs.second;
	}

}  // end anonymous namespace

Decimal
AmalgamatedBudget::balance() const
{
	load();
	return accumulate
	(	m_map->begin(),
		m_map->end(),
		Decimal(0, 0),
		map_entry_accumulation_aux
	);
}

void
AmalgamatedBudget::generate_supported_frequencies(vector<Frequency>& vec)
{
	// NOTE This is co-dependent with the function
	// AmalgamatedBudget::supports_frequency. If this
	// changes, that must change too.
	vec.reserve(10);
	vec.push_back(Frequency(1, interval_type::days));
	vec.push_back(Frequency(1, interval_type::weeks));
	vec.push_back(Frequency(2, interval_type::weeks));
	vec.push_back(Frequency(4, interval_type::weeks));
	vec.push_back(Frequency(1, interval_type::months));
	vec.push_back(Frequency(2, interval_type::months));
	vec.push_back(Frequency(3, interval_type::months));
	vec.push_back(Frequency(4, interval_type::months));
	vec.push_back(Frequency(6, interval_type::months));
	vec.push_back(Frequency(12, interval_type::months));
	return;
}

bool
AmalgamatedBudget::supports_frequency(Frequency const& p_frequency)
{
	// NOTE This is co-dependent with the function
	// AmalgamatedBudget::supported_frequencies. If this changes,
	// that must change too.
	switch (p_frequency.step_type())
	{
	case interval_type::days:
		return p_frequency.num_steps() == 1;
	case interval_type::weeks:
		switch (p_frequency.num_steps())
		{
		case 1: case 2:	return true;
		case 3:			return false;
		case 4:			return true;
		default: 		return false;
		}
	case interval_type::months:
		switch (p_frequency.num_steps())
		{
		case 1: case 2: case 3: case 4:				return true;
		case 5:										return false;
		case 6:										return true;
		case 7: case 8: case 9: case 10: case 11:	return false;
		case 12:									return true;
		default:									return false;
		}
	case interval_type::month_ends:
		return false;
	default:
		assert (false);
	}
}

Account
AmalgamatedBudget::balancing_account() const
{
	load();
	assert (m_balancing_account != 0);
	return *m_balancing_account;
}

void
AmalgamatedBudget::regenerate()
{
	load();
	regenerate_map();
	regenerate_instrument();
	return;
}

void
AmalgamatedBudget::load_map() const
{
	assert (!m_is_loaded);
	assert (m_map->empty());
	generate_map();
	return;
}

void
AmalgamatedBudget::generate_map() const
{
	scoped_ptr<Map> map_elect(new Map);
	assert (map_elect->empty());

	SQLStatement account_selector
	(	m_database_connection,
		"select account_id from accounts"
	);
	while (account_selector.step())
	{
		AccountImpl::Id const account_id =
			account_selector.extract<AccountImpl::Id>(0);
		Account const account(m_database_connection, account_id);
		(*map_elect)[account_id] =
			Decimal(0, account.commodity().precision());
	}
	BudgetItemReader budget_item_reader(m_database_connection);
	BudgetItemReader::const_iterator const beg = budget_item_reader.begin();
	BudgetItemReader::const_iterator const end = budget_item_reader.end();

	// First we calculate budgets amalgamated on the basis of
	// the canonical frequency
	BudgetItemReader::const_iterator it = beg;
	for ( ; it != end; ++it)
	{
		Frequency const raw_frequency = it->frequency();
		if (!AmalgamatedBudget::supports_frequency(raw_frequency))
		{
			throw InvalidFrequencyException
			(	"Frequency not supported by AmalgamatedBudget."
			);
		}
		AccountImpl::Id const account_id = it->account().id();
		jewel::Decimal const raw_amount = it->amount();
		jewel::Decimal const canonical_amount = convert_to_canonical
		(	raw_frequency,
			raw_amount
		);
		Map::iterator tmit = map_elect->find(account_id);
		assert (tmit != map_elect->end());
		tmit->second += canonical_amount;
	}
	// Now convert to desired frequency
	for
	(	Map::iterator mit = map_elect->begin(), mend = map_elect->end();
		mit != mend;
		++mit
	)
	{
		mit->second = round
		(	convert_from_canonical(m_frequency, mit->second),
			Account(m_database_connection, mit->first).commodity().precision()
		);
	}
	using std::swap;
	swap(m_map, map_elect);

	return;
}

void
AmalgamatedBudget::regenerate_map()
{
	load();
	generate_map();
	return;
}

void
AmalgamatedBudget::regenerate_instrument()
{
	load();

	DraftJournal fresh_journal(m_database_connection);
	fresh_journal.mimic(*m_instrument);
	reflect_entries(fresh_journal);
	reflect_repeater(fresh_journal);

	// Deal with imbalance
	Account const ba = balancing_account();
	Entry balancing_entry(m_database_connection);
	balancing_entry.set_account(ba);
	balancing_entry.set_comment("");
	balancing_entry.set_whether_reconciled(false);
	balancing_entry.set_amount
	(	-round(fresh_journal.balance(), ba.commodity().precision())
	);
	fresh_journal.push_entry(balancing_entry);
	assert (fresh_journal.is_balanced());

	m_instrument->mimic(fresh_journal);
	m_instrument->save();

	return;
}

void
AmalgamatedBudget::load_balancing_account() const
{
	SQLStatement statement
	(	m_database_connection,
		"select balancing_account_id from amalgamated_budget_data"
	);
	statement.step();
	if (m_balancing_account)
	{
		delete m_balancing_account;
		m_balancing_account = 0;
	}
	m_balancing_account = new Account
	(	m_database_connection,
		statement.extract<Account::Id>(0)
	);
	statement.step_final();
	return;
}

void
AmalgamatedBudget::load_instrument() const
{
	// Set the instrument (the DraftJournal that carries out
	// the AmalgamatedBudget)
	SQLStatement statement
	(	m_database_connection,
		"select journal_id from amalgamated_budget_data"
	);
	statement.step();
	if (m_instrument)
	{
		delete m_instrument;
		m_instrument = 0;
	}
	m_instrument = new DraftJournal
	(	m_database_connection,
		statement.extract<DraftJournal::Id>(0)
	);
	statement.step_final();
	return;
}

void
AmalgamatedBudget::reflect_entries(DraftJournal& p_journal)
{
	load();
	p_journal.clear_entries();
	Map const& map = *m_map;
	for
	(	Map::const_iterator it = map.begin(), end = map.end();
		it != end;
		++it
	)
	{
		Entry entry(m_database_connection);
		Account const account(m_database_connection, it->first);
		entry.set_account(account);
		entry.set_comment("");
		entry.set_amount(-(it->second));
		entry.set_whether_reconciled(false);
		p_journal.push_entry(entry);
	}
	return;
}

void
AmalgamatedBudget::reflect_repeater(DraftJournal& p_journal)
{
	load();
	vector<Repeater> const& old_repeaters = p_journal.repeaters();
	if (old_repeaters.size() == 1)
	{
		Frequency const old_frequency = old_repeaters[0].frequency();
		if
		(	old_frequency.step_type() == m_frequency.step_type() &&
			old_frequency.num_steps() == m_frequency.num_steps()
		)
		{
			return;
		}
	}
	p_journal.clear_repeaters();
	Repeater new_repeater(m_database_connection);
	new_repeater.set_frequency(m_frequency);
	new_repeater.set_next_date(gregorian::day_clock::local_day());
	assert (p_journal.repeaters().empty());
	p_journal.push_repeater(new_repeater);
	return;
}

}  // namespace phatbooks

<commit_msg>Stopped AmalgamatedBudget::m_instrument from being populated with Entries for Accounts for which the budget is NIL.<commit_after>#include "amalgamated_budget.hpp"
#include "account.hpp"
#include "account_impl.hpp"
#include "account_type.hpp"
#include "budget_item_reader.hpp"
#include "draft_journal.hpp"
#include "entry.hpp"
#include "frequency.hpp"
#include "interval_type.hpp"
#include "phatbooks_exceptions.hpp"
#include "repeater.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/static_assert.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <sqloxx/sql_statement.hpp>
#include <algorithm>
#include <cassert>
#include <numeric>
#include <ostream>
#include <utility>
#include <vector>

using boost::scoped_ptr;
using jewel::Decimal;
using sqloxx::SQLStatement;
using std::accumulate;
using std::ostream;
using std::pair;
using std::vector;

namespace gregorian = boost::gregorian;

// For debugging only
#include <jewel/debug_log.hpp>
#include <iostream>
using std::endl;
// End debugging stuff

namespace phatbooks
{

BOOST_STATIC_ASSERT((boost::is_same<Account::Id, AccountImpl::Id>::value));

void
AmalgamatedBudget::setup_tables(PhatbooksDatabaseConnection& dbc)
{
	dbc.execute_sql
	(	"create index budget_item_account_index on budget_items(account_id)"
	);
	dbc.execute_sql
	(	"create table amalgamated_budget_data"
		"("
			"journal_id integer unique not null "
			"references draft_journal_detail, "
			"balancing_account_id integer unique not null "
			"references accounts"
		")"
	);
	DraftJournal instrument(dbc);
	instrument.set_name("AMALGAMATED BUDGET INSTRUMENT");
	instrument.set_whether_actual(false);
	instrument.set_comment("");
	instrument.save();

	Account balancing_account(dbc);
	balancing_account.set_account_type(account_type::pure_envelope);
	balancing_account.set_name("BUDGET IMBALANCE");
	balancing_account.set_description("");
	balancing_account.set_commodity
	(	Commodity::default_commodity(dbc)
	);
	balancing_account.save();

	SQLStatement statement
	(	dbc,
		"insert into amalgamated_budget_data"
		"(journal_id, balancing_account_id) "
		"values(:journal_id, :balancing_account_id)"
	);
	statement.bind(":journal_id", instrument.id());
	statement.bind(":balancing_account_id", balancing_account.id());
	statement.step_final();

	return;
}

AmalgamatedBudget::AmalgamatedBudget
(	PhatbooksDatabaseConnection& p_database_connection
):
	m_is_loaded(false),
	m_database_connection(p_database_connection),
	m_frequency(1, interval_type::days),
	m_map(new Map),
	m_instrument(0),
	m_balancing_account(0)
{
}

AmalgamatedBudget::~AmalgamatedBudget()
{
	delete m_instrument;
	m_instrument = 0;

	delete m_balancing_account;
	m_balancing_account = 0;
}

void
AmalgamatedBudget::load() const
{
	if (m_is_loaded)
	{
		return;
	}
	assert (!m_is_loaded);
	load_balancing_account();
	load_instrument();
	load_map();
	m_is_loaded = true;
	return;
}

Frequency
AmalgamatedBudget::frequency() const
{
	load();
	assert (m_frequency.num_steps() == 1);
	return m_frequency;
}

void
AmalgamatedBudget::set_frequency(Frequency const& p_frequency)
{
	load();
	m_frequency = p_frequency;
	regenerate();
	return;
}

Decimal
AmalgamatedBudget::budget(AccountImpl::Id p_account_id) const
{
	load();
	Map::const_iterator it = m_map->find(p_account_id);
	assert (it != m_map->end());
	return it->second;
}

namespace
{
	Decimal map_entry_accumulation_aux
	(	Decimal const& dec,
		pair<AccountImpl::Id, Decimal> const& rhs
	)
	{
		return dec + rhs.second;
	}

}  // end anonymous namespace

Decimal
AmalgamatedBudget::balance() const
{
	load();
	return accumulate
	(	m_map->begin(),
		m_map->end(),
		Decimal(0, 0),
		map_entry_accumulation_aux
	);
}

void
AmalgamatedBudget::generate_supported_frequencies(vector<Frequency>& vec)
{
	// NOTE This is co-dependent with the function
	// AmalgamatedBudget::supports_frequency. If this
	// changes, that must change too.
	vec.reserve(10);
	vec.push_back(Frequency(1, interval_type::days));
	vec.push_back(Frequency(1, interval_type::weeks));
	vec.push_back(Frequency(2, interval_type::weeks));
	vec.push_back(Frequency(4, interval_type::weeks));
	vec.push_back(Frequency(1, interval_type::months));
	vec.push_back(Frequency(2, interval_type::months));
	vec.push_back(Frequency(3, interval_type::months));
	vec.push_back(Frequency(4, interval_type::months));
	vec.push_back(Frequency(6, interval_type::months));
	vec.push_back(Frequency(12, interval_type::months));
	return;
}

bool
AmalgamatedBudget::supports_frequency(Frequency const& p_frequency)
{
	// NOTE This is co-dependent with the function
	// AmalgamatedBudget::supported_frequencies. If this changes,
	// that must change too.
	switch (p_frequency.step_type())
	{
	case interval_type::days:
		return p_frequency.num_steps() == 1;
	case interval_type::weeks:
		switch (p_frequency.num_steps())
		{
		case 1: case 2:	return true;
		case 3:			return false;
		case 4:			return true;
		default: 		return false;
		}
	case interval_type::months:
		switch (p_frequency.num_steps())
		{
		case 1: case 2: case 3: case 4:				return true;
		case 5:										return false;
		case 6:										return true;
		case 7: case 8: case 9: case 10: case 11:	return false;
		case 12:									return true;
		default:									return false;
		}
	case interval_type::month_ends:
		return false;
	default:
		assert (false);
	}
}

Account
AmalgamatedBudget::balancing_account() const
{
	load();
	assert (m_balancing_account != 0);
	return *m_balancing_account;
}

void
AmalgamatedBudget::regenerate()
{
	load();
	regenerate_map();
	regenerate_instrument();
	return;
}

void
AmalgamatedBudget::load_map() const
{
	assert (!m_is_loaded);
	assert (m_map->empty());
	generate_map();
	return;
}

void
AmalgamatedBudget::generate_map() const
{
	scoped_ptr<Map> map_elect(new Map);
	assert (map_elect->empty());

	SQLStatement account_selector
	(	m_database_connection,
		"select account_id from accounts"
	);
	while (account_selector.step())
	{
		AccountImpl::Id const account_id =
			account_selector.extract<AccountImpl::Id>(0);
		Account const account(m_database_connection, account_id);
		(*map_elect)[account_id] =
			Decimal(0, account.commodity().precision());
	}
	BudgetItemReader budget_item_reader(m_database_connection);
	BudgetItemReader::const_iterator const beg = budget_item_reader.begin();
	BudgetItemReader::const_iterator const end = budget_item_reader.end();

	// First we calculate budgets amalgamated on the basis of
	// the canonical frequency
	BudgetItemReader::const_iterator it = beg;
	for ( ; it != end; ++it)
	{
		Frequency const raw_frequency = it->frequency();
		if (!AmalgamatedBudget::supports_frequency(raw_frequency))
		{
			throw InvalidFrequencyException
			(	"Frequency not supported by AmalgamatedBudget."
			);
		}
		AccountImpl::Id const account_id = it->account().id();
		jewel::Decimal const raw_amount = it->amount();
		jewel::Decimal const canonical_amount = convert_to_canonical
		(	raw_frequency,
			raw_amount
		);
		Map::iterator tmit = map_elect->find(account_id);
		assert (tmit != map_elect->end());
		tmit->second += canonical_amount;
	}
	// Now convert to desired frequency
	for
	(	Map::iterator mit = map_elect->begin(), mend = map_elect->end();
		mit != mend;
		++mit
	)
	{
		mit->second = round
		(	convert_from_canonical(m_frequency, mit->second),
			Account(m_database_connection, mit->first).commodity().precision()
		);
	}
	using std::swap;
	swap(m_map, map_elect);

	return;
}

void
AmalgamatedBudget::regenerate_map()
{
	load();
	generate_map();
	return;
}

void
AmalgamatedBudget::regenerate_instrument()
{
	load();

	DraftJournal fresh_journal(m_database_connection);
	fresh_journal.mimic(*m_instrument);
	reflect_entries(fresh_journal);
	reflect_repeater(fresh_journal);

	// Deal with imbalance
	Account const ba = balancing_account();
	Entry balancing_entry(m_database_connection);
	balancing_entry.set_account(ba);
	balancing_entry.set_comment("");
	balancing_entry.set_whether_reconciled(false);
	balancing_entry.set_amount
	(	-round(fresh_journal.balance(), ba.commodity().precision())
	);
	fresh_journal.push_entry(balancing_entry);
	assert (fresh_journal.is_balanced());

	m_instrument->mimic(fresh_journal);
	m_instrument->save();

	return;
}

void
AmalgamatedBudget::load_balancing_account() const
{
	SQLStatement statement
	(	m_database_connection,
		"select balancing_account_id from amalgamated_budget_data"
	);
	statement.step();
	if (m_balancing_account)
	{
		delete m_balancing_account;
		m_balancing_account = 0;
	}
	m_balancing_account = new Account
	(	m_database_connection,
		statement.extract<Account::Id>(0)
	);
	statement.step_final();
	return;
}

void
AmalgamatedBudget::load_instrument() const
{
	// Set the instrument (the DraftJournal that carries out
	// the AmalgamatedBudget)
	SQLStatement statement
	(	m_database_connection,
		"select journal_id from amalgamated_budget_data"
	);
	statement.step();
	if (m_instrument)
	{
		delete m_instrument;
		m_instrument = 0;
	}
	m_instrument = new DraftJournal
	(	m_database_connection,
		statement.extract<DraftJournal::Id>(0)
	);
	statement.step_final();
	return;
}

void
AmalgamatedBudget::reflect_entries(DraftJournal& p_journal)
{
	load();
	p_journal.clear_entries();
	Map const& map = *m_map;
	for
	(	Map::const_iterator it = map.begin(), end = map.end();
		it != end;
		++it
	)
	{
		if (it->second != Decimal(0, 0))
		{
			Entry entry(m_database_connection);
			entry.set_account
			(	Account(m_database_connection, it->first)
			);
			entry.set_comment("");
			entry.set_amount(-(it->second));
			entry.set_whether_reconciled(false);
			p_journal.push_entry(entry);
		}
	}
	return;
}

void
AmalgamatedBudget::reflect_repeater(DraftJournal& p_journal)
{
	load();
	vector<Repeater> const& old_repeaters = p_journal.repeaters();
	if (old_repeaters.size() == 1)
	{
		Frequency const old_frequency = old_repeaters[0].frequency();
		if
		(	old_frequency.step_type() == m_frequency.step_type() &&
			old_frequency.num_steps() == m_frequency.num_steps()
		)
		{
			return;
		}
	}
	p_journal.clear_repeaters();
	Repeater new_repeater(m_database_connection);
	new_repeater.set_frequency(m_frequency);
	new_repeater.set_next_date(gregorian::day_clock::local_day());
	assert (p_journal.repeaters().empty());
	p_journal.push_repeater(new_repeater);
	return;
}

}  // namespace phatbooks

<|endoftext|>


<commit_before>//! \file **************************************************************
//! \brief Source Action de sauvegarde de traduction.
//!
//! - Compilateur : GCC,MinGW
//!
//! \author Antoine Maleyrie
//! \version 0.9
//! \date 31.03.2013
//!
//! ********************************************************************

/*
*	Copyright © 2013 - Antoine Maleyrie.
*/

#include "action/actSaveTranslation.hpp"
#include "resource.hpp"

#include <wx/wfstream.h>
#include <wx/msgdlg.h>
#include <wx/file.h>
#include <wx/log.h>

//TEST
#include <iostream>

// *********************************************************************
// Class PanelActSaveTranslation
// *********************************************************************

PanelActSaveTranslation::PanelActSaveTranslation(wxWindow* parent, wxButton* buttonOK, ActSaveTranslation * act)
: GuiPanelActSaveTranslation(parent), _act(act), _buttonOK(buttonOK)
{
	std::map<wxString, wxString> const& languages = Resource::getInstance()->getLanguages();

	//Ajout des langues.
	for(auto &it: languages)
	{
		_choiceLanguageSource->Append(it.second);
		_choiceLanguageOfTranslation->Append(it.second);
	}

	//Sélectionne les bonnes langues.
	int n = _choiceLanguageSource->FindString(languages.at(_act->_lgsrc));
	_choiceLanguageSource->SetSelection(n);
	n = _choiceLanguageOfTranslation->FindString(languages.at(_act->_lgto));
	_choiceLanguageOfTranslation->SetSelection(n);

	//Sélectionne le bon fichier.
	_filePickerFile->SetFileName(_act->_fileName);

	//Tout sauvegarder ?
	if(_act->_saveAll)
		_radioBtnSaveAllTranslations->SetValue(true);
	else
		_radioBtnSaveATranslation->SetValue(true);

	//Pas de doublon
	if(_act->_noDoublon)
		_checkBoxNoDoublon->SetValue(true);
	else
		_checkBoxNoDoublon->SetValue(false);

	//Dessiner un dialogue
	if(_act->_showDialog)
		_checkBoxShowDialog->SetValue(true);
	else
		_checkBoxShowDialog->SetValue(false);

	//Lier l'événement du bouton OK du wxWindow parent.
	_buttonOK->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &PanelActSaveTranslation::OnOKButtonClick, this, _buttonOK->GetId());
}

PanelActSaveTranslation::~PanelActSaveTranslation()
{
	_buttonOK->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, &PanelActSaveTranslation::OnOKButtonClick, this, _buttonOK->GetId());
}

void PanelActSaveTranslation::OnOKButtonClick(wxCommandEvent& event)
{
	//Vérifie si il y a un fichier de sélectionner.
	if(_filePickerFile->GetFileName().GetFullName().IsEmpty())
	{
		wxMessageBox(_("The name of file is empty."), _("Name file invalid"), wxOK|wxICON_EXCLAMATION|wxCENTRE, this);
		return;
	}

	//Récupérer le nom du fichier.
	wxFileName tmpFileName = _filePickerFile->GetFileName();

	//Si fichier a été modifier ?
	if(_act->_fileName != tmpFileName)
	{
		//Le fichier est déjà existent ?
		if(tmpFileName.Exists() && tmpFileName != _act->_fileName)
		{
			//Si il existe, on demande si il faut remplacer le fichier.
			wxString message = _("The file \"") + tmpFileName.GetFullPath() + _("\" already exists.\n") + _("Do you want delete this file?");
			wxMessageDialog *dlg = new wxMessageDialog(this, message, _("Delete a file"), wxYES_NO|wxICON_QUESTION|wxICON_EXCLAMATION|wxCENTRE);
			if(dlg->ShowModal() != wxID_YES)
			{
				dlg->Destroy();
				return;
			}
			else
			{
				//Suppression du fichier.
				if(!wxRemoveFile(_filePickerFile->GetPath()))
				{
					wxLogError(_("Could not remove the file : ")+tmpFileName.GetFullPath());
				}

				dlg->Destroy();
			}
		}
	}

	//Affect le langage source.
	int n = _choiceLanguageSource->GetSelection();
	wxString s = _choiceLanguageSource->GetString(n);
	_act->_lgsrc = Resource::getInstance()->languageToAbbreviation(s);

	//Affect le langage de destination.
	n = _choiceLanguageOfTranslation->GetSelection();
	s = _choiceLanguageOfTranslation->GetString(n);
	_act->_lgto = Resource::getInstance()->languageToAbbreviation(s);

	//Affect les autres arguments.
	_act->_fileName = tmpFileName;
	_act->_saveAll = _radioBtnSaveAllTranslations->GetValue();
	_act->_noDoublon = _checkBoxNoDoublon->IsChecked();
	_act->_showDialog = _checkBoxShowDialog->IsChecked();

	//Propage l'événement.
	event.Skip();
}

// *********************************************************************
// Class ActSaveTranslationFile
// *********************************************************************
ActSaveTranslationFile::ActSaveTranslationFile(wxFileName const& fileName)
: _fileName(fileName), _isOk(true)
{
	//Si le fichier existe on le charge
	if(wxFile::Exists(fileName.GetFullPath()))
	{
		//Ouverture du fichier
		wxFileInputStream file(_fileName.GetFullPath());
		_isOk = file.IsOk();

		//OK ?
		if(_isOk)
		{
			//Le buffer pour stoker le tout contenue fichier
			wxMemoryBuffer buffer;
			//data temporaire.
			uint8_t tmpData[1024];

			//Lie des données temps qu'il y en a.
			while(file.CanRead() && !file.Eof())
			{
				file.Read(tmpData, 1024);
				buffer.AppendData(tmpData, file.LastRead());
			}

			//Ajouter les données dans un wxString.
			wxString stringFile;
			stringFile.Append((const char *)buffer.GetData(), buffer.GetDataLen());

			//On récupère la première ligne et on sauvegarde le reste
			wxString firstLine = stringFile.BeforeFirst('\n', &_texts);

			//On analyse la première ligne
			wxString beforeComma;
			for(size_t i = 0; i<firstLine.Length(); i++)
			{
				if(firstLine[i] == ',')
				{
					_FirstLine.Add(beforeComma);
					beforeComma.Clear();
				}
				else
				{
					beforeComma << firstLine[i];
				}
			}
		}
	}
}

ActSaveTranslationFile::~ActSaveTranslationFile()
{

}

bool ActSaveTranslationFile::isOk()
{
	return _isOk;
}

//! \todo ne fonctionne pas
bool ActSaveTranslationFile::exist(wxString text)
{
	//Caractère en minuscule.
	text.MakeLower();

	//Taille des wxString
	size_t sizeStringFile = _texts.Length();
	//Index pour le text
	size_t indexText = 0;

	//Variable pour savoir si on doit comparer les caractères.
	bool compare = true;

	//Parcoure touts les caractères (avec la ',') temps que l'on a pas trouver le "text"
	for(size_t i = 0; i < sizeStringFile; i++)
	{
		//Doit-ont comparer les caractères ?
		if(compare)
		{
			//Les caractères sont égaux.
			if(text[indexText] == _texts[i])
			{
				//Si le caractères suivent est une ',' alors le text existe
				if(_texts[i+1] == ',')
				{
					return true;
				}

				indexText++;
			}
			//On arrête de comparer pour cette ligne.
			else
			{
				compare = false;
			}
		}

		//On arrête de comparer si ','
		if(_texts[i] == ',')
		{
			compare = false;
		}
		//On repent la comparaison si nouvelle ligne ?
		else if(_texts[i] == '\n')
		{
			compare = true;
		}
	}

	return false;
}

void ActSaveTranslationFile::save(	wxString text,
									wxString mainTranslate)
{
	//Caractère en minuscule.
	text.MakeLower();
	mainTranslate.MakeLower();

	wxFile file;
	wxString stringAtWrite;

	//Ouverture du fichier
	if(!file.Open(_fileName.GetFullPath(), wxFile::write_append))
	{
		return;
	}

	//Écriture des données dans le fichier
	stringAtWrite += "\n" + text + "," + mainTranslate;
	file.Write(stringAtWrite);

	//Fermeture du fichier
	file.Close();
}

void ActSaveTranslationFile::save(
	wxString text,
	wxString mainTranslate,
	std::map<wxString, wxArrayString> const& translations)
{
	//Caractère en minuscule.
	text.MakeLower();
	mainTranslate.MakeLower();
}

// *********************************************************************
// Class ActSaveTranslation
// *********************************************************************

//! \todo a compléter avec les local
ActSaveTranslation::ActSaveTranslation()
: ActSaveTranslation(	"en", "fr", wxFileName(wxGetUserHome(), ""),
						true, true, true)
{
}

ActSaveTranslation::ActSaveTranslation(wxString const& lgsrc,
							wxString const& lgto,
							wxFileName const& fileName,
							bool soveAll,
							bool noDoublon,
							bool showDialog)
: Action(_("Save a translation"), "ActSaveTranslation",
_("Translation a word or a group words from google and save in a file.")),
_lgsrc(lgsrc), _lgto(lgto), _fileName(fileName),
_saveAll(soveAll), _noDoublon(noDoublon), _showDialog(showDialog)
{
}

ActSaveTranslation::~ActSaveTranslation()
{
}

void ActSaveTranslation::execute()
{
	//On récupère le contenue de la presse papier.
	wxString clipboard = Resource::getClipboard();

	//La presse papier est t'elle vide ?
	if(clipboard.IsEmpty())
	{
		//Pas de texte à traduire
		Notification::getInstance()->notify(_("Save clipboard translation"), _("Sorry, nothing at save."));
		return;
	}

	//On récupère le texte traduit
	std::map<wxString, wxArrayString> translations;
	wxString mainTranslate = Resource::getTranslations(&translations, clipboard, _lgsrc, _lgto);
	//On vérifie si une traduction existe.
	if(mainTranslate.IsEmpty())
	{
		Notification::getInstance()->notify(_("Save clipboard translation"), _("Sorry, nothing at save."));
		return;
	}

	//On vérifie la validités du fichier.
	if(_fileName.GetFullName().IsEmpty())
	{
		wxMessageBox(_("The name of file is wrong."), _("Name file invalid."), wxOK|wxICON_EXCLAMATION|wxCENTRE);
		return;
	}

	//Fichier de sauvegarde
	ActSaveTranslationFile file(_fileName);

	//Vérifie si ok
	if(!file.isOk())
		return;

	//Si on dois vérifier l'existence du texte dans le fichier
	if(_noDoublon)
	{
		if(file.exist(clipboard))
		{
			Notification::getInstance()->notify(_("Save clipboard translation"), _("The text is already existing in ")+_fileName.GetFullPath());
			return;
		}
	}

	//Sinon on le sauvegarde.
	if(_saveAll)//Doit ton tout sauvegarder ?
	{
		file.save(clipboard, mainTranslate, translations);
	}
	else
	{
		file.save(clipboard, mainTranslate);
	}

	Notification::getInstance()->notify(_("Save clipboard translation"), _("The text has be saved."));
}

wxPanel* ActSaveTranslation::getPanelPreferences(wxWindow* parent, wxButton* buttonOK)
{
	return new PanelActSaveTranslation(parent, buttonOK, this);
}

void ActSaveTranslation::actLoad(wxFileConfig & fileConfig)
{
	//On récupère les langages.
	fileConfig.Read("lgsrc", &_lgsrc);
	fileConfig.Read("lgto", &_lgto);

	//On récupère le fichier.
	wxString file;
	fileConfig.Read("fileName", &file);
	_fileName.Assign(file);

	//On récupère le reste
	fileConfig.Read("saveAll", &_saveAll);
	fileConfig.Read("noDoublon", &_noDoublon);
	fileConfig.Read("showDialog", &_showDialog);
}

void ActSaveTranslation::actSave(wxFileConfig & fileConfig)const
{
	//On sauvegarde les langages.
	fileConfig.Write("lgsrc", _lgsrc);
	fileConfig.Write("lgto", _lgto);

	//On sauvegarde le fichier.
	fileConfig.Write("fileName", _fileName.GetFullPath());

	//On sauvegarde le reste
	fileConfig.Write("saveAll", _saveAll);
	fileConfig.Write("noDoublon", _noDoublon);
	fileConfig.Write("showDialog", _showDialog);
}

wxString ActSaveTranslation::getStringPreferences()const
{
	return 	Resource::getInstance()->abbreviationToLanguage(_lgsrc) +
			_(" to ") +
			Resource::getInstance()->abbreviationToLanguage(_lgto) +
			_(" in ") + _fileName.GetFullPath();
}
<commit_msg>fix bug in ActSaveTranslationFile::exist<commit_after>//! \file **************************************************************
//! \brief Source Action de sauvegarde de traduction.
//!
//! - Compilateur : GCC,MinGW
//!
//! \author Antoine Maleyrie
//! \version 0.9
//! \date 31.03.2013
//!
//! ********************************************************************

/*
*	Copyright © 2013 - Antoine Maleyrie.
*/

#include "action/actSaveTranslation.hpp"
#include "resource.hpp"

#include <wx/wfstream.h>
#include <wx/msgdlg.h>
#include <wx/file.h>
#include <wx/log.h>

//TEST
#include <iostream>

// *********************************************************************
// Class PanelActSaveTranslation
// *********************************************************************

PanelActSaveTranslation::PanelActSaveTranslation(wxWindow* parent, wxButton* buttonOK, ActSaveTranslation * act)
: GuiPanelActSaveTranslation(parent), _act(act), _buttonOK(buttonOK)
{
	std::map<wxString, wxString> const& languages = Resource::getInstance()->getLanguages();

	//Ajout des langues.
	for(auto &it: languages)
	{
		_choiceLanguageSource->Append(it.second);
		_choiceLanguageOfTranslation->Append(it.second);
	}

	//Sélectionne les bonnes langues.
	int n = _choiceLanguageSource->FindString(languages.at(_act->_lgsrc));
	_choiceLanguageSource->SetSelection(n);
	n = _choiceLanguageOfTranslation->FindString(languages.at(_act->_lgto));
	_choiceLanguageOfTranslation->SetSelection(n);

	//Sélectionne le bon fichier.
	_filePickerFile->SetFileName(_act->_fileName);

	//Tout sauvegarder ?
	if(_act->_saveAll)
		_radioBtnSaveAllTranslations->SetValue(true);
	else
		_radioBtnSaveATranslation->SetValue(true);

	//Pas de doublon
	if(_act->_noDoublon)
		_checkBoxNoDoublon->SetValue(true);
	else
		_checkBoxNoDoublon->SetValue(false);

	//Dessiner un dialogue
	if(_act->_showDialog)
		_checkBoxShowDialog->SetValue(true);
	else
		_checkBoxShowDialog->SetValue(false);

	//Lier l'événement du bouton OK du wxWindow parent.
	_buttonOK->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &PanelActSaveTranslation::OnOKButtonClick, this, _buttonOK->GetId());
}

PanelActSaveTranslation::~PanelActSaveTranslation()
{
	_buttonOK->Unbind(wxEVT_COMMAND_BUTTON_CLICKED, &PanelActSaveTranslation::OnOKButtonClick, this, _buttonOK->GetId());
}

void PanelActSaveTranslation::OnOKButtonClick(wxCommandEvent& event)
{
	//Vérifie si il y a un fichier de sélectionner.
	if(_filePickerFile->GetFileName().GetFullName().IsEmpty())
	{
		wxMessageBox(_("The name of file is empty."), _("Name file invalid"), wxOK|wxICON_EXCLAMATION|wxCENTRE, this);
		return;
	}

	//Récupérer le nom du fichier.
	wxFileName tmpFileName = _filePickerFile->GetFileName();

	//Si fichier a été modifier ?
	if(_act->_fileName != tmpFileName)
	{
		//Le fichier est déjà existent ?
		if(tmpFileName.Exists() && tmpFileName != _act->_fileName)
		{
			//Si il existe, on demande si il faut remplacer le fichier.
			wxString message = _("The file \"") + tmpFileName.GetFullPath() + _("\" already exists.\n") + _("Do you want delete this file?");
			wxMessageDialog *dlg = new wxMessageDialog(this, message, _("Delete a file"), wxYES_NO|wxICON_QUESTION|wxICON_EXCLAMATION|wxCENTRE);
			if(dlg->ShowModal() != wxID_YES)
			{
				dlg->Destroy();
				return;
			}
			else
			{
				//Suppression du fichier.
				if(!wxRemoveFile(_filePickerFile->GetPath()))
				{
					wxLogError(_("Could not remove the file : ")+tmpFileName.GetFullPath());
				}

				dlg->Destroy();
			}
		}
	}

	//Affect le langage source.
	int n = _choiceLanguageSource->GetSelection();
	wxString s = _choiceLanguageSource->GetString(n);
	_act->_lgsrc = Resource::getInstance()->languageToAbbreviation(s);

	//Affect le langage de destination.
	n = _choiceLanguageOfTranslation->GetSelection();
	s = _choiceLanguageOfTranslation->GetString(n);
	_act->_lgto = Resource::getInstance()->languageToAbbreviation(s);

	//Affect les autres arguments.
	_act->_fileName = tmpFileName;
	_act->_saveAll = _radioBtnSaveAllTranslations->GetValue();
	_act->_noDoublon = _checkBoxNoDoublon->IsChecked();
	_act->_showDialog = _checkBoxShowDialog->IsChecked();

	//Propage l'événement.
	event.Skip();
}

// *********************************************************************
// Class ActSaveTranslationFile
// *********************************************************************
ActSaveTranslationFile::ActSaveTranslationFile(wxFileName const& fileName)
: _fileName(fileName), _isOk(true)
{
	//Si le fichier existe on le charge
	if(wxFile::Exists(fileName.GetFullPath()))
	{
		//Ouverture du fichier
		wxFileInputStream file(_fileName.GetFullPath());
		_isOk = file.IsOk();

		//OK ?
		if(_isOk)
		{
			//Le buffer pour stoker le tout contenue fichier
			wxMemoryBuffer buffer;
			//data temporaire.
			uint8_t tmpData[1024];

			//Lie des données temps qu'il y en a.
			while(file.CanRead() && !file.Eof())
			{
				file.Read(tmpData, 1024);
				buffer.AppendData(tmpData, file.LastRead());
			}

			//Ajouter les données dans un wxString.
			wxString stringFile;
			stringFile.Append((const char *)buffer.GetData(), buffer.GetDataLen());

			//On récupère la première ligne et on sauvegarde le reste
			wxString firstLine = stringFile.BeforeFirst('\n', &_texts);

			//On analyse la première ligne
			wxString beforeComma;
			for(size_t i = 0; i<firstLine.Length(); i++)
			{
				if(firstLine[i] == ',')
				{
					_FirstLine.Add(beforeComma);
					beforeComma.Clear();
				}
				else
				{
					beforeComma << firstLine[i];
				}
			}
		}
	}
}

ActSaveTranslationFile::~ActSaveTranslationFile()
{

}

bool ActSaveTranslationFile::isOk()
{
	return _isOk;
}

//! \todo ne fonctionne pas
bool ActSaveTranslationFile::exist(wxString text)
{
	//Caractère en minuscule.
	text.MakeLower();

	//Taille des wxString
	size_t sizeTexts = _texts.Length();
	size_t sizeText = text.Length();
	//Index pour le text
	size_t indexText = 0;

	//Variable pour savoir si on doit comparer les caractères.
	bool compare = true;

	//Parcoure touts les caractères (avec la ',') temps que l'on a pas trouver le "text"
	for(size_t i = 0; i < sizeTexts; i++)
	{
		//Doit-ont comparer les caractères ?
		if(compare)
		{
			//Si les caractère ne son pas les même.
			if(text[indexText] != _texts[i])
			{
				//Si on li une ',' et que l'on est a la fin du text.
				//Ceci veut dire que l'on a trouver le text.
				if(_texts[i] == ',' && (sizeText == indexText))
				{
					return true;
				}
				//Sinon on arrêt de comparer
				compare = false;
			}

			indexText++;
		}

		//On repent la comparaison si nouvelle ligne ?
		if(_texts[i] == '\n')
		{
			indexText = 0;
			compare = true;
		}
	}

	return false;
}

void ActSaveTranslationFile::save(	wxString text,
									wxString mainTranslate)
{
	//Caractère en minuscule.
	text.MakeLower();
	mainTranslate.MakeLower();

	wxFile file;
	wxString stringAtWrite;

	//Ouverture du fichier
	if(!file.Open(_fileName.GetFullPath(), wxFile::write_append))
	{
		return;
	}

	//Écriture des données dans le fichier
	stringAtWrite += "\n" + text + "," + mainTranslate;
	file.Write(stringAtWrite);

	//Fermeture du fichier
	file.Close();
}

void ActSaveTranslationFile::save(
	wxString text,
	wxString mainTranslate,
	std::map<wxString, wxArrayString> const& translations)
{
	//Caractère en minuscule.
	text.MakeLower();
	mainTranslate.MakeLower();
}

// *********************************************************************
// Class ActSaveTranslation
// *********************************************************************

//! \todo a compléter avec les local
ActSaveTranslation::ActSaveTranslation()
: ActSaveTranslation(	"en", "fr", wxFileName(wxGetUserHome(), ""),
						true, true, true)
{
}

ActSaveTranslation::ActSaveTranslation(wxString const& lgsrc,
							wxString const& lgto,
							wxFileName const& fileName,
							bool soveAll,
							bool noDoublon,
							bool showDialog)
: Action(_("Save a translation"), "ActSaveTranslation",
_("Translation a word or a group words from google and save in a file.")),
_lgsrc(lgsrc), _lgto(lgto), _fileName(fileName),
_saveAll(soveAll), _noDoublon(noDoublon), _showDialog(showDialog)
{
}

ActSaveTranslation::~ActSaveTranslation()
{
}

void ActSaveTranslation::execute()
{
	//On récupère le contenue de la presse papier.
	wxString clipboard = Resource::getClipboard();

	//La presse papier est t'elle vide ?
	if(clipboard.IsEmpty())
	{
		//Pas de texte à traduire
		Notification::getInstance()->notify(_("Save clipboard translation"), _("Sorry, nothing at save."));
		return;
	}

	//On récupère le texte traduit
	std::map<wxString, wxArrayString> translations;
	wxString mainTranslate = Resource::getTranslations(&translations, clipboard, _lgsrc, _lgto);
	//On vérifie si une traduction existe.
	if(mainTranslate.IsEmpty())
	{
		Notification::getInstance()->notify(_("Save clipboard translation"), _("Sorry, nothing at save."));
		return;
	}

	//On vérifie la validités du fichier.
	if(_fileName.GetFullName().IsEmpty())
	{
		wxMessageBox(_("The name of file is wrong."), _("Name file invalid."), wxOK|wxICON_EXCLAMATION|wxCENTRE);
		return;
	}

	//Fichier de sauvegarde
	ActSaveTranslationFile file(_fileName);

	//Vérifie si ok
	if(!file.isOk())
		return;

	//Si on dois vérifier l'existence du texte dans le fichier
	if(_noDoublon)
	{
		if(file.exist(clipboard))
		{
			Notification::getInstance()->notify(_("Save clipboard translation"), _("The text is already existing in ")+_fileName.GetFullPath());
			return;
		}
	}

	//Sinon on le sauvegarde.
	if(_saveAll)//Doit ton tout sauvegarder ?
	{
		file.save(clipboard, mainTranslate, translations);
	}
	else
	{
		file.save(clipboard, mainTranslate);
	}

	Notification::getInstance()->notify(_("Save clipboard translation"), _("The text has be saved."));
}

wxPanel* ActSaveTranslation::getPanelPreferences(wxWindow* parent, wxButton* buttonOK)
{
	return new PanelActSaveTranslation(parent, buttonOK, this);
}

void ActSaveTranslation::actLoad(wxFileConfig & fileConfig)
{
	//On récupère les langages.
	fileConfig.Read("lgsrc", &_lgsrc);
	fileConfig.Read("lgto", &_lgto);

	//On récupère le fichier.
	wxString file;
	fileConfig.Read("fileName", &file);
	_fileName.Assign(file);

	//On récupère le reste
	fileConfig.Read("saveAll", &_saveAll);
	fileConfig.Read("noDoublon", &_noDoublon);
	fileConfig.Read("showDialog", &_showDialog);
}

void ActSaveTranslation::actSave(wxFileConfig & fileConfig)const
{
	//On sauvegarde les langages.
	fileConfig.Write("lgsrc", _lgsrc);
	fileConfig.Write("lgto", _lgto);

	//On sauvegarde le fichier.
	fileConfig.Write("fileName", _fileName.GetFullPath());

	//On sauvegarde le reste
	fileConfig.Write("saveAll", _saveAll);
	fileConfig.Write("noDoublon", _noDoublon);
	fileConfig.Write("showDialog", _showDialog);
}

wxString ActSaveTranslation::getStringPreferences()const
{
	return 	Resource::getInstance()->abbreviationToLanguage(_lgsrc) +
			_(" to ") +
			Resource::getInstance()->abbreviationToLanguage(_lgto) +
			_(" in ") + _fileName.GetFullPath();
}
<|endoftext|>


<commit_before>/*
 *  AudioSubsystem.cpp
 *
 *  Created on: 5 maj 2014
 *  Author: Lech Kulina
 *  E-Mail: kulinalech@gmail.com
 */

#include <SDL.h>
#include <SDL_mixer.h>
#include <Core/AudioSubsystem.hpp>

Cosmic::Core::AudioSubsystem::AudioSubsystem() :
    logger(
        boost::log::keywords::severity = Common::Severity::Trace,
        boost::log::keywords::channel = Common::Channel::Subsystem),
    initialized(false) {
    BOOST_LOG_FUNCTION();

    //initialize SDL mixer library with OGG/Vorbis support
    BOOST_LOG(logger) << "Initializing SDL_mixer library with OGG/Vorbis support.";
    const int requestedFlags = MIX_INIT_OGG;
    const int acquiredFlags = Mix_Init(requestedFlags);
    if ((acquiredFlags & requestedFlags) != requestedFlags) {
        BOOST_LOG_SEV(logger, Common::Severity::Critical)
            << "Failed to initialize SDL_mixer with OGG/Vorbis support. " << Mix_GetError();
        Mix_Quit();
        return;
    }

    //retrieve version of SDL mixer library that we are currently linked against
    memcpy(&version, Mix_Linked_Version(), sizeof(SDL_version));
    BOOST_LOG_SEV(logger, Common::Severity::Debug)
        << "SDL_mixer " << int(version.major) << "." << int(version.minor) << "." << int(version.patch) << " initialized with OGG/Vorbis support.";

    //open audio device with default settings (for now at least...)
    BOOST_LOG(logger) << "Opening audio device.";
    if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) != 0) {
        BOOST_LOG_SEV(logger, Common::Severity::Critical)
            << "Failed to open audio device. " << Mix_GetError();
        Mix_Quit();
        return;
    }

    //query the actual format that is in use by the opened audio device
    if (Mix_QuerySpec(&frequency, &format, &channels) == 0) {
        BOOST_LOG_SEV(logger, Common::Severity::Critical)
            << "Failed to query audio format that is in use by the current audio device. " << Mix_GetError();
        Mix_CloseAudio();
        Mix_Quit();
        return;
    }
    BOOST_LOG_SEV(logger, Common::Severity::Debug)
        << "Audio device with frequency " << frequency << ", format " << format << " and number of channels " << channels << " opened.";

    initialized = true;
}

Cosmic::Core::AudioSubsystem::~AudioSubsystem() {
    BOOST_LOG_FUNCTION();

    //check if we are initialized
    if (!isInitialized()) {
        BOOST_LOG_SEV(logger, Common::Severity::Debug) << "SDL_mixer library was not initialized.";
        return;
    }

    //close audio device
    BOOST_LOG(logger) << "Closing audio device.";
    Mix_CloseAudio();

    //clean up SDL_mixer library stuff
    BOOST_LOG(logger) << "Cleaning up SDL_mixer library.";
    Mix_Quit();
}

bool Cosmic::Core::AudioSubsystem::isInitialized() const {
    return initialized;
}
<commit_msg>Get chunk decoders info<commit_after>/*
 *  AudioSubsystem.cpp
 *
 *  Created on: 5 maj 2014
 *  Author: Lech Kulina
 *  E-Mail: kulinalech@gmail.com
 */

#include <SDL.h>
#include <SDL_mixer.h>
#include <Core/AudioSubsystem.hpp>

Cosmic::Core::AudioSubsystem::AudioSubsystem() :
    logger(
        boost::log::keywords::severity = Common::Severity::Trace,
        boost::log::keywords::channel = Common::Channel::Subsystem),
    initialized(false) {
    BOOST_LOG_FUNCTION();

    //initialize SDL mixer library with OGG/Vorbis support
    BOOST_LOG(logger) << "Initializing SDL_mixer library with OGG/Vorbis support.";
    const int requestedFlags = MIX_INIT_OGG;
    const int acquiredFlags = Mix_Init(requestedFlags);
    if ((acquiredFlags & requestedFlags) != requestedFlags) {
        BOOST_LOG_SEV(logger, Common::Severity::Critical)
            << "Failed to initialize SDL_mixer with OGG/Vorbis support. " << Mix_GetError();
        Mix_Quit();
        return;
    }

    //retrieve version of SDL mixer library that we are currently linked against
    memcpy(&version, Mix_Linked_Version(), sizeof(SDL_version));
    BOOST_LOG_SEV(logger, Common::Severity::Debug)
        << "SDL_mixer " << int(version.major) << "." << int(version.minor) << "." << int(version.patch) << " initialized with OGG/Vorbis support.";

    //open audio device with default settings (for now at least...)
    BOOST_LOG(logger) << "Opening audio device.";
    if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) != 0) {
        BOOST_LOG_SEV(logger, Common::Severity::Critical)
            << "Failed to open audio device. " << Mix_GetError();
        Mix_Quit();
        return;
    }

    //get the chunk decoders info
    const int chunkDecoders = Mix_GetNumChunkDecoders();
    BOOST_LOG(logger) << "There are " << chunkDecoders << " chunk decoders available.";
    for (int i=0; i < chunkDecoders; ++i) {
        BOOST_LOG_SEV(logger, Common::Severity::Debug)
            << "Found " << Mix_GetChunkDecoder(i) << " chunk decoder.";
    }

    //query the actual format that is in use by the opened audio device
    if (Mix_QuerySpec(&frequency, &format, &channels) == 0) {
        BOOST_LOG_SEV(logger, Common::Severity::Critical)
            << "Failed to query audio format that is in use by the current audio device. " << Mix_GetError();
        Mix_CloseAudio();
        Mix_Quit();
        return;
    }
    BOOST_LOG_SEV(logger, Common::Severity::Debug)
        << "Audio device with frequency " << frequency << ", format " << format << " and number of channels " << channels << " opened.";

    initialized = true;
}

Cosmic::Core::AudioSubsystem::~AudioSubsystem() {
    BOOST_LOG_FUNCTION();

    //check if we are initialized
    if (!isInitialized()) {
        BOOST_LOG_SEV(logger, Common::Severity::Debug) << "SDL_mixer library was not initialized.";
        return;
    }

    //close audio device
    BOOST_LOG(logger) << "Closing audio device.";
    Mix_CloseAudio();

    //clean up SDL_mixer library stuff
    BOOST_LOG(logger) << "Cleaning up SDL_mixer library.";
    Mix_Quit();
}

bool Cosmic::Core::AudioSubsystem::isInitialized() const {
    return initialized;
}
<|endoftext|>


<commit_before><commit_msg>Additional tests<commit_after><|endoftext|>


<commit_before>#ifndef STAN_MATH_GPU_CHOLESKY_DECOMPOSE_HPP
#define STAN_MATH_GPU_CHOLESKY_DECOMPOSE_HPP
#ifdef STAN_OPENCL
#include <stan/math/gpu/matrix_gpu.hpp>
#include <stan/math/gpu/kernels/cholesky_decompose.hpp>
#include <stan/math/gpu/multiply.hpp>
#include <stan/math/gpu/multiply_transpose.hpp>
#include <stan/math/gpu/lower_tri_inverse.hpp>
#include <stan/math/gpu/transpose.hpp>
#include <stan/math/gpu/subtract.hpp>
#include <stan/math/gpu/err/check_diagonal_zeros.hpp>
#include <stan/math/gpu/err/check_nan.hpp>
#include <CL/cl.hpp>
#include <algorithm>
#include <cmath>

namespace stan {
namespace math {
inline matrix_gpu cholesky_decompose(matrix_gpu& A, const int min_block);
namespace internal {
inline matrix_gpu cholesky_decompose_recursion(matrix_gpu& A,
                                               const int min_block) {
  matrix_gpu L(A.rows(), A.cols());
  if (A.rows() <= min_block || A.rows() < 100) {
    try {
      opencl_kernels::cholesky_decompose(cl::NDRange(A.rows()),
                                         cl::NDRange(A.rows()), A.buffer(),
                                         L.buffer(), A.rows());
    } catch (const cl::Error& e) {
      check_opencl_error("cholesky_decompose", e);
    }
  } else {
    L = stan::math::cholesky_decompose(A, min_block);
  }
  return L;
}
}  // namespace internal
/**
 * Return the lower-triangular Cholesky factor (i.e., matrix
 * square root) of the specified square, symmetric matrix.
 * The return value \f$L\f$ will be a lower-traingular matrix such that the
 * original matrix \f$A\f$ is given by
 *
\f$A = L \times L^T\f$.
 * The Cholesky decomposition is computed on the GPU. This algorithm is
 * recursive. The matrix is subset into a matrix of size
 *  A.rows() / 2, and if the block size is less than
 * 100 then the cholesky decomposition on the GPU is computed
 * using that submatrix. If block is greater than
 * 100 or min_block then cholesky_decompose is run again
 * with block equal to A.rows() / 2. Once the
 * Cholesky Decomposition is computed, the full matrix cholesky is created
 * by propogating the cholesky forward as given in the reference report below.
 *
 * For a full guide to how this works
 * see the Cholesy decompostion chapter in the  reference report
 *  here.
 * @param A Symmetric matrix on the GPU.
 * @param min_block The minimum block size to execute the cholesky on.
 * @return Square root of matrix on the GPU.
 * @throw std::domain_error if m is not
 *  positive definite (if m has more than 0 elements)
 */
inline matrix_gpu cholesky_decompose(matrix_gpu& A, const int min_block) {
  auto offset = 0;
  auto block = floor(A.rows() / 2);
  // NOTE: The code in this section follows the naming conventions
  // in the report linked in the docs.
  matrix_gpu A_11(block, block);
  // Repeats the blocked cholesky decomposition until the size of the remaining
  // submatrix is smaller or equal to the block size
  if ((offset + block) < (A.rows())) {
    auto block_subset = A.rows() - offset - block;
    matrix_gpu A_21(block_subset, block);
    matrix_gpu A_22(block_subset, block_subset);
    // Copies a block of the input A into A_11
    A_11.sub_block(A, offset, offset, 0, 0, block, block);
    // The following function either calls the
    // blocked cholesky recursively for the submatrix A_11
    // or calls the kernel  directly if the size of the block is small enough
    matrix_gpu L_11
        = stan::math::internal::cholesky_decompose_recursion(A_11, min_block);
    // Copies L_11 back to the input matrix
    A.sub_block(L_11, 0, 0, offset, offset, block, block);
    // Copies a block of the input A into A_21
    auto block_offset = offset + block;
    A_21.sub_block(A, block_offset, offset, 0, 0, block_subset, block);
    // computes A_21*((L_11^-1)^T)
    // and copies the resulting submatrix to the input matrix
    matrix_gpu L_21 = A_21 * transpose(lower_triangular_inverse(L_11));
    A.sub_block(L_21, 0, 0, block_offset, offset, block_subset, block);
    A_22.sub_block(A, block_offset, block_offset, 0, 0, block_subset,
                   block_subset);
    // computes A_22 - L_21*(L_21^T)
    matrix_gpu L_22 = A_22 - multiply_transpose(L_21);
    A.sub_block(L_22, 0, 0, block_offset, block_offset, block_subset,
                block_subset);
    offset += block;
  }
  // Computes the Cholesky factor for the remaining submatrix
  const auto remaining_rows = A.rows() - offset;
  if (remaining_rows > 0) {
    matrix_gpu A_11(remaining_rows, remaining_rows);
    A_11.sub_block(A, offset, offset, 0, 0, remaining_rows, remaining_rows);
    // calculate the cholesky factor for the remaining part of the matrix
    matrix_gpu L_11
        = stan::math::internal::cholesky_decompose_recursion(A_11, min_block);
    A.sub_block(L_11, 0, 0, offset, offset, remaining_rows, remaining_rows);
  }
  check_nan("cholesky_decompose_gpu", "Matrix m", A);
  check_diagonal_zeros("cholesky_decompose_gpu", "Matrix m", A);
  A.zeros<stan::math::TriangularViewGPU::Upper>();
  return A;
}
}  // namespace math
}  // namespace stan

#endif
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 5.0.0-3~16.04.1 (tags/RELEASE_500/final)<commit_after>#ifndef STAN_MATH_GPU_CHOLESKY_DECOMPOSE_HPP
#define STAN_MATH_GPU_CHOLESKY_DECOMPOSE_HPP
#ifdef STAN_OPENCL
#include <stan/math/gpu/matrix_gpu.hpp>
#include <stan/math/gpu/kernels/cholesky_decompose.hpp>
#include <stan/math/gpu/multiply.hpp>
#include <stan/math/gpu/multiply_transpose.hpp>
#include <stan/math/gpu/lower_tri_inverse.hpp>
#include <stan/math/gpu/transpose.hpp>
#include <stan/math/gpu/subtract.hpp>
#include <stan/math/gpu/err/check_diagonal_zeros.hpp>
#include <stan/math/gpu/err/check_nan.hpp>
#include <CL/cl.hpp>
#include <algorithm>
#include <cmath>

namespace stan {
namespace math {
inline matrix_gpu cholesky_decompose(matrix_gpu& A, const int min_block);
namespace internal {
inline matrix_gpu cholesky_decompose_recursion(matrix_gpu& A,
                                               const int min_block) {
  matrix_gpu L(A.rows(), A.cols());
  if (A.rows() <= min_block || A.rows() < 100) {
    try {
      opencl_kernels::cholesky_decompose(cl::NDRange(A.rows()),
                                         cl::NDRange(A.rows()), A.buffer(),
                                         L.buffer(), A.rows());
    } catch (const cl::Error& e) {
      check_opencl_error("cholesky_decompose", e);
    }
  } else {
    L = stan::math::cholesky_decompose(A, min_block);
  }
  return L;
}
}  // namespace internal
/**
 * Return the lower-triangular Cholesky factor (i.e., matrix
 * square root) of the specified square, symmetric matrix.
 * The return value \f$L\f$ will be a lower-traingular matrix such that the
 * original matrix \f$A\f$ is given by
 *
\f$A = L \times L^T\f$.
 * The Cholesky decomposition is computed on the GPU. This algorithm is
 * recursive. The matrix is subset into a matrix of size
 *  A.rows() / 2, and if the block size is less than
 * 100 then the cholesky decomposition on the GPU is computed
 * using that submatrix. If block is greater than
 * 100 or min_block then cholesky_decompose is run
 * again with block equal to A.rows() / 2. Once the
 * Cholesky Decomposition is computed, the full matrix cholesky is created
 * by propogating the cholesky forward as given in the reference report below.
 *
 * For a full guide to how this works
 * see the Cholesy decompostion chapter in the  reference report
 *  here.
 * @param A Symmetric matrix on the GPU.
 * @param min_block The minimum block size to execute the cholesky on.
 * @return Square root of matrix on the GPU.
 * @throw std::domain_error if m is not
 *  positive definite (if m has more than 0 elements)
 */
inline matrix_gpu cholesky_decompose(matrix_gpu& A, const int min_block) {
  auto offset = 0;
  auto block = floor(A.rows() / 2);
  // NOTE: The code in this section follows the naming conventions
  // in the report linked in the docs.
  matrix_gpu A_11(block, block);
  // Repeats the blocked cholesky decomposition until the size of the remaining
  // submatrix is smaller or equal to the block size
  if ((offset + block) < (A.rows())) {
    auto block_subset = A.rows() - offset - block;
    matrix_gpu A_21(block_subset, block);
    matrix_gpu A_22(block_subset, block_subset);
    // Copies a block of the input A into A_11
    A_11.sub_block(A, offset, offset, 0, 0, block, block);
    // The following function either calls the
    // blocked cholesky recursively for the submatrix A_11
    // or calls the kernel  directly if the size of the block is small enough
    matrix_gpu L_11
        = stan::math::internal::cholesky_decompose_recursion(A_11, min_block);
    // Copies L_11 back to the input matrix
    A.sub_block(L_11, 0, 0, offset, offset, block, block);
    // Copies a block of the input A into A_21
    auto block_offset = offset + block;
    A_21.sub_block(A, block_offset, offset, 0, 0, block_subset, block);
    // computes A_21*((L_11^-1)^T)
    // and copies the resulting submatrix to the input matrix
    matrix_gpu L_21 = A_21 * transpose(lower_triangular_inverse(L_11));
    A.sub_block(L_21, 0, 0, block_offset, offset, block_subset, block);
    A_22.sub_block(A, block_offset, block_offset, 0, 0, block_subset,
                   block_subset);
    // computes A_22 - L_21*(L_21^T)
    matrix_gpu L_22 = A_22 - multiply_transpose(L_21);
    A.sub_block(L_22, 0, 0, block_offset, block_offset, block_subset,
                block_subset);
    offset += block;
  }
  // Computes the Cholesky factor for the remaining submatrix
  const auto remaining_rows = A.rows() - offset;
  if (remaining_rows > 0) {
    matrix_gpu A_11(remaining_rows, remaining_rows);
    A_11.sub_block(A, offset, offset, 0, 0, remaining_rows, remaining_rows);
    // calculate the cholesky factor for the remaining part of the matrix
    matrix_gpu L_11
        = stan::math::internal::cholesky_decompose_recursion(A_11, min_block);
    A.sub_block(L_11, 0, 0, offset, offset, remaining_rows, remaining_rows);
  }
  check_nan("cholesky_decompose_gpu", "Matrix m", A);
  check_diagonal_zeros("cholesky_decompose_gpu", "Matrix m", A);
  A.zeros<stan::math::TriangularViewGPU::Upper>();
  return A;
}
}  // namespace math
}  // namespace stan

#endif
#endif
<|endoftext|>


<commit_before>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//

#include "platform/context.hpp"
#include "amdocl/cl_gl_amd.hpp"
#include "amdocl/cl_common.hpp"
#include "platform/commandqueue.hpp"

#include <algorithm>
#include <functional>

#ifdef _WIN32
#include <d3d10_1.h>
#include <dxgi.h>
#include "CL/cl_d3d10.h"
#include "CL/cl_d3d11.h"
#include "CL/cl_dx9_media_sharing.h"
#endif  //_WIN32

namespace amd {

Context::Context(const std::vector<Device*>& devices, const Info& info)
    : devices_(devices),
      info_(info),
      properties_(NULL),
      glenv_(NULL),
      customHostAllocDevice_(NULL) {
  for (const auto& device : devices) {
    device->retain();
    if (customHostAllocDevice_ == NULL && device->customHostAllocator()) {
      customHostAllocDevice_ = device;
    }
    if (device->svmSupport()) {
      svmAllocDevice_.push_back(device);
    }
  }
  if (svmAllocDevice_.size() > 1) {
    // make sure the CPU is the last device to do allocation.
    if ((svmAllocDevice_.front()->type() == CL_DEVICE_TYPE_CPU)) {
      std::swap(svmAllocDevice_.front(), svmAllocDevice_.back());
    }

    uint isFirstDeviceFGSEnabled = svmAllocDevice_.front()->isFineGrainedSystem(true);
    for (auto& dev : svmAllocDevice_) {
      // allocation on fine - grained system incapable device first
      if (isFirstDeviceFGSEnabled && (dev->type() == CL_DEVICE_TYPE_GPU) &&
          (!(dev->isFineGrainedSystem(true)))) {
        std::swap(svmAllocDevice_.front(), dev);
        break;
      }
    }
  }
}

Context::~Context() {
  static const bool VALIDATE_ONLY = false;

  // Dissociate OCL context with any external device
  if (info_.flags_ & (GLDeviceKhr | D3D10DeviceKhr | D3D11DeviceKhr)) {
    std::vector<Device*>::const_iterator it;
    // Loop through all devices
    for (it = devices_.begin(); it != devices_.end(); it++) {
      (*it)->unbindExternalDevice(info_.flags_, info_.hDev_, info_.hCtx_, VALIDATE_ONLY);
    }
  }

  if (properties_ != NULL) {
    delete[] properties_;
  }
  if (glenv_ != NULL) {
    delete glenv_;
    glenv_ = NULL;
  }

  std::for_each(devices_.begin(), devices_.end(), std::mem_fun(&Device::release));
}

int Context::checkProperties(const cl_context_properties* properties, Context::Info* info) {
  cl_platform_id pfmId = 0;
  uint count = 0;

  const struct Element {
    intptr_t name;
    void* ptr;
  }* p = reinterpret_cast<const Element*>(properties);

  // Clear the context infor structure
  ::memset(info, 0, sizeof(Context::Info));

  if (properties == NULL) {
    return CL_SUCCESS;
  }

  // Process all properties
  while (p->name != 0) {
    switch (p->name) {
      case CL_CONTEXT_INTEROP_USER_SYNC:
        if (p->ptr == reinterpret_cast<void*>(CL_TRUE)) {
          info->flags_ |= InteropUserSync;
        }
        break;
#ifdef _WIN32
      case CL_CONTEXT_D3D10_DEVICE_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D10DeviceKhrIdx] = p->ptr;
        info->flags_ |= D3D10DeviceKhr;
        break;
      case CL_CONTEXT_D3D11_DEVICE_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D11DeviceKhrIdx] = p->ptr;
        info->flags_ |= D3D11DeviceKhr;
        break;
      case CL_CONTEXT_ADAPTER_D3D9_KHR:
        if (p->ptr == NULL) {  // not supported for xp
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D9DeviceKhrIdx] = p->ptr;
        info->flags_ |= D3D9DeviceKhr;
        break;
      case CL_CONTEXT_ADAPTER_D3D9EX_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D9DeviceEXKhrIdx] = p->ptr;
        info->flags_ |= D3D9DeviceEXKhr;
        break;
      case CL_CONTEXT_ADAPTER_DXVA_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D9DeviceVAKhrIdx] = p->ptr;
        info->flags_ |= D3D9DeviceVAKhr;
        break;
#endif  //_WIN32

      case CL_EGL_DISPLAY_KHR:
        info->flags_ |= EGLDeviceKhr;

#ifdef _WIN32
      case CL_WGL_HDC_KHR:
#endif  //_WIN32

#if defined(__linux__)
      case CL_GLX_DISPLAY_KHR:
#endif  // linux
        info->hDev_[GLDeviceKhrIdx] = p->ptr;

#if defined(__APPLE__) || defined(__MACOSX)
      case CL_CGL_SHAREGROUP_KHR:
        Unimplemented();
        break;
#endif  //__APPLE__ || MACOS

      case CL_GL_CONTEXT_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR;
        }
        if (p->name == CL_GL_CONTEXT_KHR) {
          info->hCtx_ = p->ptr;
        }
        info->flags_ |= GLDeviceKhr;
        break;
      case CL_CONTEXT_PLATFORM:
        pfmId = reinterpret_cast<cl_platform_id>(p->ptr);
        if ((NULL != pfmId) && (AMD_PLATFORM != pfmId)) {
          return CL_INVALID_VALUE;
        }
        break;
      case CL_CONTEXT_OFFLINE_DEVICES_AMD:
        if (p->ptr != reinterpret_cast<void*>(1)) {
          return CL_INVALID_VALUE;
        }
        // Set the offline device flag
        info->flags_ |= OfflineDevices;
        break;
      case CL_CONTEXT_COMMAND_INTERCEPT_CALLBACK_AMD:
        // Set the command intercept flag
        info->commandIntercept_ = (cl_int(CL_CALLBACK*)(cl_event, cl_int*))p->ptr;
        info->flags_ |= CommandIntercept;
        break;
      default:
        return CL_INVALID_VALUE;
    }
    p++;
    count++;
  }

  info->propertiesSize_ = count * sizeof(Element) + sizeof(intptr_t);
  return CL_SUCCESS;
}

int Context::create(const intptr_t* properties) {
  static const bool VALIDATE_ONLY = false;
  int result = CL_SUCCESS;

  if (properties != NULL) {
    properties_ = new cl_context_properties[info().propertiesSize_ / sizeof(cl_context_properties)];
    if (properties_ == NULL) {
      return CL_OUT_OF_HOST_MEMORY;
    }

    ::memcpy(properties_, properties, info().propertiesSize_);
  }

  // Check if OCL context can be associated with any external device
  if (info_.flags_ & (D3D10DeviceKhr | D3D11DeviceKhr | GLDeviceKhr | D3D9DeviceKhr |
                      D3D9DeviceEXKhr | D3D9DeviceVAKhr)) {
    std::vector<Device*>::const_iterator it;
    // Loop through all devices
    for (it = devices_.begin(); it != devices_.end(); it++) {
      if (!(*it)->bindExternalDevice(info_.flags_, info_.hDev_, info_.hCtx_, VALIDATE_ONLY)) {
        result = CL_INVALID_VALUE;
      }
    }
  }

  // Check if the device binding wasn't successful
  if (result != CL_SUCCESS) {
    if (info_.flags_ & GLDeviceKhr) {
      result = CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR;
    } else if (info_.flags_ & D3D10DeviceKhr) {
      // return CL_INVALID_VALUE; // FIXME_odintsov: CL_INVALID_D3D_INTEROP;
    } else if (info_.flags_ & D3D11DeviceKhr) {
      // return CL_INVALID_VALUE; // FIXME_odintsov: CL_INVALID_D3D_INTEROP;
    } else if (info_.flags_ & (D3D9DeviceKhr | D3D9DeviceEXKhr | D3D9DeviceVAKhr)) {
      // return CL_INVALID_DX9_MEDIA_ADAPTER_KHR;
    }
  } else {
    if (info_.flags_ & GLDeviceKhr) {
      // Init context for GL interop
      if (glenv_ == NULL) {
        HMODULE h = (HMODULE)Os::loadLibrary(
#ifdef _WIN32
            "OpenGL32.dll"
#else   //!_WIN32
            "libGL.so.1"
#endif  //!_WIN32
            );

        if (h && (glenv_ = new GLFunctions(h, (info_.flags_ & Flags::EGLDeviceKhr) != 0))) {
          if (!glenv_->init(reinterpret_cast<intptr_t>(info_.hDev_[GLDeviceKhrIdx]),
                            reinterpret_cast<intptr_t>(info_.hCtx_))) {
            delete glenv_;
            glenv_ = NULL;
            result = CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR;
          }
        }
      }
    }
  }

  return result;
}

void* Context::hostAlloc(size_t size, size_t alignment, bool atomics) const {
  if (customHostAllocDevice_ != NULL) {
    return customHostAllocDevice_->hostAlloc(size, alignment, atomics);
  }
  return AlignedMemory::allocate(size, alignment);
}

void Context::hostFree(void* ptr) const {
  if (customHostAllocDevice_ != NULL) {
    customHostAllocDevice_->hostFree(ptr);
    return;
  }
  AlignedMemory::deallocate(ptr);
}

void* Context::svmAlloc(size_t size, size_t alignment, cl_svm_mem_flags flags) {
  unsigned int numSVMDev = svmAllocDevice_.size();
  if (numSVMDev < 1) {
    return NULL;
  }

  if (svmAllocDevice_.front()->type() == CL_DEVICE_TYPE_CPU) {
    return AlignedMemory::allocate(size, alignment);
  } else {
    void* svmPtrAlloced = NULL;
    void* tempPtr = NULL;

    for (const auto& dev : svmAllocDevice_) {
      if (dev->type() == CL_DEVICE_TYPE_GPU) {
        // check if the device support svm platform atomics,
        // skipped allocation for platform atomics if not supported by this device
        if ((flags & CL_MEM_SVM_ATOMICS) &&
            !(dev->info().svmCapabilities_ & CL_DEVICE_SVM_ATOMICS)) {
          continue;
        }
        svmPtrAlloced = dev->svmAlloc(*this, size, alignment, flags, svmPtrAlloced);
        if (svmPtrAlloced == NULL) {
          return NULL;
        }
      }
    }
    return svmPtrAlloced;
  }
}

void Context::svmFree(void* ptr) const {
  if (svmAllocDevice_.front()->type() == CL_DEVICE_TYPE_CPU) {
    AlignedMemory::deallocate(ptr);
    return;
  }

  for (const auto& dev : svmAllocDevice_) {
    if (dev->type() == CL_DEVICE_TYPE_GPU) {
      dev->svmFree(ptr);
    }
  }
  return;
}

bool Context::containsDevice(const Device* device) const {
  std::vector<Device*>::const_iterator it;

  for (it = devices_.begin(); it != devices_.end(); ++it) {
    if (device == *it || (*it)->isAncestor(device)) {
      return true;
    }
  }
  return false;
}

DeviceQueue* Context::defDeviceQueue(const Device& dev) const {
  std::map<const Device*, DeviceQueueInfo>::const_iterator it = deviceQueues_.find(&dev);
  if (it != deviceQueues_.end()) {
    return it->second.defDeviceQueue_;
  } else {
    return NULL;
  }
}

bool Context::isDevQueuePossible(const Device& dev) {
  return (deviceQueues_[&dev].deviceQueueCnt_ < dev.info().maxOnDeviceQueues_) ? true : false;
}

void Context::addDeviceQueue(const Device& dev, DeviceQueue* queue, bool defDevQueue) {
  DeviceQueueInfo& info = deviceQueues_[&dev];
  info.deviceQueueCnt_++;
  if (defDevQueue) {
    info.defDeviceQueue_ = queue;
  }
}

void Context::removeDeviceQueue(const Device& dev, DeviceQueue* queue) {
  DeviceQueueInfo& info = deviceQueues_[&dev];
  assert((info.deviceQueueCnt_ != 0) && "The device queue map is empty!");
  info.deviceQueueCnt_--;
  if (info.defDeviceQueue_ == queue) {
    info.defDeviceQueue_ = NULL;
  }
}

}  // namespace amd
<commit_msg>P4 to Git Change 1419977 by gandryey@gera-w8 on 2017/06/08 11:16:05<commit_after>//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//

#include "platform/context.hpp"
#include "amdocl/cl_gl_amd.hpp"
#include "amdocl/cl_common.hpp"
#include "platform/commandqueue.hpp"

#include <algorithm>
#include <functional>

#ifdef _WIN32
#include <d3d10_1.h>
#include <dxgi.h>
#include "CL/cl_d3d10.h"
#include "CL/cl_d3d11.h"
#include "CL/cl_dx9_media_sharing.h"
#endif  //_WIN32

namespace amd {

Context::Context(const std::vector<Device*>& devices, const Info& info)
    : devices_(devices),
      info_(info),
      properties_(NULL),
      glenv_(NULL),
      customHostAllocDevice_(NULL) {
  for (const auto& device : devices) {
    device->retain();
    if (customHostAllocDevice_ == NULL && device->customHostAllocator()) {
      customHostAllocDevice_ = device;
    }
    if (device->svmSupport()) {
      svmAllocDevice_.push_back(device);
    }
  }
  if (svmAllocDevice_.size() > 1) {
    // make sure the CPU is the last device to do allocation.
    if ((svmAllocDevice_.front()->type() == CL_DEVICE_TYPE_CPU)) {
      std::swap(svmAllocDevice_.front(), svmAllocDevice_.back());
    }

    uint isFirstDeviceFGSEnabled = svmAllocDevice_.front()->isFineGrainedSystem(true);
    for (auto& dev : svmAllocDevice_) {
      // allocation on fine - grained system incapable device first
      if (isFirstDeviceFGSEnabled && (dev->type() == CL_DEVICE_TYPE_GPU) &&
          (!(dev->isFineGrainedSystem(true)))) {
        std::swap(svmAllocDevice_.front(), dev);
        break;
      }
    }
  }
}

Context::~Context() {
  static const bool VALIDATE_ONLY = false;

  // Dissociate OCL context with any external device
  if (info_.flags_ & (GLDeviceKhr | D3D10DeviceKhr | D3D11DeviceKhr)) {
    std::vector<Device*>::const_iterator it;
    // Loop through all devices
    for (it = devices_.begin(); it != devices_.end(); it++) {
      (*it)->unbindExternalDevice(info_.flags_, info_.hDev_, info_.hCtx_, VALIDATE_ONLY);
    }
  }

  if (properties_ != NULL) {
    delete[] properties_;
  }
  if (glenv_ != NULL) {
    delete glenv_;
    glenv_ = NULL;
  }

  std::for_each(devices_.begin(), devices_.end(), std::mem_fun(&Device::release));

#if defined WITH_LIQUID_FLASH
  lfTerminate();
#endif // WITH_LIQUID_FLASH
}

int Context::checkProperties(const cl_context_properties* properties, Context::Info* info) {
  cl_platform_id pfmId = 0;
  uint count = 0;

  const struct Element {
    intptr_t name;
    void* ptr;
  }* p = reinterpret_cast<const Element*>(properties);

  // Clear the context infor structure
  ::memset(info, 0, sizeof(Context::Info));

  if (properties == NULL) {
    return CL_SUCCESS;
  }

  // Process all properties
  while (p->name != 0) {
    switch (p->name) {
      case CL_CONTEXT_INTEROP_USER_SYNC:
        if (p->ptr == reinterpret_cast<void*>(CL_TRUE)) {
          info->flags_ |= InteropUserSync;
        }
        break;
#ifdef _WIN32
      case CL_CONTEXT_D3D10_DEVICE_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D10DeviceKhrIdx] = p->ptr;
        info->flags_ |= D3D10DeviceKhr;
        break;
      case CL_CONTEXT_D3D11_DEVICE_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D11DeviceKhrIdx] = p->ptr;
        info->flags_ |= D3D11DeviceKhr;
        break;
      case CL_CONTEXT_ADAPTER_D3D9_KHR:
        if (p->ptr == NULL) {  // not supported for xp
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D9DeviceKhrIdx] = p->ptr;
        info->flags_ |= D3D9DeviceKhr;
        break;
      case CL_CONTEXT_ADAPTER_D3D9EX_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D9DeviceEXKhrIdx] = p->ptr;
        info->flags_ |= D3D9DeviceEXKhr;
        break;
      case CL_CONTEXT_ADAPTER_DXVA_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_VALUE;
        }
        info->hDev_[D3D9DeviceVAKhrIdx] = p->ptr;
        info->flags_ |= D3D9DeviceVAKhr;
        break;
#endif  //_WIN32

      case CL_EGL_DISPLAY_KHR:
        info->flags_ |= EGLDeviceKhr;

#ifdef _WIN32
      case CL_WGL_HDC_KHR:
#endif  //_WIN32

#if defined(__linux__)
      case CL_GLX_DISPLAY_KHR:
#endif  // linux
        info->hDev_[GLDeviceKhrIdx] = p->ptr;

#if defined(__APPLE__) || defined(__MACOSX)
      case CL_CGL_SHAREGROUP_KHR:
        Unimplemented();
        break;
#endif  //__APPLE__ || MACOS

      case CL_GL_CONTEXT_KHR:
        if (p->ptr == NULL) {
          return CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR;
        }
        if (p->name == CL_GL_CONTEXT_KHR) {
          info->hCtx_ = p->ptr;
        }
        info->flags_ |= GLDeviceKhr;
        break;
      case CL_CONTEXT_PLATFORM:
        pfmId = reinterpret_cast<cl_platform_id>(p->ptr);
        if ((NULL != pfmId) && (AMD_PLATFORM != pfmId)) {
          return CL_INVALID_VALUE;
        }
        break;
      case CL_CONTEXT_OFFLINE_DEVICES_AMD:
        if (p->ptr != reinterpret_cast<void*>(1)) {
          return CL_INVALID_VALUE;
        }
        // Set the offline device flag
        info->flags_ |= OfflineDevices;
        break;
      case CL_CONTEXT_COMMAND_INTERCEPT_CALLBACK_AMD:
        // Set the command intercept flag
        info->commandIntercept_ = (cl_int(CL_CALLBACK*)(cl_event, cl_int*))p->ptr;
        info->flags_ |= CommandIntercept;
        break;
      default:
        return CL_INVALID_VALUE;
    }
    p++;
    count++;
  }

  info->propertiesSize_ = count * sizeof(Element) + sizeof(intptr_t);
  return CL_SUCCESS;
}

int Context::create(const intptr_t* properties) {
  static const bool VALIDATE_ONLY = false;
  int result = CL_SUCCESS;

  if (properties != NULL) {
    properties_ = new cl_context_properties[info().propertiesSize_ / sizeof(cl_context_properties)];
    if (properties_ == NULL) {
      return CL_OUT_OF_HOST_MEMORY;
    }

    ::memcpy(properties_, properties, info().propertiesSize_);
  }

  // Check if OCL context can be associated with any external device
  if (info_.flags_ & (D3D10DeviceKhr | D3D11DeviceKhr | GLDeviceKhr | D3D9DeviceKhr |
                      D3D9DeviceEXKhr | D3D9DeviceVAKhr)) {
    std::vector<Device*>::const_iterator it;
    // Loop through all devices
    for (it = devices_.begin(); it != devices_.end(); it++) {
      if (!(*it)->bindExternalDevice(info_.flags_, info_.hDev_, info_.hCtx_, VALIDATE_ONLY)) {
        result = CL_INVALID_VALUE;
      }
    }
  }

  // Check if the device binding wasn't successful
  if (result != CL_SUCCESS) {
    if (info_.flags_ & GLDeviceKhr) {
      result = CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR;
    } else if (info_.flags_ & D3D10DeviceKhr) {
      // return CL_INVALID_VALUE; // FIXME_odintsov: CL_INVALID_D3D_INTEROP;
    } else if (info_.flags_ & D3D11DeviceKhr) {
      // return CL_INVALID_VALUE; // FIXME_odintsov: CL_INVALID_D3D_INTEROP;
    } else if (info_.flags_ & (D3D9DeviceKhr | D3D9DeviceEXKhr | D3D9DeviceVAKhr)) {
      // return CL_INVALID_DX9_MEDIA_ADAPTER_KHR;
    }
  } else {
    if (info_.flags_ & GLDeviceKhr) {
      // Init context for GL interop
      if (glenv_ == NULL) {
        HMODULE h = (HMODULE)Os::loadLibrary(
#ifdef _WIN32
            "OpenGL32.dll"
#else   //!_WIN32
            "libGL.so.1"
#endif  //!_WIN32
            );

        if (h && (glenv_ = new GLFunctions(h, (info_.flags_ & Flags::EGLDeviceKhr) != 0))) {
          if (!glenv_->init(reinterpret_cast<intptr_t>(info_.hDev_[GLDeviceKhrIdx]),
                            reinterpret_cast<intptr_t>(info_.hCtx_))) {
            delete glenv_;
            glenv_ = NULL;
            result = CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR;
          }
        }
      }
    }
  }
#if defined WITH_LIQUID_FLASH
  lfInit();
#endif // WITH_LIQUID_FLASH
  return result;
}

void* Context::hostAlloc(size_t size, size_t alignment, bool atomics) const {
  if (customHostAllocDevice_ != NULL) {
    return customHostAllocDevice_->hostAlloc(size, alignment, atomics);
  }
  return AlignedMemory::allocate(size, alignment);
}

void Context::hostFree(void* ptr) const {
  if (customHostAllocDevice_ != NULL) {
    customHostAllocDevice_->hostFree(ptr);
    return;
  }
  AlignedMemory::deallocate(ptr);
}

void* Context::svmAlloc(size_t size, size_t alignment, cl_svm_mem_flags flags) {
  unsigned int numSVMDev = svmAllocDevice_.size();
  if (numSVMDev < 1) {
    return NULL;
  }

  if (svmAllocDevice_.front()->type() == CL_DEVICE_TYPE_CPU) {
    return AlignedMemory::allocate(size, alignment);
  } else {
    void* svmPtrAlloced = NULL;
    void* tempPtr = NULL;

    for (const auto& dev : svmAllocDevice_) {
      if (dev->type() == CL_DEVICE_TYPE_GPU) {
        // check if the device support svm platform atomics,
        // skipped allocation for platform atomics if not supported by this device
        if ((flags & CL_MEM_SVM_ATOMICS) &&
            !(dev->info().svmCapabilities_ & CL_DEVICE_SVM_ATOMICS)) {
          continue;
        }
        svmPtrAlloced = dev->svmAlloc(*this, size, alignment, flags, svmPtrAlloced);
        if (svmPtrAlloced == NULL) {
          return NULL;
        }
      }
    }
    return svmPtrAlloced;
  }
}

void Context::svmFree(void* ptr) const {
  if (svmAllocDevice_.front()->type() == CL_DEVICE_TYPE_CPU) {
    AlignedMemory::deallocate(ptr);
    return;
  }

  for (const auto& dev : svmAllocDevice_) {
    if (dev->type() == CL_DEVICE_TYPE_GPU) {
      dev->svmFree(ptr);
    }
  }
  return;
}

bool Context::containsDevice(const Device* device) const {
  std::vector<Device*>::const_iterator it;

  for (it = devices_.begin(); it != devices_.end(); ++it) {
    if (device == *it || (*it)->isAncestor(device)) {
      return true;
    }
  }
  return false;
}

DeviceQueue* Context::defDeviceQueue(const Device& dev) const {
  std::map<const Device*, DeviceQueueInfo>::const_iterator it = deviceQueues_.find(&dev);
  if (it != deviceQueues_.end()) {
    return it->second.defDeviceQueue_;
  } else {
    return NULL;
  }
}

bool Context::isDevQueuePossible(const Device& dev) {
  return (deviceQueues_[&dev].deviceQueueCnt_ < dev.info().maxOnDeviceQueues_) ? true : false;
}

void Context::addDeviceQueue(const Device& dev, DeviceQueue* queue, bool defDevQueue) {
  DeviceQueueInfo& info = deviceQueues_[&dev];
  info.deviceQueueCnt_++;
  if (defDevQueue) {
    info.defDeviceQueue_ = queue;
  }
}

void Context::removeDeviceQueue(const Device& dev, DeviceQueue* queue) {
  DeviceQueueInfo& info = deviceQueues_[&dev];
  assert((info.deviceQueueCnt_ != 0) && "The device queue map is empty!");
  info.deviceQueueCnt_--;
  if (info.defDeviceQueue_ == queue) {
    info.defDeviceQueue_ = NULL;
  }
}

}  // namespace amd
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//
// --------------------
// Class AliMpLocalBoard
// --------------------
// The class defines the properties of local board
// Author: Ch. Finck, Subatech Nantes

#include "AliMpLocalBoard.h"
#include "AliMpConstants.h"
#include "AliMpIntPair.h"

#include "AliLog.h"

#include <TString.h>
#include <Riostream.h>

/// \cond CLASSIMP
ClassImp(AliMpLocalBoard)
/// \endcond

//_____________________________________________________________________________
AliMpLocalBoard::AliMpLocalBoard(Int_t id, const Char_t* name, Int_t slot)
    : TNamed(name, "mapping trigger local board"),
      fId(id),
      fSlot(slot),
      fTC(true),
      fCrate(),
      fSwitches(false),
      fNotified(true),
      fDEId(false)

{
/// Default constructor
}

//______________________________________________________________________________
AliMpLocalBoard::AliMpLocalBoard(TRootIOCtor* /*ioCtor*/)
    : TNamed(),
      fId(),
      fSlot(),
      fTC(),
      fCrate(),
      fSwitches(),
      fNotified(),
      fDEId()
{
/// Root IO constructor
}

//_____________________________________________________________________________
AliMpLocalBoard::~AliMpLocalBoard()
{
/// Destructor

}

//_____________________________________________________________________________
Int_t AliMpLocalBoard::GetIndex(Int_t chamberId) const
{
/// Return the index from chamver Id.
/// chamberId could range from 10-13 in absolute value
/// chamberId could also range from 0-3 in relative value

   Int_t index = chamberId;

   if ( chamberId >= AliMpConstants::NofTrackingChambers() &&
        chamberId <  AliMpConstants::NofChambers() )
   {
       index -= AliMpConstants::NofTrackingChambers();
   }

   if (index < 0 || index >=  AliMpConstants::NofTriggerChambers() )
   {
     AliError(Form("chamber# %d not a valid trigger chamber Id, [0-3] or [10-13]", chamberId));
     return -1;
   }

   return index;
}

//______________________________________________________________________________
Bool_t AliMpLocalBoard::AddDE(Int_t detElemId)
{
/// Add detection element with given detElemId.
/// Return true if the detection element was added

 if ( HasDEId(detElemId) ) {
    AliWarningStream()
      << "Detection element Id = " << detElemId << " already present."
      << endl;
    return false;
 }

  fDEId.Add(detElemId);
  return true;
}

//______________________________________________________________________________
Int_t AliMpLocalBoard::GetNofDEs() const
{
/// Return the number of detection elements connected to this crate

  return fDEId.GetSize();
}

//______________________________________________________________________________
Int_t  AliMpLocalBoard::GetDEId(Int_t index) const
{
/// Return the detection element by index (in loop)

  return fDEId.GetValue(index);
}

//______________________________________________________________________________
Int_t  AliMpLocalBoard::GetDEIdByChamber(Int_t chamberId) const
{
/// Return the detection element by index (in loop)

  return fDEId.GetValue(GetIndex(chamberId));
}

//______________________________________________________________________________
Bool_t  AliMpLocalBoard::HasDEId(Int_t detElemId) const
{
/// Return true if the detection element Id is present

  return fDEId.HasValue(detElemId);
}

//______________________________________________________________________________
Bool_t AliMpLocalBoard::AddSwitch(Int_t swit)
{
/// Add a swicth for the given local board
/// Return true if switch was added

    if ( swit > 1 ) {
      AliWarningStream()
	  << "Invalid value for switch = " << swit
	  << endl;
      return false;
    }

    fSwitches.Add(swit);
    return true;
}

//______________________________________________________________________________
Int_t AliMpLocalBoard::GetNofSwitches() const
{
/// Return the number switches in this local board

  return fSwitches.GetSize();
}

//______________________________________________________________________________
Int_t  AliMpLocalBoard::GetSwitch(Int_t index) const
{
/// Return switch by index (in loop)

    if (index < fSwitches.GetSize())
	return fSwitches.GetValue(index);
    else
	AliWarning("Switch index too large");

    return -1;
}

//______________________________________________________________________________
AliMpIntPair AliMpLocalBoard::GetPosition() const
{
/// gives position of the local board in (line, col)

    const Char_t* boardName = GetName();
    Int_t iLine = boardName[4] - '0';
    Int_t iCol = boardName[2] - '0';
    if ( iLine == 5 ) --iCol;

    return (AliMpIntPair(iLine, iCol));

}

<commit_msg>GetPosition corrected (Philippe C.)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//
// --------------------
// Class AliMpLocalBoard
// --------------------
// The class defines the properties of local board
// Author: Ch. Finck, Subatech Nantes

#include "AliMpLocalBoard.h"
#include "AliMpConstants.h"
#include "AliMpIntPair.h"

#include "AliLog.h"

#include <TString.h>
#include <Riostream.h>

/// \cond CLASSIMP
ClassImp(AliMpLocalBoard)
/// \endcond

//_____________________________________________________________________________
AliMpLocalBoard::AliMpLocalBoard(Int_t id, const Char_t* name, Int_t slot)
    : TNamed(name, "mapping trigger local board"),
      fId(id),
      fSlot(slot),
      fTC(true),
      fCrate(),
      fSwitches(false),
      fNotified(true),
      fDEId(false)

{
/// Default constructor
}

//______________________________________________________________________________
AliMpLocalBoard::AliMpLocalBoard(TRootIOCtor* /*ioCtor*/)
    : TNamed(),
      fId(),
      fSlot(),
      fTC(),
      fCrate(),
      fSwitches(),
      fNotified(),
      fDEId()
{
/// Root IO constructor
}

//_____________________________________________________________________________
AliMpLocalBoard::~AliMpLocalBoard()
{
/// Destructor

}

//_____________________________________________________________________________
Int_t AliMpLocalBoard::GetIndex(Int_t chamberId) const
{
/// Return the index from chamver Id.
/// chamberId could range from 10-13 in absolute value
/// chamberId could also range from 0-3 in relative value

   Int_t index = chamberId;

   if ( chamberId >= AliMpConstants::NofTrackingChambers() &&
        chamberId <  AliMpConstants::NofChambers() )
   {
       index -= AliMpConstants::NofTrackingChambers();
   }

   if (index < 0 || index >=  AliMpConstants::NofTriggerChambers() )
   {
     AliError(Form("chamber# %d not a valid trigger chamber Id, [0-3] or [10-13]", chamberId));
     return -1;
   }

   return index;
}

//______________________________________________________________________________
Bool_t AliMpLocalBoard::AddDE(Int_t detElemId)
{
/// Add detection element with given detElemId.
/// Return true if the detection element was added

 if ( HasDEId(detElemId) ) {
    AliWarningStream()
      << "Detection element Id = " << detElemId << " already present."
      << endl;
    return false;
 }

  fDEId.Add(detElemId);
  return true;
}

//______________________________________________________________________________
Int_t AliMpLocalBoard::GetNofDEs() const
{
/// Return the number of detection elements connected to this crate

  return fDEId.GetSize();
}

//______________________________________________________________________________
Int_t  AliMpLocalBoard::GetDEId(Int_t index) const
{
/// Return the detection element by index (in loop)

  return fDEId.GetValue(index);
}

//______________________________________________________________________________
Int_t  AliMpLocalBoard::GetDEIdByChamber(Int_t chamberId) const
{
/// Return the detection element by index (in loop)

  return fDEId.GetValue(GetIndex(chamberId));
}

//______________________________________________________________________________
Bool_t  AliMpLocalBoard::HasDEId(Int_t detElemId) const
{
/// Return true if the detection element Id is present

  return fDEId.HasValue(detElemId);
}

//______________________________________________________________________________
Bool_t AliMpLocalBoard::AddSwitch(Int_t swit)
{
/// Add a swicth for the given local board
/// Return true if switch was added

    if ( swit > 1 ) {
      AliWarningStream()
	  << "Invalid value for switch = " << swit
	  << endl;
      return false;
    }

    fSwitches.Add(swit);
    return true;
}

//______________________________________________________________________________
Int_t AliMpLocalBoard::GetNofSwitches() const
{
/// Return the number switches in this local board

  return fSwitches.GetSize();
}

//______________________________________________________________________________
Int_t  AliMpLocalBoard::GetSwitch(Int_t index) const
{
/// Return switch by index (in loop)

    if (index < fSwitches.GetSize())
	return fSwitches.GetValue(index);
    else
	AliWarning("Switch index too large");

    return -1;
}

//______________________________________________________________________________
AliMpIntPair AliMpLocalBoard::GetPosition() const
{
/// gives position of the local board in (line, col)

    const Char_t* boardName = GetName();
    Int_t iLine = boardName[4] - '0';
    Int_t iCol = boardName[2] - '0';

    return (AliMpIntPair(iLine, iCol));
}

<|endoftext|>