mirror of
https://github.com/FunKey-Project/RetroFE.git
synced 2026-01-03 04:28:51 +01:00
Support ability to import hyperlist
This commit is contained in:
parent
898d2dedb3
commit
4072f25b14
@ -25,9 +25,9 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
CollectionInfoBuilder::CollectionInfoBuilder(Configuration &c, DB &db)
|
||||
CollectionInfoBuilder::CollectionInfoBuilder(Configuration &c, MetadataDatabase &mdb)
|
||||
: Conf(c)
|
||||
, MetaDB(db, c)
|
||||
, MetaDB(mdb)
|
||||
{
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ CollectionInfo *CollectionInfoBuilder::BuildCollection(std::string name)
|
||||
std::string listItemsPath;
|
||||
std::string launcherName;
|
||||
std::string extensions;
|
||||
std::string metadataType;
|
||||
std::string metadataType = name;
|
||||
std::string metadataPath;
|
||||
|
||||
Conf.GetCollectionAbsolutePath(name, listItemsPath);
|
||||
@ -137,7 +137,7 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info)
|
||||
}
|
||||
}
|
||||
|
||||
MetaDB.UpdateMetadata(info);
|
||||
MetaDB.InjectMetadata(info);
|
||||
|
||||
while(includeFilter.size() > 0)
|
||||
{
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../Database/DB.h"
|
||||
#include "../Database/MetadataDatabase.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
@ -16,12 +15,12 @@ class CollectionInfo;
|
||||
class CollectionInfoBuilder
|
||||
{
|
||||
public:
|
||||
CollectionInfoBuilder(Configuration &c, DB &db);
|
||||
CollectionInfoBuilder(Configuration &c, MetadataDatabase &mdb);
|
||||
virtual ~CollectionInfoBuilder();
|
||||
CollectionInfo *BuildCollection(std::string collectionName);
|
||||
|
||||
private:
|
||||
MetadataDatabase MetaDB;
|
||||
MetadataDatabase &MetaDB;
|
||||
bool ImportDirectory(CollectionInfo *info);
|
||||
Configuration &Conf;
|
||||
};
|
||||
|
||||
@ -47,12 +47,11 @@ MetadataDatabase::~MetadataDatabase()
|
||||
|
||||
bool MetadataDatabase::ResetDatabase()
|
||||
{
|
||||
bool retVal = true;
|
||||
int rc;
|
||||
char *error = NULL;
|
||||
sqlite3 *handle = DBInstance.GetHandle();
|
||||
|
||||
Logger::Write(Logger::ZONE_INFO, "Database", "Erasing");
|
||||
Logger::Write(Logger::ZONE_INFO, "Metadata", "Erasing");
|
||||
|
||||
std::string sql;
|
||||
sql.append("DROP TABLE IF EXISTS Meta;");
|
||||
@ -63,11 +62,11 @@ bool MetadataDatabase::ResetDatabase()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Unable to create Metadata table. Error: " << error;
|
||||
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
|
||||
retVal = false;
|
||||
Logger::Write(Logger::ZONE_ERROR, "Metadata", ss.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
||||
return Initialize();
|
||||
}
|
||||
|
||||
bool MetadataDatabase::Initialize()
|
||||
@ -94,15 +93,61 @@ bool MetadataDatabase::Initialize()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Unable to create Metadata table. Error: " << error;
|
||||
Logger::Write(Logger::ZONE_ERROR, "Database", ss.str());
|
||||
Logger::Write(Logger::ZONE_ERROR, "Metadata", ss.str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(NeedsRefresh())
|
||||
{
|
||||
ImportDirectory();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MetadataDatabase::UpdateMetadata(CollectionInfo *collection)
|
||||
bool MetadataDatabase::ImportDirectory()
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *dirp;
|
||||
std::string metaPath = "Meta";
|
||||
dp = opendir(metaPath.c_str());
|
||||
|
||||
while((dirp = readdir(dp)) != NULL)
|
||||
{
|
||||
if (dirp->d_type != DT_DIR && std::string(dirp->d_name) != "." && std::string(dirp->d_name) != "..")
|
||||
{
|
||||
|
||||
std::string basename = dirp->d_name;
|
||||
|
||||
// if(basename.length() > 0)
|
||||
{
|
||||
std::string extension = basename.substr(basename.find_last_of("."), basename.size()-1);
|
||||
basename = basename.substr(0, basename.find_last_of("."));
|
||||
std::string collectionName = basename.substr(0, basename.find_first_of("."));
|
||||
|
||||
|
||||
std::string type = "";
|
||||
|
||||
if(collectionName.length() < basename.length())
|
||||
{
|
||||
type = basename.substr(collectionName.length() + 1, basename.size());
|
||||
}
|
||||
|
||||
if(type == "hyperlist" && extension == ".xml")
|
||||
{
|
||||
std::string importFile = Configuration::GetAbsolutePath() + "/" + metaPath + "/" + dirp->d_name;
|
||||
Logger::Write(Logger::ZONE_INFO, "Metadata", "Importing hyperlist: " + importFile);
|
||||
ImportHyperList(importFile, collectionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MetadataDatabase::InjectMetadata(CollectionInfo *collection)
|
||||
{
|
||||
sqlite3 *handle = DBInstance.GetHandle();
|
||||
int rc;
|
||||
@ -130,7 +175,7 @@ void MetadataDatabase::UpdateMetadata(CollectionInfo *collection)
|
||||
"FROM Meta WHERE collectionName=? ORDER BY title ASC;",
|
||||
-1, &stmt, 0);
|
||||
|
||||
sqlite3_bind_text(stmt, 1, collection->GetName().c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 1, collection->GetMetadataType().c_str(), -1, SQLITE_TRANSIENT);
|
||||
|
||||
rc = sqlite3_step(stmt);
|
||||
|
||||
@ -196,3 +241,114 @@ void MetadataDatabase::UpdateMetadata(CollectionInfo *collection)
|
||||
rc = sqlite3_step(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
bool MetadataDatabase::NeedsRefresh()
|
||||
{
|
||||
sqlite3 *handle = DBInstance.GetHandle();
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
sqlite3_prepare_v2(handle,
|
||||
"SELECT COUNT(*) FROM Meta;",
|
||||
-1, &stmt, 0);
|
||||
|
||||
int rc = sqlite3_step(stmt);
|
||||
|
||||
if(rc == SQLITE_ROW)
|
||||
{
|
||||
int count = sqlite3_column_int(stmt, 0);
|
||||
|
||||
return (count == 0) ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool MetadataDatabase::ImportHyperList(std::string hyperlistFile, std::string collectionName)
|
||||
{
|
||||
bool retVal = false;
|
||||
char *error = NULL;
|
||||
rapidxml::xml_document<> doc;
|
||||
std::ifstream file(hyperlistFile.c_str());
|
||||
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||
|
||||
try
|
||||
{
|
||||
buffer.push_back('\0');
|
||||
|
||||
doc.parse<0>(&buffer[0]);
|
||||
|
||||
rapidxml::xml_node<> *root = doc.first_node("menu");
|
||||
|
||||
if(!root)
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "Metadata", "Does not appear to be a HyperList file (missing <menu> tag)");
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlite3 *handle = DBInstance.GetHandle();
|
||||
sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error);
|
||||
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)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
sqlite3_prepare_v2(handle,
|
||||
"INSERT OR REPLACE INTO Meta (name, title, year, manufacturer, cloneOf, collectionName) VALUES (?,?,?,?,?,?)",
|
||||
-1, &stmt, 0);
|
||||
|
||||
sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 2, description.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 3, year.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 4, manufacturer.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 5, cloneOf.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 6, collectionName.c_str(), -1, SQLITE_TRANSIENT);
|
||||
|
||||
sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
}
|
||||
sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error);
|
||||
}
|
||||
}
|
||||
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, "Metadata", ss.str());
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
std::string what = e.what();
|
||||
Logger::Write(Logger::ZONE_ERROR, "Metadata", "Could not parse hyperlist file. Reason: " + what);
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@ -20,9 +20,12 @@ public:
|
||||
bool Initialize();
|
||||
bool ResetDatabase();
|
||||
|
||||
void UpdateMetadata(CollectionInfo *collection);
|
||||
void InjectMetadata(CollectionInfo *collection);
|
||||
bool ImportHyperList(std::string hyperlistFile, std::string collectionName);
|
||||
|
||||
private:
|
||||
bool ImportDirectory();
|
||||
bool NeedsRefresh();
|
||||
Configuration &Config;
|
||||
DB &DBInstance;
|
||||
};
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
#include "Database/Configuration.h"
|
||||
#include "Database/CollectionDatabase.h"
|
||||
#include "Database/MamelistMetadata.h"
|
||||
#include "Execute/Launcher.h"
|
||||
#include "Utility/Log.h"
|
||||
|
||||
@ -91,6 +91,14 @@ int RetroFE::Initialize(void *context)
|
||||
return -1;
|
||||
}
|
||||
|
||||
instance->MetaDb = new MetadataDatabase(*(instance->Db), instance->Config);
|
||||
|
||||
if(!instance->MetaDb->Initialize())
|
||||
{
|
||||
Logger::Write(Logger::ZONE_ERROR, "RetroFE", "Could not initialize meta database");
|
||||
return -1;
|
||||
}
|
||||
|
||||
instance->Config.GetProperty("videoEnable", videoEnable);
|
||||
instance->Config.GetProperty("videoLoop", videoLoop);
|
||||
|
||||
@ -164,6 +172,12 @@ bool RetroFE::DeInitialize()
|
||||
delete page;
|
||||
PageChain.pop_back();
|
||||
}
|
||||
if(MetaDb)
|
||||
{
|
||||
delete MetaDb;
|
||||
MetaDb = NULL;
|
||||
}
|
||||
|
||||
if(Db)
|
||||
{
|
||||
delete Db;
|
||||
@ -499,7 +513,7 @@ CollectionInfo *RetroFE::GetCollection(std::string collectionName)
|
||||
// the page will deallocate this once its done
|
||||
MenuParser mp;
|
||||
|
||||
CollectionInfoBuilder cib(Config, *Db);
|
||||
CollectionInfoBuilder cib(Config, *MetaDb);
|
||||
CollectionInfo *collection = cib.BuildCollection(collectionName);
|
||||
mp.GetMenuItems(collection);
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "Collection/Item.h"
|
||||
#include "Control/UserInput.h"
|
||||
#include "Database/DB.h"
|
||||
#include "Database/MetadataDatabase.h"
|
||||
#include "Execute/AttractMode.h"
|
||||
#include "Graphics/FontCache.h"
|
||||
#include "Video/IVideo.h"
|
||||
@ -58,6 +59,7 @@ private:
|
||||
CollectionInfo *GetCollection(std::string collectionName);
|
||||
Configuration &Config;
|
||||
DB *Db;
|
||||
MetadataDatabase *MetaDb;
|
||||
UserInput Input;
|
||||
std::list<Page *> PageChain;
|
||||
float KeyInputDisable;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user