Many style changes and code improvements to addons management.
The addons icon is now greyed out in case of an error (and till the list of addons is downloaded, though usually that is done by the time the main gui is shown). Moved synchronisations/threading from addons_manager to network_http. Added 'Synchron' template to hide usage of mutex to provide synchronised accesses to a variable. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7177 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
1c57310b41
commit
ce986d623d
@ -28,94 +28,96 @@
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include "irrXML.h"
|
||||
|
||||
#include "addons/network_http.hpp"
|
||||
#include "addons/zip.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "states_screens/kart_selection.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
|
||||
using namespace irr; /* irrXML which is used to read (not write) xml file,
|
||||
is located in the namespace irr::io.*/
|
||||
using namespace io;
|
||||
AddonsManager* addons_manager = 0;
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
AddonsManager::AddonsManager()
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises the non-online component of the addons manager (i.e. handling
|
||||
* the list of already installed addons). The online component is initialised
|
||||
* later from a separate thread in network_http (once network_http is setup).
|
||||
*/
|
||||
AddonsManager::AddonsManager() : m_state(STATE_INIT)
|
||||
{
|
||||
m_index = -1;
|
||||
int download_state = 0;
|
||||
m_download_state = download_state;
|
||||
pthread_mutex_init(&m_str_mutex, NULL);
|
||||
|
||||
// FIXME: It is _very_ dirty to save the list as a locale file since we have a
|
||||
// function to load it directly in a string.
|
||||
const bool success = download("list");
|
||||
if (!success)
|
||||
{
|
||||
fprintf(stderr, "Downloading 'list' failed\n");
|
||||
}
|
||||
|
||||
std::string xml_file = file_manager->getConfigDir() + "/" + "list";
|
||||
std::cout << "[Addons] Using file '" << xml_file << "'\n";
|
||||
IrrXMLReader* xml = createIrrXMLReader(xml_file.c_str());
|
||||
|
||||
// strings for storing the data we want to get out of the file
|
||||
std::string attribute_name;
|
||||
|
||||
// parse the file until end reached
|
||||
|
||||
while(xml && xml->read())
|
||||
{
|
||||
/*only if it is a node*/
|
||||
if(xml->getNodeType() == EXN_ELEMENT)
|
||||
{
|
||||
if (!strcmp("kart", xml->getNodeName()) || !strcmp("track", xml->getNodeName()))
|
||||
{
|
||||
addons_prop addons;
|
||||
//the unsigned is to remove the compiler warnings, maybe it is a bad idea ?
|
||||
for(unsigned int i = 0; i < xml->getAttributeCount(); i++)
|
||||
{
|
||||
attribute_name = xml->getAttributeName(i);
|
||||
if(attribute_name == "name")
|
||||
{
|
||||
addons.name = xml->getAttributeValue("name");
|
||||
}
|
||||
if(attribute_name == "version")
|
||||
{
|
||||
addons.version = atoi(xml->getAttributeValue("version"));
|
||||
}
|
||||
if(attribute_name == "file")
|
||||
{
|
||||
addons.file = xml->getAttributeValue("file");
|
||||
}
|
||||
if(attribute_name == "description")
|
||||
{
|
||||
addons.description = xml->getAttributeValue("description");
|
||||
}
|
||||
if(attribute_name == "icon")
|
||||
{
|
||||
addons.icon = xml->getAttributeValue("icon");
|
||||
}
|
||||
if(attribute_name == "id")
|
||||
{
|
||||
addons.id = xml->getAttributeValue("id");
|
||||
}
|
||||
}
|
||||
addons.type = xml->getNodeName();
|
||||
addons.installed = false;
|
||||
m_addons_list.push_back(addons);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete xml;
|
||||
|
||||
m_file_installed = file_manager->getConfigDir()
|
||||
+ "/" + "addons_installed.xml";
|
||||
getInstalledAddons();
|
||||
}
|
||||
} // AddonsManager
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This initialises the online portion of the addons manager. It downloads
|
||||
* the list of available addons. This is called by network_http before it
|
||||
* goes into command-receiving mode, so we can't use any asynchronous calls
|
||||
* here (though this is being called from a separate thread anyway, so the
|
||||
* main GUI is not blocked). This function will update the state variable
|
||||
*
|
||||
*/
|
||||
void AddonsManager::initOnline()
|
||||
{
|
||||
if(UserConfigParams::m_verbosity>=3)
|
||||
printf("[addons] Init online addons manager\n");
|
||||
int download_state = 0;
|
||||
m_download_state = download_state;
|
||||
|
||||
// FIXME: It is _very_ dirty to save the list as a locale file
|
||||
// since we have a function to load it directly in a string.
|
||||
if(UserConfigParams::m_verbosity>=3)
|
||||
printf("[addons] Addons manager downloading list\n");
|
||||
if(!network_http->downloadFileSynchron("list"))
|
||||
{
|
||||
m_state.set(STATE_ERROR);
|
||||
return;
|
||||
}
|
||||
if(UserConfigParams::m_verbosity>=3)
|
||||
printf("[addons] Addons manager list downloaded\n");
|
||||
|
||||
std::string xml_file = file_manager->getAddonsFile("list");
|
||||
|
||||
const XMLNode *xml = new XMLNode(xml_file);
|
||||
for(unsigned int i=0; i<xml->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *node = xml->getNode(i);
|
||||
if(node->getName()=="track")
|
||||
{
|
||||
AddonsProp addons(*node);
|
||||
m_addons_list.push_back(addons);
|
||||
}
|
||||
else if(node->getName()=="kart")
|
||||
{
|
||||
AddonsProp addons(*node);
|
||||
m_addons_list.push_back(addons);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Found invalid node '%s' while downloading addons.\n",
|
||||
node->getName().c_str());
|
||||
fprintf(stderr, "Ignored.\n");
|
||||
}
|
||||
} // for i<xml->getNumNodes
|
||||
delete xml;
|
||||
|
||||
m_state.set(STATE_READY);
|
||||
} // initOnline
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns true if the list of online addons has been downloaded. This is
|
||||
* used to grey out the 'addons' entry till a network connections could be
|
||||
* established.
|
||||
*/
|
||||
bool AddonsManager::onlineReady()
|
||||
{
|
||||
return m_state.get()==STATE_READY;
|
||||
} // onlineReady
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AddonsManager::resetIndex()
|
||||
{
|
||||
@ -131,7 +133,7 @@ void AddonsManager::getInstalledAddons()
|
||||
|
||||
std::cout << "[Addons] Loading an xml file for installed addons: ";
|
||||
std::cout << m_file_installed << std::endl;
|
||||
IrrXMLReader* xml = createIrrXMLReader(m_file_installed.c_str());
|
||||
io::IrrXMLReader* xml = io::createIrrXMLReader(m_file_installed.c_str());
|
||||
|
||||
// parse the file until end reached
|
||||
|
||||
@ -142,12 +144,14 @@ void AddonsManager::getInstalledAddons()
|
||||
int version = 0;
|
||||
switch(xml->getNodeType())
|
||||
{
|
||||
case EXN_ELEMENT:
|
||||
case io::EXN_ELEMENT:
|
||||
{
|
||||
if (!strcmp("kart", xml->getNodeName()) || !strcmp("track", xml->getNodeName()))
|
||||
if (!strcmp("kart", xml->getNodeName()) ||
|
||||
!strcmp("track", xml->getNodeName()) )
|
||||
{
|
||||
std::cout << xml->getAttributeCount() << std::endl;
|
||||
//the unsigned is to remove the compiler warnings, maybe it is a bad idea ?
|
||||
//the unsigned is to remove the compiler warnings,
|
||||
// maybe it is a bad idea ?
|
||||
for(unsigned int i = 0; i < xml->getAttributeCount(); i++)
|
||||
{
|
||||
attribute_name = xml->getAttributeName(i);
|
||||
@ -166,18 +170,19 @@ void AddonsManager::getInstalledAddons()
|
||||
}
|
||||
if(selectId(id))
|
||||
{
|
||||
m_addons_list[m_index].installed = true;
|
||||
m_addons_list[m_index].installed_version = version;
|
||||
std::cout << "[Addons] An addon is already installed: " << id << std::endl;
|
||||
m_addons_list[m_index].m_installed = true;
|
||||
m_addons_list[m_index].m_installed_version = version;
|
||||
std::cout << "[Addons] An addon is already installed: "
|
||||
<< id << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
addons_prop addons;
|
||||
addons.type = xml->getNodeName();
|
||||
addons.name = name;
|
||||
addons.installed_version = version;
|
||||
addons.version = version;
|
||||
addons.installed = true;
|
||||
AddonsProp addons;
|
||||
addons.m_type = xml->getNodeName();
|
||||
addons.m_name = name;
|
||||
addons.m_installed_version = version;
|
||||
addons.m_version = version;
|
||||
addons.m_installed = true;
|
||||
m_addons_list.push_back(addons);
|
||||
}
|
||||
}
|
||||
@ -208,12 +213,12 @@ bool AddonsManager::nextType(std::string type)
|
||||
{
|
||||
while(next())
|
||||
{
|
||||
if(m_addons_list[m_index].type == type)
|
||||
if(m_addons_list[m_index].m_type == type)
|
||||
return true;
|
||||
}
|
||||
while(next())
|
||||
{
|
||||
if(m_addons_list[m_index].type == type)
|
||||
if(m_addons_list[m_index].m_type == type)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -236,12 +241,12 @@ bool AddonsManager::previousType(std::string type)
|
||||
{
|
||||
while(previous())
|
||||
{
|
||||
if(m_addons_list[m_index].type == type)
|
||||
if(m_addons_list[m_index].m_type == type)
|
||||
return true;
|
||||
}
|
||||
while(previous())
|
||||
{
|
||||
if(m_addons_list[m_index].type == type)
|
||||
if(m_addons_list[m_index].m_type == type)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -253,7 +258,7 @@ bool AddonsManager::select(std::string name)
|
||||
//the unsigned is to remove the compiler warnings, maybe it is a bad idea ?
|
||||
for(unsigned int i = 0; i < m_addons_list.size(); i++)
|
||||
{
|
||||
if(m_addons_list[i].name == name)
|
||||
if(m_addons_list[i].m_name == name)
|
||||
{
|
||||
m_index = i;
|
||||
return true;
|
||||
@ -265,21 +270,20 @@ bool AddonsManager::select(std::string name)
|
||||
// ----------------------------------------------------------------------------
|
||||
bool AddonsManager::selectId(std::string id)
|
||||
{
|
||||
//the unsigned is to remove the compiler warnings, maybe it is a bad idea ?
|
||||
for(unsigned int i = 0; i < m_addons_list.size(); i++)
|
||||
{
|
||||
if(m_addons_list[i].m_id == id)
|
||||
{
|
||||
if(m_addons_list[i].id == id)
|
||||
{
|
||||
m_index = i;
|
||||
return true;
|
||||
}
|
||||
m_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} // selectId
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/* FIXME : remove this function */
|
||||
addons_prop AddonsManager::getAddons()
|
||||
const AddonsManager::AddonsProp& AddonsManager::getAddons() const
|
||||
{
|
||||
return m_addons_list[m_index];
|
||||
} // getAddons
|
||||
@ -288,7 +292,7 @@ addons_prop AddonsManager::getAddons()
|
||||
std::string AddonsManager::getVersionAsStr() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << m_addons_list[m_index].version;
|
||||
os << m_addons_list[m_index].m_version;
|
||||
return os.str();
|
||||
} // getVersionAsStr
|
||||
|
||||
@ -296,25 +300,25 @@ std::string AddonsManager::getVersionAsStr() const
|
||||
std::string AddonsManager::getIdAsStr() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << m_addons_list[m_index].id;
|
||||
os << m_addons_list[m_index].m_id;
|
||||
return os.str();
|
||||
} // getIdAsStr
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int AddonsManager::getInstalledVersion() const
|
||||
{
|
||||
if(m_addons_list[m_index].installed)
|
||||
return m_addons_list[m_index].installed_version;
|
||||
if(m_addons_list[m_index].m_installed)
|
||||
return m_addons_list[m_index].m_installed_version;
|
||||
return 0;
|
||||
} // getInstalledVersion
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string AddonsManager::getInstalledVersionAsStr() const
|
||||
{
|
||||
if(m_addons_list[m_index].installed)
|
||||
if(m_addons_list[m_index].m_installed)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << m_addons_list[m_index].installed_version;
|
||||
os << m_addons_list[m_index].m_installed_version;
|
||||
return os.str();
|
||||
}
|
||||
return "";
|
||||
@ -325,14 +329,12 @@ void AddonsManager::install()
|
||||
{
|
||||
//download of the addons file
|
||||
|
||||
pthread_mutex_lock(&m_str_mutex);
|
||||
m_str_state = "Downloading...";
|
||||
pthread_mutex_unlock(&m_str_mutex);
|
||||
|
||||
std::string file = "file/" + m_addons_list[m_index].file;
|
||||
bool success = download(file,
|
||||
m_addons_list[m_index].name, &m_download_state);
|
||||
|
||||
std::string file = "file/" + m_addons_list[m_index].m_file;
|
||||
network_http->downloadFileAsynchron(file, m_addons_list[m_index].m_name);
|
||||
//FIXME , &m_download_state);
|
||||
bool success=true;
|
||||
if (!success)
|
||||
{
|
||||
// TODO: show a message in the interface
|
||||
@ -340,34 +342,32 @@ void AddonsManager::install()
|
||||
return;
|
||||
}
|
||||
|
||||
file_manager->checkAndCreateDirForAddons(m_addons_list[m_index].name,
|
||||
m_addons_list[m_index].type + "s/");
|
||||
file_manager->checkAndCreateDirForAddons(m_addons_list[m_index].m_name,
|
||||
m_addons_list[m_index].m_type + "s/");
|
||||
|
||||
//extract the zip in the addons folder called like the addons name
|
||||
std::string dest_file =file_manager->getAddonsDir() + "/" + "data" + "/" +
|
||||
m_addons_list[m_index].type + "s/" +
|
||||
m_addons_list[m_index].name + "/" ;
|
||||
std::string from = file_manager->getConfigDir() + "/" + m_addons_list[m_index].name;
|
||||
m_addons_list[m_index].m_type + "s/" +
|
||||
m_addons_list[m_index].m_name + "/" ;
|
||||
std::string from = file_manager->getConfigDir() + "/"
|
||||
+ m_addons_list[m_index].m_name;
|
||||
std::string to = dest_file;
|
||||
|
||||
pthread_mutex_lock(&m_str_mutex);
|
||||
m_str_state = "Unzip the addons...";
|
||||
pthread_mutex_unlock(&m_str_mutex);
|
||||
|
||||
success = extract_zip(from, to);
|
||||
if (!success)
|
||||
{
|
||||
// TODO: show a message in the interface
|
||||
std::cerr << "[Addons] Failed to unzip '" << from << "' to '" << to << "'\n";
|
||||
std::cerr << "[Addons] Failed to unzip '" << from << "' to '"
|
||||
<< to << "'\n";
|
||||
return;
|
||||
}
|
||||
|
||||
m_addons_list[m_index].installed = true;
|
||||
m_addons_list[m_index].installed_version = m_addons_list[m_index].version;
|
||||
m_addons_list[m_index].m_installed = true;
|
||||
m_addons_list[m_index].m_installed_version = m_addons_list[m_index].m_version;
|
||||
|
||||
pthread_mutex_lock(&m_str_mutex);
|
||||
m_str_state = "Reloading kart list...";
|
||||
pthread_mutex_unlock(&m_str_mutex);
|
||||
saveInstalled();
|
||||
} // install
|
||||
|
||||
@ -385,15 +385,15 @@ void AddonsManager::saveInstalled()
|
||||
|
||||
for(unsigned int i = 0; i < m_addons_list.size(); i++)
|
||||
{
|
||||
if(m_addons_list[i].installed)
|
||||
if(m_addons_list[i].m_installed)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << m_addons_list[i].installed_version;
|
||||
os << m_addons_list[i].m_installed_version;
|
||||
|
||||
//transform the version (int) in string
|
||||
xml_installed << "<"+ m_addons_list[i].type +" name=\"" +
|
||||
m_addons_list[i].name + "\" id=\"" +
|
||||
m_addons_list[i].id + "\"";
|
||||
xml_installed << "<"+ m_addons_list[i].m_type +" name=\"" +
|
||||
m_addons_list[i].m_name + "\" id=\"" +
|
||||
m_addons_list[i].m_id + "\"";
|
||||
xml_installed << " version=\"" + os.str() + "\" />" << std::endl;
|
||||
}
|
||||
}
|
||||
@ -406,13 +406,14 @@ void AddonsManager::saveInstalled()
|
||||
// ----------------------------------------------------------------------------
|
||||
void AddonsManager::uninstall()
|
||||
{
|
||||
std::cout << "[Addons] Uninstalling <" << m_addons_list[m_index].name << ">\n";
|
||||
std::cout << "[Addons] Uninstalling <"
|
||||
<< m_addons_list[m_index].m_name << ">\n";
|
||||
|
||||
m_addons_list[m_index].installed = false;
|
||||
m_addons_list[m_index].m_installed = false;
|
||||
//write the xml file with the informations about installed karts
|
||||
std::string dest_file = file_manager->getAddonsDir() + "/" + "data" + "/" +
|
||||
m_addons_list[m_index].type + "s/" +
|
||||
m_addons_list[m_index].name + "/";
|
||||
m_addons_list[m_index].m_type + "s/" +
|
||||
m_addons_list[m_index].m_name + "/";
|
||||
|
||||
//remove the addons directory
|
||||
file_manager->removeDirectory(dest_file.c_str());
|
||||
@ -423,20 +424,15 @@ void AddonsManager::uninstall()
|
||||
// ----------------------------------------------------------------------------
|
||||
int AddonsManager::getDownloadState()
|
||||
{
|
||||
pthread_mutex_lock(&download_mutex);
|
||||
int value = m_download_state;
|
||||
pthread_mutex_unlock(&download_mutex);
|
||||
return value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
std::string AddonsManager::getDownloadStateAsStr() const
|
||||
const std::string& AddonsManager::getDownloadStateAsStr() const
|
||||
{
|
||||
pthread_mutex_lock(&m_str_mutex);
|
||||
std::string value = m_str_state;
|
||||
pthread_mutex_unlock(&m_str_mutex);
|
||||
return value;
|
||||
return m_str_state;
|
||||
} // getDownloadStateAsStr
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -22,43 +22,70 @@
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <pthread.h>
|
||||
#include <vector>
|
||||
|
||||
struct addons_prop
|
||||
{
|
||||
std::string name;
|
||||
int version;
|
||||
int installed_version;
|
||||
std::string description;
|
||||
std::string icon;
|
||||
std::string file;
|
||||
std::string id;
|
||||
bool installed;
|
||||
std::string type;
|
||||
};
|
||||
#include "io/xml_node.hpp"
|
||||
#include "utils/synchronised.hpp"
|
||||
|
||||
class AddonsManager
|
||||
{
|
||||
class AddonsProp
|
||||
{
|
||||
public:
|
||||
std::string m_name;
|
||||
int m_version;
|
||||
int m_installed_version;
|
||||
std::string m_description;
|
||||
std::string m_icon;
|
||||
std::string m_file;
|
||||
std::string m_id;
|
||||
bool m_installed;
|
||||
std::string m_type;
|
||||
AddonsProp() {};
|
||||
AddonsProp(const XMLNode &xml)
|
||||
{
|
||||
m_installed = false;
|
||||
m_installed_version = 0;
|
||||
m_type = xml.getName();
|
||||
m_name = ""; xml.get("name", &m_name );
|
||||
m_version = 0 ; xml.get("version", &m_version );
|
||||
m_file = ""; xml.get("file", &m_file );
|
||||
m_description = ""; xml.get("description", &m_description);
|
||||
m_icon = ""; xml.get("icon", &m_icon );
|
||||
m_id = ""; xml.get("id", &m_id );
|
||||
}; // AddonsProp(const XML&)
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<addons_prop> m_addons_list;
|
||||
std::vector<AddonsProp> m_addons_list;
|
||||
int m_index;
|
||||
std::string m_file_installed;
|
||||
void saveInstalled();
|
||||
void getInstalledAddons();
|
||||
std::string m_type;
|
||||
int m_download_state;
|
||||
mutable pthread_mutex_t m_str_mutex;
|
||||
std::string m_str_state;
|
||||
public:
|
||||
AddonsManager();
|
||||
std::string m_str_state;
|
||||
|
||||
/** Which state the addons manager is:
|
||||
* INIT: Waiting to download the list of addons.
|
||||
* READY: List is downloaded, manager is ready.
|
||||
* ERROR: Error downloading the list, no addons available. */
|
||||
enum STATE_TYPE {STATE_INIT, STATE_READY, STATE_ERROR};
|
||||
// Synchronise the state between threads (e.g. GUI and update thread)
|
||||
Synchronised<STATE_TYPE> m_state;
|
||||
|
||||
public:
|
||||
AddonsManager();
|
||||
|
||||
void initOnline();
|
||||
bool onlineReady();
|
||||
/** Select the next addons in the addons list. */
|
||||
bool next();
|
||||
/** Select the next addons in the addons list. */
|
||||
bool previous();
|
||||
|
||||
/** Get all the selected addon parameters. */
|
||||
addons_prop getAddons();
|
||||
const AddonsProp &getAddons() const;
|
||||
|
||||
/** Select an addon with it name. */
|
||||
bool select(std::string);
|
||||
@ -68,14 +95,14 @@ class AddonsManager
|
||||
|
||||
/** Get the name of the selected addon. */
|
||||
const std::string &getName() const
|
||||
{ return m_addons_list[m_index].name; };
|
||||
{ return m_addons_list[m_index].m_name; };
|
||||
|
||||
/** Get the version of the selected addon. */
|
||||
int getVersion() const { return m_addons_list[m_index].version; };
|
||||
int getVersion() const { return m_addons_list[m_index].m_version; };
|
||||
|
||||
/** Get the path of the addon icon. */
|
||||
const std::string &getIcon() const
|
||||
{ return m_addons_list[m_index].icon; };
|
||||
{ return m_addons_list[m_index].m_icon; };
|
||||
|
||||
/** Get the version of the selected addon as a string. */
|
||||
std::string getVersionAsStr() const;
|
||||
@ -92,10 +119,10 @@ class AddonsManager
|
||||
|
||||
/** Get the description of the selected addons. */
|
||||
const std::string &getDescription() const
|
||||
{ return m_addons_list[m_index].description; };
|
||||
{ return m_addons_list[m_index].m_description; };
|
||||
|
||||
const std::string &getType() const
|
||||
{ return m_addons_list[m_index].type; };
|
||||
{ return m_addons_list[m_index].m_type; };
|
||||
/** Install or upgrade the selected addon. */
|
||||
void install();
|
||||
|
||||
@ -106,15 +133,15 @@ class AddonsManager
|
||||
void resetIndex();
|
||||
|
||||
/** Get the state of the addon: if it is installed or not.*/
|
||||
bool isInstalledAsBool() const
|
||||
{ return m_addons_list[m_index].installed; };
|
||||
bool isInstalled() const
|
||||
{ return m_addons_list[m_index].m_installed; };
|
||||
|
||||
bool nextType(std::string type);
|
||||
bool previousType(std::string type);
|
||||
int getDownloadState();
|
||||
|
||||
/** Get the install state (if it is the download, unzip...)*/
|
||||
std::string getDownloadStateAsStr() const;
|
||||
const std::string& getDownloadStateAsStr() const;
|
||||
|
||||
};
|
||||
extern AddonsManager *addons_manager;
|
||||
|
@ -42,22 +42,21 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
pthread_mutex_t download_mutex;
|
||||
NetworkHttp * network_http = 0;
|
||||
NetworkHttp *network_http;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Create a thread that handles all network functions independent of the
|
||||
* main program.
|
||||
* main program. NetworkHttp supports only a single thread (i.e. it's not
|
||||
* possible to download two addons at the same time), which makes handling
|
||||
* and synchronisation a lot easier (otherwise all objects using this object
|
||||
* would need an additional handle to get the right data back).
|
||||
* This separate thread is running in NetworkHttp::mainLoop, and is being
|
||||
* waken up if a command is issued (e.g. using downloadFileAsynchronous).
|
||||
*/
|
||||
NetworkHttp::NetworkHttp()
|
||||
NetworkHttp::NetworkHttp() : m_news(""), m_progress(-1.0f)
|
||||
{
|
||||
pthread_mutex_init(&m_mutex_news, NULL);
|
||||
m_news_message = "";
|
||||
|
||||
pthread_mutex_init(&m_mutex_command, NULL);
|
||||
pthread_cond_init(&m_cond_command, NULL);
|
||||
m_command = HC_SLEEP;
|
||||
m_abort = false;
|
||||
|
||||
pthread_attr_t attr;
|
||||
@ -76,16 +75,21 @@ NetworkHttp::NetworkHttp()
|
||||
void *NetworkHttp::mainLoop(void *obj)
|
||||
{
|
||||
NetworkHttp *me=(NetworkHttp*)obj;
|
||||
|
||||
// FIXME: this needs better error handling!
|
||||
me->checkNewServer();
|
||||
me->updateNews();
|
||||
// Allow this thread to be cancelled anytime
|
||||
// FIXME: this mechanism will later not be necessary anymore!
|
||||
|
||||
// Initialise the online portion of the addons manager.
|
||||
addons_manager->initOnline();
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
|
||||
// Wait in the main loop till a command is received
|
||||
// (atm only QUIT is used).
|
||||
pthread_mutex_lock(&me->m_mutex_command);
|
||||
me->m_command = HC_SLEEP;
|
||||
while(1)
|
||||
{
|
||||
pthread_cond_wait(&me->m_cond_command, &me->m_mutex_command);
|
||||
@ -99,8 +103,12 @@ void *NetworkHttp::mainLoop(void *obj)
|
||||
case HC_NEWS:
|
||||
me->updateNews();
|
||||
break;
|
||||
case HC_DOWNLOAD_FILE:
|
||||
me->downloadFileInternal();
|
||||
} // switch(m_command)
|
||||
me->m_command = HC_SLEEP;
|
||||
} // while !m_abort
|
||||
pthread_mutex_unlock(&me->m_mutex_command);
|
||||
return NULL;
|
||||
} // mainLoop
|
||||
|
||||
@ -121,7 +129,6 @@ NetworkHttp::~NetworkHttp()
|
||||
void *result;
|
||||
pthread_join(m_thread_id, &result);
|
||||
|
||||
pthread_mutex_destroy(&m_mutex_news);
|
||||
pthread_mutex_destroy(&m_mutex_command);
|
||||
pthread_cond_destroy(&m_cond_command);
|
||||
} // ~NetworkHttp
|
||||
@ -132,7 +139,7 @@ NetworkHttp::~NetworkHttp()
|
||||
*/
|
||||
void NetworkHttp::checkNewServer()
|
||||
{
|
||||
std::string newserver = downloadToStr("redirect");
|
||||
std::string newserver = downloadToStrInternal("redirect");
|
||||
if (newserver != "")
|
||||
{
|
||||
newserver.replace(newserver.find("\n"), 1, "");
|
||||
@ -158,14 +165,10 @@ void NetworkHttp::checkNewServer()
|
||||
*/
|
||||
void NetworkHttp::updateNews()
|
||||
{
|
||||
const std::string tmp_str = downloadToStr("news");
|
||||
// Only lock the actual assignment, not the downloading!
|
||||
const std::string tmp_str = downloadToStrInternal("news");
|
||||
m_news.set(tmp_str);
|
||||
|
||||
pthread_mutex_lock(&m_mutex_news);
|
||||
{
|
||||
// Only lock the actual assignment, not the downloading!
|
||||
m_news_message = tmp_str;
|
||||
}
|
||||
pthread_mutex_unlock(&m_mutex_news);
|
||||
} // updateNews
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -174,30 +177,28 @@ void NetworkHttp::updateNews()
|
||||
*/
|
||||
const std::string NetworkHttp::getNewsMessage() const
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex_news);
|
||||
const std::string tmp_str = m_news_message;
|
||||
pthread_mutex_unlock(&m_mutex_news);
|
||||
return tmp_str;
|
||||
return m_news.get();
|
||||
} // getNewsMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
size_t NetworkHttp::writeStr(char ptr [], size_t size, size_t nb_char, std::string * stream)
|
||||
size_t NetworkHttp::writeStr(char ptr [], size_t size, size_t nb_char,
|
||||
std::string * stream)
|
||||
{
|
||||
static std::string str = std::string(ptr);
|
||||
*stream = str;
|
||||
*stream = std::string(ptr);
|
||||
|
||||
//needed, otherwise, the download failed
|
||||
return nb_char;
|
||||
}
|
||||
} // writeStr
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
std::string NetworkHttp::downloadToStr(std::string url)
|
||||
std::string NetworkHttp::downloadToStrInternal(std::string url)
|
||||
{
|
||||
CURL *session = curl_easy_init();
|
||||
|
||||
std::string full_url = (std::string)UserConfigParams::m_server_addons + "/" + url;
|
||||
std::string full_url = (std::string)UserConfigParams::m_server_addons
|
||||
+ "/" + url;
|
||||
curl_easy_setopt(session, CURLOPT_URL, full_url.c_str());
|
||||
|
||||
std::string fout;
|
||||
@ -213,39 +214,33 @@ std::string NetworkHttp::downloadToStr(std::string url)
|
||||
|
||||
if (success == 0) return fout;
|
||||
else return "";
|
||||
}
|
||||
} // downloadToStrInternal
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Download a file. The file name isn't absolute, the server in the config
|
||||
* will be added to file.
|
||||
* \param progress_data is used to have the state of the download (in %)
|
||||
*/
|
||||
bool download(std::string file, const std::string &save, int * progress_data)
|
||||
bool NetworkHttp::downloadFileInternal()
|
||||
{
|
||||
m_progress.set(0.0f);
|
||||
|
||||
CURL *session = curl_easy_init();
|
||||
std::string full_url = (std::string)UserConfigParams::m_server_addons + "/" + file;
|
||||
std::string full_url = (std::string)UserConfigParams::m_server_addons
|
||||
+ "/" + m_file;
|
||||
curl_easy_setopt(session, CURLOPT_URL, full_url.c_str());
|
||||
FILE * fout;
|
||||
if(save != "")
|
||||
fout = fopen((file_manager->getAddonsDir() + "/" + save).c_str(), "w");
|
||||
else
|
||||
fout = fopen((file_manager->getAddonsDir() + "/" + file).c_str(), "w");
|
||||
|
||||
FILE * fout = fopen(file_manager->getAddonsFile(m_save_filename).c_str(),
|
||||
"w");
|
||||
|
||||
//from and out
|
||||
curl_easy_setopt(session, CURLOPT_WRITEDATA, fout);
|
||||
curl_easy_setopt(session, CURLOPT_WRITEDATA, fout );
|
||||
curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, fwrite);
|
||||
|
||||
//init the mutex for the progress function
|
||||
pthread_mutex_init(&download_mutex, NULL);
|
||||
|
||||
curl_easy_setopt(session, CURLOPT_PROGRESSFUNCTION, &progressDownload);
|
||||
//needed, else, the progress function doesn't work
|
||||
|
||||
curl_easy_setopt(session, CURLOPT_PROGRESSFUNCTION,
|
||||
&NetworkHttp::progressDownload);
|
||||
// Necessary, oyherwise the progress function doesn't work
|
||||
curl_easy_setopt(session, CURLOPT_NOPROGRESS, 0);
|
||||
|
||||
//to update the progress bar
|
||||
curl_easy_setopt(session, CURLOPT_PROGRESSDATA, progress_data);
|
||||
|
||||
|
||||
int success = curl_easy_perform(session);
|
||||
|
||||
//close the file where we downloaded the content
|
||||
@ -253,30 +248,79 @@ bool download(std::string file, const std::string &save, int * progress_data)
|
||||
|
||||
//stop curl
|
||||
curl_easy_cleanup(session);
|
||||
|
||||
return (success == 0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
m_progress.set( (success==CURLE_OK) ? 1.0f : -1.0f );
|
||||
return success==CURLE_OK;
|
||||
} // downloadFileInternal
|
||||
|
||||
//FIXME : this way is a bit ugly but the simplest at the moment
|
||||
int time_last_print = 0;
|
||||
int progressDownload (void *clientp, float dltotal, float dlnow,
|
||||
float ultotal, float ulnow)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** External interface to download a file synchronously, i.e. it will only
|
||||
* return once the download is complete.
|
||||
* \param file The file from the server to download.
|
||||
* \param save The name to save the downloaded file under. Defaults to
|
||||
* the name given in file.
|
||||
*/
|
||||
bool NetworkHttp::downloadFileSynchron(const std::string &file,
|
||||
const std::string &save)
|
||||
{
|
||||
int progress = (int)(dlnow/dltotal*100);
|
||||
if(isnan(dlnow/dltotal*100))
|
||||
progress = 0;
|
||||
pthread_mutex_lock(&download_mutex);
|
||||
if(clientp != NULL)
|
||||
m_file = file;
|
||||
m_save_filename = (save!="") ? save : file;
|
||||
|
||||
return downloadFileInternal();
|
||||
} // downloadFileSynchron
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** External interface to download a file asynchronously. This will wake up
|
||||
* the thread and schedule it to download the file. The calling program has
|
||||
* to poll using getProgress() to find out if the download has finished.
|
||||
* \param file The file from the server to download.
|
||||
* \param save The name to save the downloaded file under. Defaults to
|
||||
* the name given in file.
|
||||
*/
|
||||
void NetworkHttp::downloadFileAsynchron(const std::string &file,
|
||||
const std::string &save)
|
||||
{
|
||||
m_progress.set(0.0f);
|
||||
m_file = file;
|
||||
m_save_filename = (save!="") ? save : file;
|
||||
|
||||
// Wake up the network http thread
|
||||
pthread_mutex_lock(&m_mutex_command);
|
||||
{
|
||||
int * progress_data = (int*)clientp;
|
||||
*progress_data = progress;
|
||||
m_command = HC_DOWNLOAD_FILE;
|
||||
pthread_cond_signal(&m_cond_command);
|
||||
}
|
||||
pthread_mutex_unlock(&download_mutex);
|
||||
pthread_mutex_unlock(&m_mutex_command);
|
||||
} // downloadFileAsynchron
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Callback function from curl: inform about progress.
|
||||
* \param clientp
|
||||
* \param download_total Total size of data to download.
|
||||
* \param download_now How much has been downloaded so far.
|
||||
* \param upload_total Total amount of upload.
|
||||
* \param upload_now How muc has been uploaded so far.
|
||||
*/
|
||||
int NetworkHttp::progressDownload(void *clientp,
|
||||
float download_total, float download_now,
|
||||
float upload_total, float upload_now)
|
||||
{
|
||||
float f;
|
||||
if(download_now < download_total)
|
||||
{
|
||||
f = download_now / download_total;
|
||||
// In case of floating point rouding errors make sure that
|
||||
// 1.0 is only reached when downloadFileInternal is finished
|
||||
if (f>=1.0f) f=0.99f;
|
||||
}
|
||||
else
|
||||
f=1.0f;
|
||||
network_http->m_progress.set(f);
|
||||
|
||||
static int time_last_print=0;
|
||||
if(time_last_print > 10)
|
||||
{
|
||||
std::cout << "Download progress: " << progress << "%" << std::endl;
|
||||
std::cout << "Download progress: " << f << "%" << std::endl;
|
||||
time_last_print = 0;
|
||||
}
|
||||
else
|
||||
@ -284,5 +328,15 @@ int progressDownload (void *clientp, float dltotal, float dlnow,
|
||||
time_last_print += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // progressDownload
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the progress of a download that has been started.
|
||||
* \return <0 in case of an error, between 0 and smaller than 1 while the
|
||||
* download is in progress, and 1.0f if the download has finished.
|
||||
*/
|
||||
float NetworkHttp::getProgress() const
|
||||
{
|
||||
return m_progress.get();
|
||||
} // getProgress
|
||||
#endif
|
||||
|
@ -23,33 +23,44 @@
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
|
||||
#include "utils/synchronised.hpp"
|
||||
|
||||
class NetworkHttp
|
||||
{
|
||||
public:
|
||||
/** List of 'http commands' for this object:
|
||||
* HC_SLEEP: No command, sleep
|
||||
* HC_INIT: Object is being initialised
|
||||
* HC_DOWNLOAD_FILE : download a file
|
||||
* HC_QUIT: Stop loop and terminate thread.
|
||||
* HC_NEWS: Update the news
|
||||
*/
|
||||
enum HttpCommands {HC_SLEEP,
|
||||
HC_QUIT,
|
||||
HC_INIT,
|
||||
HC_DOWNLOAD_FILE,
|
||||
HC_NEWS } ;
|
||||
private:
|
||||
|
||||
/** The news message from the server. This is guarded by m_mutex_news. */
|
||||
std::string m_news_message;
|
||||
|
||||
/** A mutex for accessing m_news_message. Exclude this so that
|
||||
* getter can be declared const. */
|
||||
mutable pthread_mutex_t m_mutex_news;
|
||||
Synchronised<std::string> m_news;
|
||||
|
||||
/** Which command to execute next. Access to this variable is guarded
|
||||
* by m_mutex_command and m_cond_command. */
|
||||
HttpCommands m_command;
|
||||
HttpCommands m_command;
|
||||
/** A mutex for accessing m_commands. */
|
||||
pthread_mutex_t m_mutex_command;
|
||||
/** A conditional variable to wake up the main loop. */
|
||||
pthread_cond_t m_cond_command;
|
||||
pthread_cond_t m_cond_command;
|
||||
|
||||
/** The file to download when a file download is triggered. */
|
||||
std::string m_file;
|
||||
|
||||
/** The name and path under which to save the downloaded file. */
|
||||
std::string m_save_filename;
|
||||
|
||||
/** Progress of a download in percent. It is guaranteed that
|
||||
* this value only becomes 1.0f, if the download is completed.*/
|
||||
Synchronised<float> m_progress;
|
||||
|
||||
/** Thread id of the thread running in this object. */
|
||||
pthread_t m_thread_id;
|
||||
@ -61,26 +72,27 @@ private:
|
||||
void checkNewServer();
|
||||
|
||||
void updateNews();
|
||||
std::string downloadToStrInternal(std::string url);
|
||||
bool downloadFileInternal();
|
||||
static int progressDownload(void *clientp, float dltotal, float dlnow,
|
||||
float ultotal, float ulnow);
|
||||
|
||||
public:
|
||||
NetworkHttp();
|
||||
~NetworkHttp();
|
||||
static size_t writeStr(char str [], size_t size, size_t nb_char,
|
||||
std::string * stream);
|
||||
std::string downloadToStr(std::string url);
|
||||
void downloadFileAsynchron(const std::string &file,
|
||||
const std::string &save = "");
|
||||
bool downloadFileSynchron(const std::string &file,
|
||||
const std::string &save = "");
|
||||
|
||||
const std::string
|
||||
getNewsMessage() const;
|
||||
float getProgress() const;
|
||||
};
|
||||
|
||||
extern NetworkHttp *network_http;
|
||||
bool download(std::string file, const std::string &save = "",
|
||||
int *progress_data = 0);
|
||||
|
||||
|
||||
int progressDownload (void *clientp, float dltotal, float dlnow,
|
||||
float ultotal, float ulnow);
|
||||
|
||||
extern pthread_mutex_t download_mutex;
|
||||
#endif
|
||||
#endif
|
||||
|
@ -862,6 +862,10 @@
|
||||
RelativePath="..\..\io\xml_node.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\io\xml_writer.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="input"
|
||||
@ -1360,6 +1364,10 @@
|
||||
RelativePath="..\..\utils\string_utils.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\utils\synchronised.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\utils\translation.hpp"
|
||||
>
|
||||
@ -1764,6 +1772,10 @@
|
||||
RelativePath="..\..\io\xml_node.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\io\xml_writer.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="input"
|
||||
|
@ -568,13 +568,21 @@ void FileManager::checkAndCreateAddonsDir()
|
||||
} // checkAndCreateAddonsDir
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string FileManager::getAddonsDir() const
|
||||
/** Returns the directory for addon files. */
|
||||
const std::string &FileManager::getAddonsDir() const
|
||||
{
|
||||
return m_addons_dir;
|
||||
} // getADdonsDir
|
||||
/* see l450: to avoid the compilation of unused methods. */
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns a filename in the addons directory.
|
||||
* \param name Name of the file.
|
||||
*/
|
||||
std::string FileManager::getAddonsFile(const std::string &name)
|
||||
{
|
||||
return getAddonsDir()+"/"+name;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string FileManager::getConfigDir() const
|
||||
{
|
||||
@ -666,10 +674,10 @@ void FileManager::listFiles(std::set<std::string>& result, const std::string& di
|
||||
void FileManager::checkAndCreateDirForAddons(std::string addons_name,
|
||||
std::string addons_type)
|
||||
{
|
||||
bool success = checkAndCreateDirectory(getAddonsDir() + "/data/" + addons_type);
|
||||
bool success = checkAndCreateDirectory(getAddonsDir() + addons_type);
|
||||
if(!success)
|
||||
std::cout << "There is a problem with the addons dir." << std::endl;
|
||||
checkAndCreateDirectory(getAddonsDir() + "/data/" + addons_type + addons_name);
|
||||
checkAndCreateDirectory(getAddonsDir() + addons_type + addons_name);
|
||||
|
||||
}
|
||||
bool FileManager::removeDirectory(char const *name)
|
||||
|
@ -42,46 +42,48 @@ class FileManager : public NoCopy
|
||||
{
|
||||
private:
|
||||
/** Handle to irrlicht's file systems. */
|
||||
io::IFileSystem *m_file_system;
|
||||
io::IFileSystem *m_file_system;
|
||||
/** Pointer to the irrlicht device. This is necessary before reInit is
|
||||
* called to store the NULL device initially created. See Constructor
|
||||
* for details. */
|
||||
IrrlichtDevice *m_device;
|
||||
IrrlichtDevice *m_device;
|
||||
|
||||
bool m_is_full_path;
|
||||
bool m_is_full_path;
|
||||
/** Directory where user config files are stored. */
|
||||
std::string m_config_dir;
|
||||
std::string m_config_dir;
|
||||
/** Directory where addons are stored. */
|
||||
std::string m_addons_dir;
|
||||
std::string m_addons_dir;
|
||||
/** Root data directory. */
|
||||
std::string m_root_dir;
|
||||
std::vector<std::string> m_texture_search_path,
|
||||
m_model_search_path,
|
||||
m_music_search_path;
|
||||
bool findFile (std::string& full_path,
|
||||
const std::string& fname,
|
||||
const std::vector<std::string>& search_path)
|
||||
const;
|
||||
void makePath (std::string& path, const std::string& dir,
|
||||
const std::string& fname) const;
|
||||
bool checkAndCreateDirectory(const std::string &path);
|
||||
io::path createAbsoluteFilename(const std::string &f);
|
||||
void checkAndCreateConfigDir();
|
||||
std::string m_root_dir;
|
||||
std::vector<std::string>
|
||||
m_texture_search_path,
|
||||
m_model_search_path,
|
||||
m_music_search_path;
|
||||
bool findFile(std::string& full_path,
|
||||
const std::string& fname,
|
||||
const std::vector<std::string>& search_path)
|
||||
const;
|
||||
void makePath(std::string& path, const std::string& dir,
|
||||
const std::string& fname) const;
|
||||
bool checkAndCreateDirectory(const std::string &path);
|
||||
io::path createAbsoluteFilename(const std::string &f);
|
||||
void checkAndCreateConfigDir();
|
||||
#ifdef ADDONS_MANAGER
|
||||
void checkAndCreateAddonsDir();
|
||||
void checkAndCreateAddonsDir();
|
||||
#endif
|
||||
public:
|
||||
FileManager(char *argv[]);
|
||||
~FileManager();
|
||||
void setDevice(IrrlichtDevice *device);
|
||||
void dropFileSystem();
|
||||
io::IXMLReader *createXMLReader(const std::string &filename);
|
||||
XMLNode *createXMLTree(const std::string &filename);
|
||||
FileManager(char *argv[]);
|
||||
~FileManager();
|
||||
void setDevice(IrrlichtDevice *device);
|
||||
void dropFileSystem();
|
||||
io::IXMLReader *createXMLReader(const std::string &filename);
|
||||
XMLNode *createXMLTree(const std::string &filename);
|
||||
|
||||
std::string getConfigDir () const;
|
||||
bool checkAndCreateDirectoryP(const std::string &path);
|
||||
std::string getConfigDir() const;
|
||||
bool checkAndCreateDirectoryP(const std::string &path);
|
||||
#ifdef ADDONS_MANAGER
|
||||
std::string getAddonsDir () const;
|
||||
const std::string &getAddonsDir() const;
|
||||
std::string getAddonsFile(const std::string &name);
|
||||
void checkAndCreateDirForAddons(std::string addons_name,
|
||||
std::string addons_type);
|
||||
bool removeDirectory(char const *name);
|
||||
|
21
src/main.cpp
21
src/main.cpp
@ -214,7 +214,7 @@ int handleCmdLinePreliminary(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else if( !strcmp(argv[i], "--version") || !strcmp(argv[i], "-v") )
|
||||
else if( !strcmp(argv[i], "--version") || !strcmp(argv[i], "-V") )
|
||||
{
|
||||
printf("==============================\n");
|
||||
#ifdef VERSION
|
||||
@ -561,6 +561,13 @@ void initRest()
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
GUIEngine::init(device, driver, StateManager::get());
|
||||
|
||||
#ifdef ADDONS_MANAGER
|
||||
// This only initialises the non-network part of the addons manager. The
|
||||
// online section of the addons manager will be initialised from a
|
||||
// separate thread running in network http.
|
||||
addons_manager = new AddonsManager();
|
||||
network_http = new NetworkHttp();
|
||||
#endif
|
||||
music_manager = new MusicManager();
|
||||
sfx_manager = new SFXManager();
|
||||
// The order here can be important, e.g. KartPropertiesManager needs
|
||||
@ -576,16 +583,16 @@ void initRest()
|
||||
highscore_manager = new HighscoreManager ();
|
||||
network_manager = new NetworkManager ();
|
||||
#ifdef ADDONS_MANAGER
|
||||
network_http = new NetworkHttp ();
|
||||
addons_manager = new AddonsManager ();
|
||||
|
||||
KartPropertiesManager::addKartSearchDir(file_manager->getAddonsDir() + "/data/karts/");
|
||||
track_manager->addTrackSearchDir(file_manager->getAddonsDir() + "/data/tracks/");
|
||||
KartPropertiesManager::addKartSearchDir(
|
||||
file_manager->getAddonsFile("data/karts/") );
|
||||
track_manager->addTrackSearchDir(
|
||||
file_manager->getAddonsFile("/data/tracks/"));
|
||||
#endif
|
||||
track_manager->loadTrackList();
|
||||
music_manager->addMusicToTracks();
|
||||
|
||||
GUIEngine::addLoadingIcon( irr_driver->getTexture(file_manager->getTextureFile("notes.png")) );
|
||||
GUIEngine::addLoadingIcon(
|
||||
irr_driver->getTexture(file_manager->getTextureFile("notes.png")) );
|
||||
|
||||
grand_prix_manager = new GrandPrixManager ();
|
||||
// Consistency check for challenges, and enable all challenges
|
||||
|
@ -72,13 +72,13 @@ void AddonsScreen::loadList()
|
||||
while(addons_manager->nextType(m_type))
|
||||
{
|
||||
std::cout << addons_manager->getName() << std::endl;
|
||||
if(addons_manager->isInstalledAsBool() &&
|
||||
if(addons_manager->isInstalled() &&
|
||||
addons_manager->getInstalledVersion() < addons_manager->getVersion())
|
||||
{
|
||||
w_list->addItem(addons_manager->getIdAsStr().c_str(),
|
||||
addons_manager->getName().c_str(), 2 /* icon installed */);
|
||||
}
|
||||
else if(addons_manager->isInstalledAsBool())
|
||||
else if(addons_manager->isInstalled())
|
||||
{
|
||||
w_list->addItem(addons_manager->getIdAsStr().c_str(),
|
||||
addons_manager->getName().c_str(), 0 /* icon installed */);
|
||||
|
@ -66,7 +66,8 @@ void AddonsUpdateScreen::eventCallback(GUIEngine::Widget* widget,
|
||||
}
|
||||
else if (name == "category")
|
||||
{
|
||||
std::string selection = ((GUIEngine::RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str();
|
||||
std::string selection =
|
||||
((GUIEngine::RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);
|
||||
|
||||
if (selection == "tab_track")
|
||||
{
|
||||
@ -96,12 +97,12 @@ void AddonsUpdateScreen::init()
|
||||
//w_list->addItem("kart", _("Karts:"), -1 /* no icon */);
|
||||
while(addons_manager->next())
|
||||
{
|
||||
if(addons_manager->isInstalledAsBool() &&
|
||||
if(addons_manager->isInstalled() &&
|
||||
addons_manager->getInstalledVersion() < addons_manager->getVersion())
|
||||
{
|
||||
std::cout << addons_manager->getName() << std::endl;
|
||||
w_list->addItem(addons_manager->getIdAsStr().c_str(),
|
||||
addons_manager->getName().c_str(), 0);
|
||||
w_list->addItem(addons_manager->getIdAsStr(),
|
||||
addons_manager->getName().c_str(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ namespace GUIEngine { class Widget; }
|
||||
* \brief Help screen, part 1
|
||||
* \ingroup states_screens
|
||||
*/
|
||||
class AddonsUpdateScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingleton<AddonsUpdateScreen>
|
||||
class AddonsUpdateScreen : public GUIEngine::Screen,
|
||||
public GUIEngine::ScreenSingleton<AddonsUpdateScreen>
|
||||
{
|
||||
friend class GUIEngine::ScreenSingleton<AddonsUpdateScreen>;
|
||||
AddonsUpdateScreen();
|
||||
@ -45,7 +46,8 @@ public:
|
||||
virtual void loadedFromFile();
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name, const int playerID);
|
||||
virtual void eventCallback(GUIEngine::Widget* widget,
|
||||
const std::string& name, const int playerID);
|
||||
|
||||
/** \brief implement callback from parent class GUIEngine::Screen */
|
||||
virtual void init();
|
||||
|
@ -37,25 +37,22 @@ using namespace irr::gui;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
|
||||
AddonsLoading::AddonsLoading(const float w, const float h) :
|
||||
ModalDialog(w, h)
|
||||
AddonsLoading::AddonsLoading(const float w, const float h)
|
||||
: ModalDialog(w, h)
|
||||
{
|
||||
loadFromFile("addons_view_dialog.stkgui");
|
||||
m_can_install = false;
|
||||
m_can_load_icon = false;
|
||||
m_can_install = false;
|
||||
m_can_load_icon = false;
|
||||
m_percent_update = false;
|
||||
pthread_mutex_init(&m_mutex_can_install, NULL);
|
||||
|
||||
/*Init the icon here to be able to load a single image*/
|
||||
icon = getWidget<IconButtonWidget>("icon");
|
||||
|
||||
name = getWidget<LabelWidget>("name");
|
||||
|
||||
description = getWidget<LabelWidget>("description");
|
||||
m_icon = getWidget<IconButtonWidget>("icon");
|
||||
m_name = getWidget<LabelWidget>("name");
|
||||
m_description = getWidget<LabelWidget>("description");
|
||||
m_version = getWidget<LabelWidget>("version");
|
||||
|
||||
version = getWidget<LabelWidget>("version");
|
||||
|
||||
if(addons_manager->isInstalledAsBool())
|
||||
if(addons_manager->isInstalled())
|
||||
{
|
||||
if(addons_manager->getInstalledVersion() < addons_manager->getVersion())
|
||||
getWidget<ButtonWidget>("install")->setLabel(_("Update"));
|
||||
@ -67,11 +64,11 @@ AddonsLoading::AddonsLoading(const float w, const float h) :
|
||||
}
|
||||
void AddonsLoading::loadInfo()
|
||||
{
|
||||
name->setText(StringUtils::insertValues(_("Name: %i"),
|
||||
m_name->setText(StringUtils::insertValues(_("Name: %i"),
|
||||
addons_manager->getName().c_str()));
|
||||
description->setText(StringUtils::insertValues(_("Description: %i"),
|
||||
m_description->setText(StringUtils::insertValues(_("Description: %i"),
|
||||
addons_manager->getDescription().c_str()));
|
||||
version->setText(StringUtils::insertValues(_("Version: %i"),
|
||||
m_version->setText(StringUtils::insertValues(_("Version: %i"),
|
||||
addons_manager->getVersionAsStr().c_str()));
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, &AddonsLoading::downloadIcon, this);
|
||||
@ -83,13 +80,14 @@ void * AddonsLoading::downloadIcon( void * pthis)
|
||||
AddonsLoading * pt = (AddonsLoading*)pthis;
|
||||
|
||||
std::string iconPath = "icon/" + addons_manager->getIcon();
|
||||
if (download(iconPath, addons_manager->getName() + ".png"))
|
||||
network_http->downloadFileAsynchron(iconPath, addons_manager->getName() + ".png");
|
||||
// FIXME if (network_http->downloadFile(iconPath, addons_manager->getName() + ".png"))
|
||||
{
|
||||
pthread_mutex_lock(&(pt->m_mutex_can_install));
|
||||
pt->m_can_load_icon = true;
|
||||
pthread_mutex_unlock(&(pt->m_mutex_can_install));
|
||||
}
|
||||
else
|
||||
// else
|
||||
{
|
||||
fprintf(stderr, "[Addons] Download icon '%s' failed\n", iconPath.c_str());
|
||||
}
|
||||
@ -170,7 +168,7 @@ void AddonsLoading::onUpdate(float delta)
|
||||
}
|
||||
if(m_can_load_icon)
|
||||
{
|
||||
icon->setImage( (file_manager->getConfigDir() + "/"
|
||||
m_icon->setImage( (file_manager->getConfigDir() + "/"
|
||||
+ addons_manager->getName() + ".png").c_str(),
|
||||
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
|
||||
}
|
||||
@ -192,7 +190,7 @@ void AddonsLoading::close()
|
||||
void * AddonsLoading::startInstall(void* pthis)
|
||||
{
|
||||
AddonsLoading * obj = (AddonsLoading*)pthis;
|
||||
if(!addons_manager->isInstalledAsBool() || addons_manager->needUpdate())
|
||||
if(!addons_manager->isInstalled() || addons_manager->needUpdate())
|
||||
{
|
||||
addons_manager->install();
|
||||
}
|
||||
|
@ -21,26 +21,27 @@
|
||||
#ifndef HEADER_ADDONS_LOADING_HPP
|
||||
#define HEADER_ADDONS_LOADING_HPP
|
||||
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
|
||||
#include "addons/addons_manager.hpp"
|
||||
#include "guiengine/widgets.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
#include <pthread.h>
|
||||
|
||||
class AddonsLoading : public GUIEngine::ModalDialog
|
||||
{
|
||||
//virtual void escapePressed() {};
|
||||
private:
|
||||
GUIEngine::LabelWidget * name;
|
||||
GUIEngine::LabelWidget * description;
|
||||
GUIEngine::LabelWidget * version;
|
||||
GUIEngine::LabelWidget * author;
|
||||
GUIEngine::LabelWidget * m_state;
|
||||
GUIEngine::ProgressBarWidget * m_progress;
|
||||
GUIEngine::ButtonWidget * m_back_button;
|
||||
GUIEngine::ButtonWidget * install_button;
|
||||
GUIEngine::IconButtonWidget * icon;
|
||||
GUIEngine::IconButtonWidget * m_next;
|
||||
GUIEngine::IconButtonWidget * m_previous;
|
||||
GUIEngine::LabelWidget *m_name;
|
||||
GUIEngine::LabelWidget *m_description;
|
||||
GUIEngine::LabelWidget *m_version;
|
||||
GUIEngine::LabelWidget *m_author;
|
||||
GUIEngine::LabelWidget *m_state;
|
||||
GUIEngine::ProgressBarWidget *m_progress;
|
||||
GUIEngine::ButtonWidget *m_back_button;
|
||||
GUIEngine::ButtonWidget *m_install_button;
|
||||
GUIEngine::IconButtonWidget *m_icon;
|
||||
GUIEngine::IconButtonWidget *m_next;
|
||||
GUIEngine::IconButtonWidget *m_previous;
|
||||
|
||||
/**
|
||||
* This function is called when the user click on 'Install', 'Uninstall', or
|
||||
|
@ -26,12 +26,12 @@
|
||||
#include "io/file_manager.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "main_loop.hpp"
|
||||
#include "states_screens/addons_screen.hpp"
|
||||
#include "states_screens/challenges.hpp"
|
||||
#include "states_screens/credits.hpp"
|
||||
#include "states_screens/kart_selection.hpp"
|
||||
#include "states_screens/help_screen_1.hpp"
|
||||
#include "states_screens/kart_selection.hpp"
|
||||
#include "states_screens/options_screen_video.hpp"
|
||||
#include "states_screens/addons_screen.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
|
||||
//FIXME : remove, temporary tutorial test
|
||||
@ -90,13 +90,26 @@ void MainMenuScreen::init()
|
||||
// To avoid this, we will clean the last used device, making
|
||||
// the key bindings for the first player the default again.
|
||||
input_manager->getDeviceList()->clearLatestUsedDevice();
|
||||
|
||||
|
||||
if(!addons_manager->onlineReady())
|
||||
{
|
||||
IconButtonWidget* w = this->getWidget<IconButtonWidget>("addons");
|
||||
w->setDeactivated();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef ADDONS_MANAGER
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
void MainMenuScreen::onUpdate(float delta, irr::video::IVideoDriver* driver)
|
||||
{
|
||||
IconButtonWidget* icon = this->getWidget<IconButtonWidget>("addons");
|
||||
if(!addons_manager->onlineReady())
|
||||
icon->setDeactivated();
|
||||
else
|
||||
icon->setActivated();
|
||||
|
||||
|
||||
LabelWidget* w = this->getWidget<LabelWidget>("info_addons");
|
||||
const std::string &news_text = network_http->getNewsMessage();
|
||||
if(news_text == "")
|
||||
|
82
src/utils/synchronised.hpp
Normal file
82
src/utils/synchronised.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// $Id$
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2010 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_SYNCHRONISED_HPP
|
||||
#define HEADER_SYNCHRONISED_HPP
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
template<typename TYPE>
|
||||
|
||||
/** A variable that is automatically synchronised using pthreads mutex.
|
||||
*/
|
||||
class Synchronised
|
||||
{
|
||||
private:
|
||||
/** The mutex to protect this variable with. */
|
||||
mutable pthread_mutex_t m_mutex;
|
||||
/** The actual data to be used. */
|
||||
TYPE m_data;
|
||||
public:
|
||||
/** Initialise the data and the mutex. */
|
||||
Synchronised(const TYPE &v)
|
||||
{
|
||||
m_data = v;
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
} // Synchronised
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Destroy this mutex.
|
||||
*/
|
||||
~Synchronised()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
} // ~Synchronised
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the value of this variable using a mutex.
|
||||
* \param v Value to be set.
|
||||
*/
|
||||
void set(const TYPE &v)
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
m_data = v;
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
} // set
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a copy of this variable.
|
||||
*/
|
||||
TYPE get() const
|
||||
{
|
||||
TYPE v;
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
v = m_data;
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
return v;
|
||||
} // get
|
||||
|
||||
private:
|
||||
// Make sure that no actual copying is taking place
|
||||
// ------------------------------------------------------------------------
|
||||
void operator=(const Synchronised<TYPE>& v) {}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user