Removed collection database concept. Replacing with a metadata concept.

This commit is contained in:
emb 2015-01-19 09:35:08 -06:00
parent 86f80f06cb
commit 898d2dedb3
17 changed files with 374 additions and 950 deletions

View File

@ -79,9 +79,9 @@ set(RETROFE_HEADERS
"${RETROFE_DIR}/Source/Collection/Item.h"
"${RETROFE_DIR}/Source/Collection/MenuParser.h"
"${RETROFE_DIR}/Source/Control/UserInput.h"
"${RETROFE_DIR}/Source/Database/CollectionDatabase.h"
"${RETROFE_DIR}/Source/Database/Configuration.h"
"${RETROFE_DIR}/Source/Database/DB.h"
"${RETROFE_DIR}/Source/Database/MetadataDatabase.h"
"${RETROFE_DIR}/Source/Database/MamelistMetadata.h"
"${RETROFE_DIR}/Source/Execute/AttractMode.h"
"${RETROFE_DIR}/Source/Execute/Launcher.h"
@ -122,9 +122,9 @@ set(RETROFE_SOURCES
"${RETROFE_DIR}/Source/Collection/Item.cpp"
"${RETROFE_DIR}/Source/Collection/MenuParser.cpp"
"${RETROFE_DIR}/Source/Control/UserInput.cpp"
"${RETROFE_DIR}/Source/Database/CollectionDatabase.cpp"
"${RETROFE_DIR}/Source/Database/Configuration.cpp"
"${RETROFE_DIR}/Source/Database/DB.cpp"
"${RETROFE_DIR}/Source/Database/MetadataDatabase.cpp"
"${RETROFE_DIR}/Source/Database/MamelistMetadata.cpp"
"${RETROFE_DIR}/Source/Execute/AttractMode.cpp"
"${RETROFE_DIR}/Source/Execute/Launcher.cpp"

View File

@ -14,6 +14,7 @@
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CollectionInfo.h"
#include "Item.h"
#include "../Database/Configuration.h"
#include <sstream>
@ -32,6 +33,14 @@ CollectionInfo::CollectionInfo(std::string name,
CollectionInfo::~CollectionInfo()
{
std::vector<Item *>::iterator it = Items.begin();
while(it != Items.end())
{
delete *it;
Items.erase(it);
it = Items.begin();
}
}
std::string CollectionInfo::GetName() const
@ -74,6 +83,10 @@ void CollectionInfo::GetExtensions(std::vector<std::string> &extensions)
extensions.push_back(token);
}
}
std::vector<Item *> *CollectionInfo::GetItems()
{
return &Items;
}

View File

@ -6,6 +6,8 @@
#include <string>
#include <vector>
class Item;
class CollectionInfo
{
public:
@ -17,6 +19,7 @@ public:
std::string GetMetadataType() const;
std::string GetMetadataPath() const;
std::string GetExtensions() const;
std::vector<Item *> *GetItems();
void GetExtensions(std::vector<std::string> &extensions);
private:
@ -25,4 +28,5 @@ private:
std::string Extensions;
std::string MetadataType;
std::string MetadataPath;
std::vector<Item *> Items;
};

View File

@ -15,86 +15,28 @@
*/
#include "CollectionInfoBuilder.h"
#include "CollectionInfo.h"
#include "Item.h"
#include "../Database/Configuration.h"
#include "../Database/MetadataDatabase.h"
#include "../Database/DB.h"
#include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include <dirent.h>
#include <sstream>
#include <vector>
CollectionInfoBuilder::CollectionInfoBuilder(Configuration &c)
CollectionInfoBuilder::CollectionInfoBuilder(Configuration &c, DB &db)
: Conf(c)
, MetaDB(db, c)
{
}
CollectionInfoBuilder::~CollectionInfoBuilder()
{
std::map<std::string, CollectionInfo *>::iterator it = InfoMap.begin();
for(it == InfoMap.begin(); it != InfoMap.end(); ++it)
{
delete it->second;
}
InfoMap.clear();
}
bool CollectionInfoBuilder::LoadAllCollections()
CollectionInfo *CollectionInfoBuilder::BuildCollection(std::string name)
{
std::vector<std::string> collections;
Conf.GetChildKeyCrumbs("collections", collections);
if(collections.size() == 0)
{
Logger::Write(Logger::ZONE_ERROR, "Collections", "No collections were found. Please configure Settings.conf");
return false;
}
bool retVal = true;
std::vector<std::string>::iterator it;
for(it = collections.begin(); it != collections.end(); ++it)
{
// todo: There is nothing that should really stop us from creating a collection
// in the main folder. I just need to find some time to look at the impacts if
// I remove this conditional check.
if(*it != "Main")
{
std::string oldCollection = Conf.GetCurrentCollection();
Conf.SetCurrentCollection(*it);
if(ImportCollection(*it))
{
Logger::Write(Logger::ZONE_INFO, "Collections", "Adding collection " + *it);
}
else
{
// Continue processing the rest of the collections if an error occurs during import.
// ImportCollection() will print out an error to the log file.
retVal = false;
}
Conf.SetCurrentCollection(oldCollection);
}
}
return retVal;
}
void CollectionInfoBuilder::GetCollections(std::vector<CollectionInfo *> &collections)
{
std::map<std::string, CollectionInfo *>::iterator InfoMapIt;
for(InfoMapIt = InfoMap.begin(); InfoMapIt != InfoMap.end(); ++InfoMapIt)
{
collections.push_back(InfoMapIt->second);
}
}
bool CollectionInfoBuilder::ImportCollection(std::string name)
{
// create a new instance if one does not exist
if(InfoMap.find(name) != InfoMap.end())
{
return true;
}
std::string listItemsPathKey = "collections." + name + ".list.path";
std::string listFilterKey = "collections." + name + ".list.filter";
std::string extensionsKey = "collections." + name + ".list.extensions";
@ -128,7 +70,87 @@ bool CollectionInfoBuilder::ImportCollection(std::string name)
Logger::Write(Logger::ZONE_WARNING, "Collections", ss.str());
}
InfoMap[name] = new CollectionInfo(name, listItemsPath, extensions, metadataType, metadataPath);
CollectionInfo *collection = new CollectionInfo(name, listItemsPath, extensions, metadataType, metadataPath);
std::vector<Item *> *list = collection->GetItems();
return (InfoMap[name] != NULL);
ImportDirectory(collection);
return collection;
}
bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info)
{
DIR *dp;
struct dirent *dirp;
std::string path = info->GetListPath();
std::map<std::string, Item *> includeFilter;
std::map<std::string, Item *> excludeFilter;
bool retVal = true;
std::string includeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.txt";
std::string excludeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Exclude.txt";
std::string launcher;
(void)Conf.GetProperty("collections." + info->GetName() + ".launcher", launcher);
dp = opendir(path.c_str());
std::vector<std::string> extensions;
info->GetExtensions(extensions);
std::vector<std::string>::iterator extensionsIt;
if(dp == NULL)
{
Logger::Write(Logger::ZONE_ERROR, "CollectionInfoBuilder", "Could not read directory \"" + path + "\"");
//todo: store into a database
}
else
{
while((dirp = readdir(dp)) != NULL)
{
std::string file = dirp->d_name;
Utils::NormalizeBackSlashes(file);
size_t position = file.find_last_of(".");
std::string basename = (std::string::npos == position)? file : file.substr(0, position);
if((includeFilter.size() == 0 || includeFilter.find(basename) != includeFilter.end()) &&
(excludeFilter.size() == 0 || excludeFilter.find(basename) == excludeFilter.end()))
{
for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt)
{
std::string comparator = "." + *extensionsIt;
int start = file.length() - comparator.length() + 1;
if(start >= 0)
{
if(file.compare(start, comparator.length(), *extensionsIt) == 0)
{
Item *i = new Item();
i->SetName(basename);
i->SetFullTitle(basename);
i->SetTitle(basename);
i->SetLauncher(launcher);
info->GetItems()->push_back(i);
}
}
}
}
}
}
MetaDB.UpdateMetadata(info);
while(includeFilter.size() > 0)
{
std::map<std::string, Item *>::iterator it = includeFilter.begin();
delete it->second;
includeFilter.erase(it);
}
while(excludeFilter.size() > 0)
{
std::map<std::string, Item *>::iterator it = excludeFilter.begin();
delete it->second;
excludeFilter.erase(it);
}
return true;
}

View File

@ -3,6 +3,8 @@
*/
#pragma once
#include "../Database/DB.h"
#include "../Database/MetadataDatabase.h"
#include <string>
#include <map>
#include <vector>
@ -10,16 +12,16 @@
class Configuration;
class CollectionInfo;
class CollectionInfoBuilder
{
public:
CollectionInfoBuilder(Configuration &c);
CollectionInfoBuilder(Configuration &c, DB &db);
virtual ~CollectionInfoBuilder();
bool LoadAllCollections();
void GetCollections(std::vector<CollectionInfo *> &keys);
CollectionInfo *BuildCollection(std::string collectionName);
private:
bool ImportCollection(std::string name);
std::map<std::string, CollectionInfo *> InfoMap;
MetadataDatabase MetaDB;
bool ImportDirectory(CollectionInfo *info);
Configuration &Conf;
};

View File

@ -15,10 +15,10 @@
*/
#include "MenuParser.h"
#include "CollectionInfo.h"
#include "Item.h"
#include "../Utility/Log.h"
#include "../Database/Configuration.h"
#include "../Database/CollectionDatabase.h"
#include "../Database/DB.h"
#include <algorithm>
#include <rapidxml.hpp>
@ -39,11 +39,11 @@ MenuParser::~MenuParser()
}
//todo: clean up this method, too much nesting
bool MenuParser::GetMenuItems(CollectionDatabase *cdb, std::string collectionName, std::vector<Item *> &items)
bool MenuParser::GetMenuItems(CollectionInfo *collection)
{
bool retVal = false;
//todo: magic string
std::string menuFilename = Configuration::GetAbsolutePath() + "/Collections/" + collectionName + "/Menu.xml";
std::string menuFilename = Configuration::GetAbsolutePath() + "/Collections/" + collection->GetName() + "/Menu.xml";
rapidxml::xml_document<> doc;
rapidxml::xml_node<> * rootNode;
@ -93,18 +93,23 @@ bool MenuParser::GetMenuItems(CollectionDatabase *cdb, std::string collectionNam
item->SetFullTitle(title);
item->SetName(collectionAttribute->value());
item->SetIsLeaf(false);
items.push_back(item);
collection->GetItems()->push_back(item);
}
else
{
std::string collectionName = collectionAttribute->value();
Logger::Write(Logger::ZONE_INFO, "Menu", "Loading collection into menu: " + collectionName);
cdb->GetCollection(collectionAttribute->value(), items);
//todo: unsupported option with this refactor
// need to append the collection
}
}
}
std::sort( items.begin(), items.end(), VectorSort);
// todo: sorting should occur within the collection itself, not externally
std::vector<Item *> *items = collection->GetItems();
std::sort( items->begin(), items->end(), VectorSort);
retVal = true;
}

View File

@ -2,16 +2,14 @@
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include "Item.h"
#include <vector>
class CollectionDatabase;
class CollectionInfo;
class MenuParser
{
public:
MenuParser();
virtual ~MenuParser();
bool GetMenuItems(CollectionDatabase *cdb, std::string collectionName, std::vector<Item *> &items);
bool GetMenuItems(CollectionInfo *cdb);
};

View File

@ -1,759 +0,0 @@
/* This file is part of RetroFE.
*
* RetroFE 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.
*
* RetroFE 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 RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CollectionDatabase.h"
#include "../Collection/CollectionInfoBuilder.h"
#include "../Collection/CollectionInfo.h"
#include "../Collection/Item.h"
#include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include "MamelistMetadata.h"
#include "Configuration.h"
#include "DB.h"
#include <algorithm>
#include <dirent.h>
#include <fstream>
#include <list>
#include <rapidxml.hpp>
#include <sstream>
#include <string>
#include <map>
#include <sys/types.h>
#include <sqlite3.h>
#include <zlib.h>
#include <exception>
CollectionDatabase::CollectionDatabase(DB &db, Configuration &c)
: Config(c)
, DBInstance(db)
{
}
CollectionDatabase::~CollectionDatabase()
{
}
bool CollectionDatabase::ResetDatabase()
{
bool retVal = true;
int rc;
char *error = NULL;
sqlite3 *handle = DBInstance.GetHandle();
Logger::Write(Logger::ZONE_INFO, "Database", "Erasing");
std::string sql;
sql.append("DROP TABLE IF EXISTS CollectionItems;");
sql.append("DROP TABLE IF EXISTS Meta;");
sql.append("DROP TABLE IF EXISTS Collections;");
rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error);
if(rc != SQLITE_OK)
{
std::stringstream ss;
ss << "Unable to create Configurations table. Error: " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
return retVal;
}
bool CollectionDatabase::Initialize()
{
int rc;
char *error = NULL;
sqlite3 *handle = DBInstance.GetHandle();
std::string sql;
sql.append("CREATE TABLE IF NOT EXISTS CollectionItems(");
sql.append("collectionName TEXT KEY,");
sql.append("filePath TEXT NOT NULL DEFAULT '',");
sql.append("name TEXT NOT NULL DEFAULT '',");
sql.append("hidden INT NOT NULL DEFAULT 0);");
sql.append("CREATE TABLE IF NOT EXISTS Meta(");
sql.append("collectionName TEXT KEY,");
sql.append("name TEXT NOT NULL DEFAULT '',");
sql.append("title TEXT NOT NULL DEFAULT '',");
sql.append("year TEXT NOT NULL DEFAULT '',");
sql.append("manufacturer TEXT NOT NULL DEFAULT '',");
sql.append("cloneOf TEXT NOT NULL DEFAULT '',");
sql.append("players INTEGER,");
sql.append("buttons INTEGER);");
sql.append("CREATE UNIQUE INDEX IF NOT EXISTS MetaUniqueId ON Meta(collectionName, name);");
sql.append("CREATE TABLE IF NOT EXISTS Collections(");
sql.append("collectionName TEXT KEY,");
sql.append("crc32 UNSIGNED INTEGER NOT NULL DEFAULT 0);");
sql.append("CREATE UNIQUE INDEX IF NOT EXISTS CollectionsUniqueId ON Collections(collectionName);");
rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error);
if(rc != SQLITE_OK)
{
std::stringstream ss;
ss << "Unable to create Configurations table. Error: " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
return false;
}
return true;
}
bool CollectionDatabase::Import()
{
bool retVal = true;
// should keep allocation here
CollectionInfoBuilder cib(Config);
(void)cib.LoadAllCollections();
std::vector<CollectionInfo *> collections;
cib.GetCollections(collections);
std::vector<CollectionInfo *>::iterator it;
for(it = collections.begin(); it != collections.end() && retVal; ++it)
{
CollectionInfo *info = *it;
std::string title = info->GetName();
unsigned long crc32 = CalculateCollectionCrc32(info);
std::stringstream crcStr;
crcStr << crc32;
if(title != "Main")
{
if(CollectionChanged(info, crc32))
{
std::string msg = "Detected collection \"" + title + "\" has changed (new CRC: " + crcStr.str() + "). Rebuilding database for this collection.";
Logger::Write(Logger::ZONE_INFO, "Database", msg);
(void)ImportDirectory(info, crc32);
retVal = true;
}
else
{
std::stringstream ss;
std::string msg = "Collection \"" + title + "\" has not changed (CRC: " + crcStr.str() + "). Using existing database settings.";
Logger::Write(Logger::ZONE_INFO, "Database", msg);
}
}
//std::cout << "Importing collection metadata for " << info->GetFullTitle() << " (collections." << info->GetName() << ")" << std::endl;
//ImportMetadata(info);
}
Logger::Write(Logger::ZONE_INFO, "Database", "Updating complete");
return retVal;
}
unsigned long CollectionDatabase::CalculateCollectionCrc32(CollectionInfo *info)
{
unsigned long crc = crc32(0L, Z_NULL, 0);
// start off by reading all of the contents in the collection configuration folders
std::string settingsFile = info->GetSettingsPath() + "/Settings.conf";
crc = CrcFile(settingsFile, crc);
std::string includeFile = info->GetSettingsPath() + "/Include.txt";
crc = CrcFile(includeFile, crc);
std::string excludeFile = info->GetSettingsPath() + "/Exclude.txt";
crc = CrcFile(excludeFile, crc);
std::string mamelistFile = info->GetSettingsPath() + "/Mamelist.xml";
crc = CrcFile(mamelistFile, crc);
DIR *dp;
struct dirent *dirp;
std::string path = info->GetListPath();
dp = opendir(path.c_str());
if(dp == NULL)
{
Logger::Write(Logger::ZONE_ERROR, "Database", "Could not read directory for caching \"" + info->GetListPath() + "\"");
return crc;
}
std::vector<std::string> extensions;
info->GetExtensions(extensions);
std::vector<std::string>::iterator extensionsIt;
// md5sum each filename for the matching extension
while((dirp = readdir(dp)) != NULL)
{
std::string file = dirp->d_name;
for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt)
{
std::string comparator = "." + *extensionsIt;
int start = file.length() - comparator.length() + 1;
if(start >= 0 && file.compare(start, comparator.length(), *extensionsIt) == 0)
{
std::string filename = dirp->d_name;
filename.append("\n");
crc = crc32(crc, (const unsigned char *)filename.c_str(), (unsigned int)filename.length());
}
}
}
return crc;
}
unsigned long CollectionDatabase::CrcFile(std::string file, unsigned long crc)
{
// CRC both the filename and its contents
crc = crc32(crc, (const unsigned char *)file.c_str(), (unsigned int)file.length());
std::ifstream ifFile(file.c_str());
if(ifFile.good())
{
std::stringstream ss;
ss << ifFile.rdbuf();
crc = crc32(crc, (const unsigned char *)ss.str().c_str(), (unsigned int)ss.str().length());
Logger::Write(Logger::ZONE_INFO, "Database", "Crcing \"" + file + "\"");
ifFile.close();
}
return crc;
}
bool CollectionDatabase::CollectionChanged(CollectionInfo *info, unsigned long crc32)
{
bool retVal = true;
sqlite3 *handle = DBInstance.GetHandle();
int rc;
sqlite3_stmt *stmt;
sqlite3_prepare_v2(handle,
"SELECT crc32 "
"FROM Collections WHERE collectionName=? and crc32=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 2, crc32);
rc = sqlite3_step(stmt);
if(rc == SQLITE_ROW)
{
retVal = false;
}
return retVal;
}
bool CollectionDatabase::SetHidden(std::string collectionName, Item *item, bool hidden)
{
bool retVal = true;
char *error = NULL;
sqlite3 *handle = DBInstance.GetHandle();
std::string mode = (hidden) ? "hidden":"visible";
int isHidden = (hidden)?1:0;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Marking \"" + item->GetFullTitle() + "\" " + mode);
sqlite3_stmt *stmt;
sqlite3_prepare_v2(handle,
"UPDATE CollectionItems SET hidden=? WHERE collectionName=? AND name=?;",
-1, &stmt, 0);
sqlite3_bind_int(stmt, 1, isHidden);
sqlite3_bind_text(stmt, 2, collectionName.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, item->GetFullTitle().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error);
return retVal;
}
//todo: This file needs MASSIVE REFACTORING!
bool CollectionDatabase::ImportDirectory(CollectionInfo *info, unsigned long crc32)
{
DIR *dp;
struct dirent *dirp;
std::string path = info->GetListPath();
std::map<std::string, Item *> includeFilter;
std::map<std::string, Item *> excludeFilter;
std::map<std::string, Item *> includeList;
std::map<std::string, Item *> metaList;
bool retVal = true;
char *error = NULL;
sqlite3 *handle = DBInstance.GetHandle();
std::string includeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.txt";
std::string excludeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Exclude.txt";
std::string includeHyperListFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.xml";
if(!ImportBasicList(info, includeFile, includeFilter))
{
ImportHyperList(info, includeHyperListFile, includeFilter);
}
//todo: this shouldn't be read twice, perform a copy
ImportHyperList(info, includeHyperListFile, metaList);
(void)ImportBasicList(info, excludeFile, excludeFilter);
dp = opendir(path.c_str());
std::vector<std::string> extensions;
info->GetExtensions(extensions);
std::vector<std::string>::iterator extensionsIt;
if(dp == NULL)
{
Logger::Write(Logger::ZONE_ERROR, "Database", "Could not read directory \"" + info->GetListPath() + "\"");
//todo: store into a database
}
else
{
while((dirp = readdir(dp)) != NULL)
{
std::string file = dirp->d_name;
Utils::NormalizeBackSlashes(file);
size_t position = file.find_last_of(".");
std::string basename = (std::string::npos == position)? file : file.substr(0, position);
if((includeFilter.size() == 0 || includeFilter.find(basename) != includeFilter.end()) &&
(excludeFilter.size() == 0 || excludeFilter.find(basename) == excludeFilter.end()))
{
for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt)
{
std::string comparator = "." + *extensionsIt;
int start = file.length() - comparator.length() + 1;
if(start >= 0)
{
if(file.compare(start, comparator.length(), *extensionsIt) == 0)
{
if(includeList.find(basename) == includeList.end())
{
Item *i = new Item();
i->SetFullTitle(file);
includeList[basename] = i;
}
if(metaList.find(basename) == metaList.end())
{
Item *i = new Item();
i->SetFullTitle(file);
metaList[basename] = i;
}
}
}
}
}
}
}
while(includeFilter.size() > 0)
{
std::map<std::string, Item *>::iterator it = includeFilter.begin();
delete it->second;
includeFilter.erase(it);
}
while(excludeFilter.size() > 0)
{
std::map<std::string, Item *>::iterator it = excludeFilter.begin();
delete it->second;
excludeFilter.erase(it);
}
Logger::Write(Logger::ZONE_INFO, "Database", "Scanning to import \"" + path + "\"");
sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error);
sqlite3_stmt *stmt;
sqlite3_prepare_v2(handle,
"DELETE FROM Collections WHERE collectionName=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_prepare_v2(handle,
"DELETE FROM CollectionItems WHERE collectionName=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_prepare_v2(handle,
"DELETE FROM Meta WHERE collectionName=?;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
if(sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error) != SQLITE_OK)
{
std::stringstream ss;
ss << "Updating cache collection failure " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
std::map<std::string, Item *>::iterator it;
if(sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error) != SQLITE_OK)
{
std::stringstream ss;
ss << "Delete cache collection failure " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
for(it = includeList.begin(); it != includeList.end(); it++)
{
std::string basename = it->first;
Item *file = it->second;
std::string name = file->GetFullTitle();
Utils::NormalizeBackSlashes(name);
file->SetFullTitle(name);
sqlite3_prepare_v2(handle,
"INSERT OR REPLACE INTO CollectionItems (collectionName, filePath, name) VALUES (?,?,?);",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, file->GetFullTitle().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, basename.c_str(), -1, SQLITE_TRANSIENT);
//todo: better error handling for all of these messages
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
for(it = metaList.begin(); it != metaList.end(); it++)
{
std::string basename = it->first;
Item *file = it->second;
sqlite3_prepare_v2(handle,
"INSERT OR REPLACE INTO Meta (collectionName, name, title, year, manufacturer, cloneOf, players, buttons) VALUES (?,?,?,?,?,?,?,?);",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, basename.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, basename.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, file->GetYear().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, file->GetManufacturer().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, file->GetCloneOf().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 7, file->GetNumberPlayersString().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 8, file->GetNumberButtonsString().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
sqlite3_prepare_v2(handle,
"INSERT OR REPLACE INTO Collections (collectionName, crc32) VALUES (?,?);",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 2, crc32);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
if(sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error) != SQLITE_OK)
{
std::stringstream ss;
ss << "Updating cache collection failure " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
Logger::Write(Logger::ZONE_INFO, "Database", "Imported files from \"" + path + "\" into database");
//todo: create a helper method to get this file directly (copy paste hazard)
std::string mamelistFile = info->GetSettingsPath() + "/Mamelist.xml";
std::ifstream infile(mamelistFile.c_str());
if(infile.good())
{
Logger::Write(Logger::ZONE_INFO, "Database", "Updating Mamelist metadata for \"" + info->GetName() + "\" (\"" + mamelistFile + "\") into database. This will take a while...");
MamelistMetadata mld(DBInstance);
mld.Import(mamelistFile, info->GetName());
}
infile.close();
while(includeList.size() > 0)
{
std::map<std::string, Item *>::iterator it = includeList.begin();
delete it->second;
includeList.erase(it);
}
while(metaList.size() > 0)
{
std::map<std::string, Item *>::iterator it = metaList.begin();
delete it->second;
metaList.erase(it);
}
return retVal;
}
bool CollectionDatabase::ImportBasicList(CollectionInfo *info, std::string file, std::map<std::string, Item *> &list)
{
bool retVal = false;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Checking to see if \"" + file + "\" exists");
std::ifstream includeStream(file.c_str());
if (includeStream.good())
{
Logger::Write(Logger::ZONE_DEBUG, "Database", "Importing \"" + file + "\"");
std::string line;
while(std::getline(includeStream, line))
{
if(list.find(line) == list.end())
{
Item *i = new Item();
line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() );
i->SetFullTitle(line);
list[line] = i;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Including \"" + line + "\" (if file exists)");
}
}
retVal = true;
}
return retVal;
}
bool CollectionDatabase::ImportHyperList(CollectionInfo *info, std::string hyperlistFile, std::map<std::string, Item *> &list)
{
bool retVal = false;
rapidxml::xml_document<> doc;
std::ifstream file(hyperlistFile.c_str());
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
Logger::Write(Logger::ZONE_DEBUG, "Database", "Checking to see if \"" + hyperlistFile + "\" exists");
if(!file.good())
{
Logger::Write(Logger::ZONE_INFO, "Database", "Could not find HyperList file: " + hyperlistFile);
return retVal;
}
try
{
Logger::Write(Logger::ZONE_INFO, "Database", "Importing: " + hyperlistFile);
buffer.push_back('\0');
doc.parse<0>(&buffer[0]);
rapidxml::xml_node<> *root = doc.first_node("menu");
if(!root)
{
Logger::Write(Logger::ZONE_ERROR, "CollectionDatabase", "Does not appear to be a HyperList file (missing <menu> tag)");
return NULL;
}
else
{
for(rapidxml::xml_node<> *game = root->first_node("game"); game; game = game->next_sibling("game"))
{
rapidxml::xml_attribute<> *nameXml = game->first_attribute("name");
rapidxml::xml_node<> *descriptionXml = game->first_node("description");
rapidxml::xml_node<> *cloneofXml = game->first_node("cloneof");
rapidxml::xml_node<> *crcXml = game->first_node("crc");
rapidxml::xml_node<> *manufacturerXml = game->first_node("manufacturer");
rapidxml::xml_node<> *yearXml = game->first_node("year");
rapidxml::xml_node<> *genreXml = game->first_node("genre");
rapidxml::xml_node<> *ratingXml = game->first_node("rating");
rapidxml::xml_node<> *enabledXml = game->first_node("enabled");
std::string name = (nameXml) ? nameXml->value() : "";
std::string description = (descriptionXml) ? descriptionXml->value() : "";
std::string crc = (crcXml) ? crcXml->value() : "";
std::string cloneOf = (cloneofXml) ? cloneofXml->value() : "";
std::string manufacturer = (manufacturerXml) ? manufacturerXml->value() : "";
std::string year = (yearXml) ? yearXml->value() : "";
std::string genre = (genreXml) ? genreXml->value() : "";
std::string rating = (ratingXml) ? ratingXml->value() : "";
std::string enabled = (enabledXml) ? enabledXml->value() : "";
if(name.length() > 0 && list.find(name) == list.end())
{
Item *i = new Item();
i->SetFullTitle(name);
i->SetYear(year);
i->SetManufacturer(manufacturer);
i->SetCloneOf(cloneOf);
list[name] = i;
Logger::Write(Logger::ZONE_DEBUG, "Database", "Including \"" + name + "\" (if file exists)");
}
}
}
}
catch(rapidxml::parse_error &e)
{
std::string what = e.what();
long line = static_cast<long>(std::count(&buffer.front(), e.where<char>(), char('\n')) + 1);
std::stringstream ss;
ss << "Could not parse layout file. [Line: " << line << "] Reason: " << e.what();
Logger::Write(Logger::ZONE_ERROR, "Layout", ss.str());
}
catch(std::exception &e)
{
std::string what = e.what();
Logger::Write(Logger::ZONE_ERROR, "Layout", "Could not parse layout file. Reason: " + what);
}
return retVal;
}
/*
bool CollectionDatabase::ImportMetadata(CollectionInfo *info)
{
bool retVal = true;
std::string type = info->GetMetadataType();
if(type.compare("mamelist") == 0)
{
MamelistMetadata meta;
//todo: pass in collectionName
retVal = meta.Import(info->GetMetadataPath(), "arcade");
}
else if(!type.empty())
{
std::stringstream ss;
ss << "Unsupported metadata type \"" << type << "\" for " << info->GetFullTitle() << " (collections." << info->GetName() << ".metadata.type)" << std::endl;
Log::Write(Log::ERROR, "Database", ss.str());
retVal = false;
}
return retVal;
}
*/
bool CollectionDatabase::GetCollection(std::string collectionName, std::vector<Item *> &list)
{
bool retVal = true;
sqlite3 *handle = DBInstance.GetHandle();
int rc;
sqlite3_stmt *stmt;
bool showParenthesis = true;
bool showSquareBrackets = true;
(void)Config.GetProperty("showParenthesis", showParenthesis);
(void)Config.GetProperty("showSquareBrackets", showSquareBrackets);
//todo: program crashes if this query fails
sqlite3_prepare_v2(handle,
"SELECT DISTINCT CollectionItems.filePath, CollectionItems.name, Meta.title, Meta.year, Meta.manufacturer, Meta.players, Meta.buttons, Meta.cloneOf "
"FROM CollectionItems, Meta WHERE CollectionItems.collectionName=? AND Meta.collectionName=? AND CollectionItems.name=Meta.name AND CollectionItems.hidden=0 ORDER BY title ASC;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, collectionName.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, collectionName.c_str(), -1, SQLITE_TRANSIENT);
rc = sqlite3_step(stmt);
while(rc == SQLITE_ROW)
{
std::string filePath = (char *)sqlite3_column_text(stmt, 0);
std::string name = (char *)sqlite3_column_text(stmt, 1);
std::string fullTitle = (char *)sqlite3_column_text(stmt, 2);
std::string year = (char *)sqlite3_column_text(stmt, 3);
std::string manufacturer = (char *)sqlite3_column_text(stmt, 4);
int numberPlayers = (int)sqlite3_column_int(stmt, 5);
int numberButtons = (int)sqlite3_column_int(stmt, 6);
std::string cloneOf = (char *)sqlite3_column_text(stmt, 7);
std::string launcher;
std::string title = fullTitle;
if(!showParenthesis)
{
std::string::size_type firstPos = title.find_first_of("(");
std::string::size_type secondPos = title.find_first_of(")", firstPos);
while(firstPos != std::string::npos && secondPos != std::string::npos)
{
firstPos = title.find_first_of("(");
secondPos = title.find_first_of(")", firstPos);
if (firstPos != std::string::npos)
{
title.erase(firstPos, (secondPos - firstPos) + 1);
}
}
}
if(!showSquareBrackets)
{
std::string::size_type firstPos = title.find_first_of("[");
std::string::size_type secondPos = title.find_first_of("]", firstPos);
while(firstPos != std::string::npos && secondPos != std::string::npos)
{
firstPos = title.find_first_of("[");
secondPos = title.find_first_of("]", firstPos);
if (firstPos != std::string::npos && secondPos != std::string::npos)
{
title.erase(firstPos, (secondPos - firstPos) + 1);
}
}
}
Item *item = new Item();
item->SetFilePath(filePath);
item->SetName(name);
item->SetTitle(title);
item->SetFullTitle(fullTitle);
item->SetYear(year);
item->SetManufacturer(manufacturer);
item->SetNumberPlayers(numberPlayers);
item->SetNumberButtons(numberButtons);
item->SetCloneOf(cloneOf);
//std::cout << "loading " << title << std::endl;
if(Config.GetProperty("collections." + collectionName + ".launcher", launcher))
{
item->SetLauncher(launcher);
}
list.push_back(item);
rc = sqlite3_step(stmt);
}
//todo: query the metadata table to populate each item
return retVal;
}

View File

@ -1,44 +0,0 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
#include <vector>
#include <map>
class DB;
class Configuration;
class CollectionInfo;
class Item;
class CollectionDatabase
{
public:
CollectionDatabase(DB &db, Configuration &c);
virtual ~CollectionDatabase();
bool Initialize();
bool Import();
bool ResetDatabase();
bool GetCollection(std::string collectionName, std::vector<Item *> &list);
bool SetHidden(std::string collectionName, Item *item, bool hidden);
private:
unsigned long CalculateCollectionCrc32(CollectionInfo *info);
bool CollectionChanged(CollectionInfo *info, unsigned long crc32);
unsigned long CrcFile(std::string file, unsigned long crc);
// bool ImportMetadata(CollectionInfo *info);
bool ImportDirectory(CollectionInfo *info, unsigned long crc32);
bool ImportBasicList(CollectionInfo *info,
std::string file,
std::map<std::string, Item *> &list);
bool ImportHyperList(CollectionInfo *info,
std::string file,
std::map<std::string, Item *> &list);
std::map<std::string, Item *> *ImportHyperList(CollectionInfo *info);
Configuration &Config;
DB &DBInstance;
};

View File

@ -0,0 +1,198 @@
/* This file is part of RetroFE.
*
* RetroFE 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.
*
* RetroFE 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 RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MetadataDatabase.h"
#include "../Collection/CollectionInfo.h"
#include "../Collection/Item.h"
#include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include "MamelistMetadata.h"
#include "Configuration.h"
#include "DB.h"
#include <algorithm>
#include <dirent.h>
#include <fstream>
#include <list>
#include <rapidxml.hpp>
#include <sstream>
#include <string>
#include <map>
#include <sys/types.h>
#include <sqlite3.h>
#include <zlib.h>
#include <exception>
MetadataDatabase::MetadataDatabase(DB &db, Configuration &c)
: Config(c)
, DBInstance(db)
{
}
MetadataDatabase::~MetadataDatabase()
{
}
bool MetadataDatabase::ResetDatabase()
{
bool retVal = true;
int rc;
char *error = NULL;
sqlite3 *handle = DBInstance.GetHandle();
Logger::Write(Logger::ZONE_INFO, "Database", "Erasing");
std::string sql;
sql.append("DROP TABLE IF EXISTS Meta;");
rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error);
if(rc != SQLITE_OK)
{
std::stringstream ss;
ss << "Unable to create Metadata table. Error: " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
retVal = false;
}
return retVal;
}
bool MetadataDatabase::Initialize()
{
int rc;
char *error = NULL;
sqlite3 *handle = DBInstance.GetHandle();
std::string sql;
sql.append("CREATE TABLE IF NOT EXISTS Meta(");
sql.append("collectionName TEXT KEY,");
sql.append("name TEXT NOT NULL DEFAULT '',");
sql.append("title TEXT NOT NULL DEFAULT '',");
sql.append("year TEXT NOT NULL DEFAULT '',");
sql.append("manufacturer TEXT NOT NULL DEFAULT '',");
sql.append("cloneOf TEXT NOT NULL DEFAULT '',");
sql.append("players INTEGER,");
sql.append("buttons INTEGER);");
sql.append("CREATE UNIQUE INDEX IF NOT EXISTS MetaUniqueId ON Meta(collectionName, name);");
rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error);
if(rc != SQLITE_OK)
{
std::stringstream ss;
ss << "Unable to create Metadata table. Error: " << error;
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
return false;
}
return true;
}
void MetadataDatabase::UpdateMetadata(CollectionInfo *collection)
{
sqlite3 *handle = DBInstance.GetHandle();
int rc;
sqlite3_stmt *stmt;
bool showParenthesis = true;
bool showSquareBrackets = true;
(void)Config.GetProperty("showParenthesis", showParenthesis);
(void)Config.GetProperty("showSquareBrackets", showSquareBrackets);
// items into a hash to make it easily searchable
std::vector<Item *> *items = collection->GetItems();
std::map<std::string, Item *> itemMap;
for(std::vector<Item *>::iterator it = items->begin(); it != items->end(); it++)
{
itemMap[(*it)->GetName()] = *it;
}
//todo: program crashes if this query fails
sqlite3_prepare_v2(handle,
"SELECT DISTINCT Meta.name, Meta.title, Meta.year, Meta.manufacturer, Meta.players, Meta.buttons, Meta.cloneOf "
"FROM Meta WHERE collectionName=? ORDER BY title ASC;",
-1, &stmt, 0);
sqlite3_bind_text(stmt, 1, collection->GetName().c_str(), -1, SQLITE_TRANSIENT);
rc = sqlite3_step(stmt);
while(rc == SQLITE_ROW)
{
std::string name = (char *)sqlite3_column_text(stmt, 0);
std::string fullTitle = (char *)sqlite3_column_text(stmt, 1);
std::string year = (char *)sqlite3_column_text(stmt, 2);
std::string manufacturer = (char *)sqlite3_column_text(stmt, 3);
int numberPlayers = (int)sqlite3_column_int(stmt, 4);
int numberButtons = (int)sqlite3_column_int(stmt, 5);
std::string cloneOf = (char *)sqlite3_column_text(stmt, 6);
std::string launcher;
std::string title = fullTitle;
//todo: this should be a helper method, peformed both in CollectionInfoBuilder
if(!showParenthesis)
{
std::string::size_type firstPos = title.find_first_of("(");
std::string::size_type secondPos = title.find_first_of(")", firstPos);
while(firstPos != std::string::npos && secondPos != std::string::npos)
{
firstPos = title.find_first_of("(");
secondPos = title.find_first_of(")", firstPos);
if (firstPos != std::string::npos)
{
title.erase(firstPos, (secondPos - firstPos) + 1);
}
}
}
if(!showSquareBrackets)
{
std::string::size_type firstPos = title.find_first_of("[");
std::string::size_type secondPos = title.find_first_of("]", firstPos);
while(firstPos != std::string::npos && secondPos != std::string::npos)
{
firstPos = title.find_first_of("[");
secondPos = title.find_first_of("]", firstPos);
if (firstPos != std::string::npos && secondPos != std::string::npos)
{
title.erase(firstPos, (secondPos - firstPos) + 1);
}
}
}
std::map<std::string, Item *>::iterator it = itemMap.find(name);
if(it != itemMap.end())
{
Item *item = it->second;
item->SetTitle(title);
item->SetFullTitle(fullTitle);
item->SetYear(year);
item->SetManufacturer(manufacturer);
item->SetNumberPlayers(numberPlayers);
item->SetNumberButtons(numberButtons);
item->SetCloneOf(cloneOf);
}
rc = sqlite3_step(stmt);
}
}

View File

@ -0,0 +1,28 @@
/* This file is subject to the terms and conditions defined in
* file 'LICENSE.txt', which is part of this source code package.
*/
#pragma once
#include <string>
#include <vector>
#include <map>
class DB;
class Configuration;
class CollectionInfo;
class Item;
class MetadataDatabase
{
public:
MetadataDatabase(DB &db, Configuration &c);
virtual ~MetadataDatabase();
bool Initialize();
bool ResetDatabase();
void UpdateMetadata(CollectionInfo *collection);
private:
Configuration &Config;
DB &DBInstance;
};

View File

@ -15,8 +15,8 @@
*/
#include "ComponentItemBindingBuilder.h"
#include "ComponentItemBinding.h"
#include "../Database/CollectionDatabase.h"
#include "../Collection/Item.h"
#include "../Utility/Log.h"
ComponentItemBindingBuilder::ComponentItemBindingBuilder()
{

View File

@ -17,6 +17,7 @@
#include "Page.h"
#include "ComponentItemBinding.h"
#include "Component/Component.h"
#include "../Collection/CollectionInfo.h"
#include "Component/Text.h"
#include "../Utility/Log.h"
#include "Component/ScrollingList.h"
@ -298,9 +299,9 @@ void Page::PageScroll(ScrollDirection direction)
}
void Page::SetItems(std::vector<Item *> *items)
void Page::SetCollection(CollectionInfo *collection)
{
std::vector<ComponentItemBinding *> *sprites = ComponentItemBindingBuilder::BuildCollectionItems(items);
std::vector<ComponentItemBinding *> *sprites = ComponentItemBindingBuilder::BuildCollectionItems(collection->GetItems());
if(Menu)
{
Menu->SetItems(sprites);

View File

@ -8,6 +8,7 @@
#include <vector>
#include <string>
class CollectionInfo;
class Component;
class Configuration;
class ScrollingList;
@ -29,7 +30,7 @@ public:
Page(std::string collectionName, Configuration &c);
virtual ~Page();
virtual void OnNewItemSelected(Item *);
void SetItems(std::vector<Item *> *items);
void SetCollection(CollectionInfo *collection);
void SetMenu(ScrollingList *s);
void SetLoadSound(Sound *chunk)
{

View File

@ -16,8 +16,6 @@
#include "Database/Configuration.h"
#include "Database/CollectionDatabase.h"
#include "Collection/CollectionInfoBuilder.h"
#include "Collection/CollectionInfo.h"
#include "Database/MamelistMetadata.h"
#include "Execute/Launcher.h"
#include "Utility/Log.h"
@ -30,7 +28,6 @@
static bool ImportConfiguration(Configuration *c);
static bool StartLogging();
CollectionDatabase *InitializeCollectionDatabase(DB &db, Configuration &config);
int main(int argc, char *argv[])
{

View File

@ -15,7 +15,8 @@
*/
#include "RetroFE.h"
#include "Database/CollectionDatabase.h"
#include "Collection/CollectionInfoBuilder.h"
#include "Collection/CollectionInfo.h"
#include "Database/Configuration.h"
#include "Collection/Item.h"
#include "Execute/Launcher.h"
@ -41,7 +42,6 @@ RetroFE::RetroFE(Configuration &c)
, InitializeThread(NULL)
, Config(c)
, Db(NULL)
, CollectionDB(NULL)
, Input(Config)
, KeyInputDisable(0)
, CurrentTime(0)
@ -53,30 +53,6 @@ RetroFE::~RetroFE()
DeInitialize();
}
CollectionDatabase *RetroFE::InitializeCollectionDatabase(DB &db, Configuration &config)
{
CollectionDatabase *cdb = NULL;
config.SetStatus("Initializing database");
std::string dbFile = (Configuration::GetAbsolutePath() + "/cache.db");
std::ifstream infile(dbFile.c_str());
cdb = new CollectionDatabase(db, config);
if(!cdb->Initialize())
{
delete cdb;
cdb = NULL;
}
else if(!cdb->Import())
{
delete cdb;
cdb = NULL;
}
return cdb;
}
void RetroFE::Render()
{
SDL_LockMutex(SDL::GetMutex());
@ -115,16 +91,6 @@ int RetroFE::Initialize(void *context)
return -1;
}
instance->CollectionDB = instance->InitializeCollectionDatabase(*instance->Db, instance->Config);
if(!instance->CollectionDB)
{
Logger::Write(Logger::ZONE_ERROR, "RetroFE", "Could not initialize CollectionDB!");
delete instance->Db;
return -1;
}
instance->Config.GetProperty("videoEnable", videoEnable);
instance->Config.GetProperty("videoLoop", videoLoop);
@ -204,11 +170,6 @@ bool RetroFE::DeInitialize()
Db = NULL;
}
if(CollectionDB)
{
delete CollectionDB;
Db = NULL;
}
Initialized = false;
//todo: handle video deallocation
return retVal;
@ -492,7 +453,8 @@ Page *RetroFE::LoadPage(std::string collectionName)
Page *page = NULL;
std::vector<Item *> *collection = GetCollection(collectionName);
Config.SetCurrentCollection(collectionName);
CollectionInfo *collection = GetCollection(collectionName);
std::string layoutName = GetLayout(collectionName);
if(PageChain.size() > 0)
@ -510,8 +472,7 @@ Page *RetroFE::LoadPage(std::string collectionName)
}
else
{
Config.SetCurrentCollection(collectionName);
page->SetItems(collection);
page->SetCollection(collection);
page->Start();
PageChain.push_back(page);
@ -522,11 +483,10 @@ Page *RetroFE::LoadPage(std::string collectionName)
Page *RetroFE::LoadSplashPage()
{
PageBuilder pb("Splash", "", Config, &FC);
std::vector<Item *> *coll = new std::vector<Item *>();
Page * page = pb.BuildPage();
// page->SetStatusText("foobar");
Config.SetCurrentCollection("");
page->SetItems(coll);
page->SetCollection(new CollectionInfo("", "", "", "", ""));
page->Start();
PageChain.push_back(page);
@ -534,16 +494,16 @@ Page *RetroFE::LoadSplashPage()
}
std::vector<Item *> *RetroFE::GetCollection(std::string collectionName)
CollectionInfo *RetroFE::GetCollection(std::string collectionName)
{
// the page will deallocate this once its done
std::vector<Item *> *collection = new std::vector<Item *>();
MenuParser mp;
mp.GetMenuItems(CollectionDB, collectionName, *collection);
CollectionDB->GetCollection(collectionName, *collection);
CollectionInfoBuilder cib(Config, *Db);
CollectionInfo *collection = cib.BuildCollection(collectionName);
mp.GetMenuItems(collection);
if(collection->size() == 0)
if(collection->GetItems()->size() == 0)
{
Logger::Write(Logger::ZONE_WARNING, "RetroFE", "No list items found for collection " + collectionName);
}

View File

@ -13,7 +13,7 @@
#include <list>
#include <vector>
class CollectionDatabase;
class CollectionInfo;
class Configuration;
class Page;
@ -47,7 +47,6 @@ private:
};
void Render();
CollectionDatabase *InitializeCollectionDatabase(DB &db, Configuration &config);
bool Back(bool &exit);
void Quit();
void WaitToInitialize();
@ -56,10 +55,9 @@ private:
RETROFE_STATE ProcessUserInput(Page *page);
void Update(float dt, bool scrollActive);
std::string GetLayout(std::string collectionName);
std::vector<Item *> *GetCollection(std::string collectionName);
CollectionInfo *GetCollection(std::string collectionName);
Configuration &Config;
DB *Db;
CollectionDatabase *CollectionDB;
UserInput Input;
std::list<Page *> PageChain;
float KeyInputDisable;