diff --git a/src/framework/BOINCClientAdapter.cpp b/src/framework/BOINCClientAdapter.cpp index d999271db321c1d98b7e83657699edc0da87e944..ef587e7670319261f222b0bb81108dd06ff1510f 100644 --- a/src/framework/BOINCClientAdapter.cpp +++ b/src/framework/BOINCClientAdapter.cpp @@ -19,6 +19,9 @@ ***************************************************************************/ #include "BOINCClientAdapter.h" +#include "Libxml2Adapter.h" + +#include <sstream> BOINCClientAdapter::BOINCClientAdapter(string sharedMemoryIdentifier) { @@ -26,6 +29,8 @@ BOINCClientAdapter::BOINCClientAdapter(string sharedMemoryIdentifier) m_SharedMemoryAreaIdentifier = sharedMemoryIdentifier; m_SharedMemoryAreaAvailable = false; + m_xmlIFace = new Libxml2Adapter(); + m_GraphicsFrameRate = 20; m_GraphicsQualitySetting = BOINCClientAdapter::LowGraphicsQualitySetting; m_GraphicsWindowWidth = 800; @@ -34,15 +39,18 @@ BOINCClientAdapter::BOINCClientAdapter(string sharedMemoryIdentifier) BOINCClientAdapter::~BOINCClientAdapter() { + if(m_xmlIFace) delete m_xmlIFace; } void BOINCClientAdapter::initialize() { - readUserInfo(); - readSharedMemoryArea(); - readProjectPreferences(); + if(!m_Initialized) { + readUserInfo(); + readSharedMemoryArea(); + readProjectPreferences(); - m_Initialized = true; + m_Initialized = true; + } } void BOINCClientAdapter::refresh() @@ -54,7 +62,7 @@ void BOINCClientAdapter::refresh() /// \todo Check that we're still watching our own WU (or science app)! } else { - cerr << "The BOINC Client Adapter has not yet been initialized! Doing so now..."; + cerr << "The BOINC Client Adapter has not yet been initialized! Doing so now..." << endl; initialize(); } } @@ -91,7 +99,52 @@ void BOINCClientAdapter::readSharedMemoryArea() void BOINCClientAdapter::readProjectPreferences() { - + string temp; + istringstream convertor; + convertor.exceptions(ios_base::badbit | ios_base::failbit); + + // prepare xml document + m_xmlIFace->setXmlDocument(projectInformation(), "http://einstein.phys.uwm.edu"); + + // use XPath queries to get attributes + try { + temp = m_xmlIFace->getSingleNodeContentByXPath("/project_preferences/graphics/@fps"); + if(temp.length() > 0) { + convertor.str(temp); + convertor >> dec >> m_GraphicsFrameRate; + convertor.clear(); + } + + temp = m_xmlIFace->getSingleNodeContentByXPath("/project_preferences/graphics/@quality"); + if(temp.length() > 0) { + if(temp == "high") { + m_GraphicsQualitySetting = BOINCClientAdapter::HighGraphicsQualitySetting; + } + else if(temp == "medium") { + m_GraphicsQualitySetting = BOINCClientAdapter::MediumGraphicsQualitySetting; + } + else { + m_GraphicsQualitySetting = BOINCClientAdapter::LowGraphicsQualitySetting; + } + } + + temp = m_xmlIFace->getSingleNodeContentByXPath("/project_preferences/graphics/@width"); + if(temp.length() > 0) { + convertor.str(temp); + convertor >> dec >> m_GraphicsWindowWidth; + convertor.clear(); + } + + temp = m_xmlIFace->getSingleNodeContentByXPath("/project_preferences/graphics/@height"); + if(temp.length() > 0) { + convertor.str(temp); + convertor >> dec >> m_GraphicsWindowHeight; + convertor.clear(); + } + } + catch(ios_base::failure) { + cerr << "Error parsing project preferences! Using defaults..." << endl; + } } string BOINCClientAdapter::applicationInformation() const @@ -101,8 +154,12 @@ string BOINCClientAdapter::applicationInformation() const string BOINCClientAdapter::projectInformation() const { - // TODO: check if we have to add the <project_specific> tag! - return m_UserData.project_preferences; + // ugly workaround for incomplete XML fragment returned by BOINC! + string temp = "<project_preferences>\n"; + temp += m_UserData.project_preferences; + temp += "</project_preferences>\n"; + + return temp; } int BOINCClientAdapter::graphicsFrameRate() const diff --git a/src/framework/BOINCClientAdapter.h b/src/framework/BOINCClientAdapter.h index d8689abfd4f7e464035014adf223ec55d08991be..ee5d5c4313e1404069d34bd780c43df6dc400669 100644 --- a/src/framework/BOINCClientAdapter.h +++ b/src/framework/BOINCClientAdapter.h @@ -28,6 +28,8 @@ #include "boinc_api.h" #include "graphics2.h" +#include "XMLProcessorInterface.h" + using namespace std; /** @@ -226,7 +228,7 @@ public: * (not yet literally a XML schema, will be provided later) with respect to graphics settings: * \verbatim - <project_specific> + <project_preferences> <graphics fps="20" quality="low" width="800" height="600"> <starsphere> <feature id="globe" enabled="true" /> @@ -235,7 +237,7 @@ public: <feature id="sound" enabled="false" /> </waverider> </graphics> - </project_specific> + </project_preferences> \endverbatim * * The \c graphics tag and its four attributes \b must be provided as shown above where @@ -380,6 +382,9 @@ private: * user account, work unit and computation session. */ APP_INIT_DATA m_UserData; + + /// Pointer to the XML processor + XMLProcessorInterface* m_xmlIFace; }; /** diff --git a/src/framework/Libxml2Adapter.cpp b/src/framework/Libxml2Adapter.cpp index 07186c37a8a533f7c5bd999c098748da4db688ac..ead673d0dc2be35983c47133ac1b83566b5f0f1e 100644 --- a/src/framework/Libxml2Adapter.cpp +++ b/src/framework/Libxml2Adapter.cpp @@ -32,6 +32,8 @@ Libxml2Adapter::Libxml2Adapter() Libxml2Adapter::~Libxml2Adapter() { + if(m_xmlDocument) xmlFreeDoc(m_xmlDocument); + xmlCleanupParser(); } void Libxml2Adapter::setXmlDocument(const string xml, const string url) @@ -48,7 +50,7 @@ void Libxml2Adapter::setXmlDocument(const string xml, const string url) string Libxml2Adapter::getSingleNodeContentByXPath(const string xpath) { // no document available! - if(!m_xmlDocument) return(NULL); + if(!m_xmlDocument) return(""); // prepare xpath search stringstream buffer; @@ -64,11 +66,11 @@ string Libxml2Adapter::getSingleNodeContentByXPath(const string xpath) if(size == 0) { cerr << "No node found using XPath expression: " << xpath << endl; - return(NULL); + return(""); } else if(size < 1) { cerr << "More than node found using XPath expression: " << xpath << endl; - return(NULL); + return(""); } // convert xml contents diff --git a/src/framework/Libxml2Adapter.h b/src/framework/Libxml2Adapter.h index 92ca84b026b3cc94198d423e511953f6d63817b7..d4fb1c9a6f5b3e537571c763b392d32eb917c13b 100644 --- a/src/framework/Libxml2Adapter.h +++ b/src/framework/Libxml2Adapter.h @@ -84,13 +84,13 @@ public: * This method takes a XPath expression that properly defines how to search * for a specific node (element or attribute). If the XPath search results * in more than one instance or if the node (or its content) can't be found - * the return value is NULL. + * the return value is an empty string. * * \param xml The XML document to be used for processing * \param url The base URL of the document * \param xpath The XPath expression to be used for seaching * - * \return The node's content or NULL in case of an error + * \return The node's content or an empty string in case of an error */ string getSingleNodeContentByXPath(const string xml, const string url, const string xpath);