diff options
-rw-r--r-- | common/tools.cpp | 12 | ||||
-rw-r--r-- | include/media/mediaManager.h | 1 | ||||
-rw-r--r-- | include/server.h | 2 | ||||
-rw-r--r-- | include/tools/string.h | 1 | ||||
-rw-r--r-- | media/mediaManager.cpp | 21 | ||||
-rw-r--r-- | plugins/provider/fileProvider/fileProvider.cpp | 87 | ||||
-rw-r--r-- | server/server.cpp | 6 | ||||
-rw-r--r-- | upnp.cpp | 3 |
8 files changed, 111 insertions, 22 deletions
diff --git a/common/tools.cpp b/common/tools.cpp index 6f02d2a..1e40ccc 100644 --- a/common/tools.cpp +++ b/common/tools.cpp @@ -74,6 +74,18 @@ StringVector GetNetworkInterfaces(bool skipLoop){ return interfaces; } +string Trim(const std::string& str, const std::string& whitespace) +{ + const unsigned long int strBegin = str.find_first_not_of(whitespace); + if (strBegin == std::string::npos) + return ""; // no content + + const unsigned long int strEnd = str.find_last_not_of(whitespace); + const unsigned long int strRange = strEnd - strBegin + 1; + + return str.substr(strBegin, strRange); +} + string ToString(long number){ stringstream ss; ss << number; diff --git a/include/media/mediaManager.h b/include/media/mediaManager.h index 40aa49f..9857d50 100644 --- a/include/media/mediaManager.h +++ b/include/media/mediaManager.h @@ -60,6 +60,7 @@ public: void SetDatabaseDir(const string& file); bool Initialise(); + void Housekeeping(); uint32_t GetSystemUpdateID() const; IdList GetContainerUpdateIDs(bool unevented = false); diff --git a/include/server.h b/include/server.h index ebdee03..be76e41 100644 --- a/include/server.h +++ b/include/server.h @@ -75,6 +75,8 @@ public: static void RegisterService(cUPnPService* service); + void Housekeeping(); + private: cMediaServer(); diff --git a/include/tools/string.h b/include/tools/string.h index 0ff5434..8d54706 100644 --- a/include/tools/string.h +++ b/include/tools/string.h @@ -21,6 +21,7 @@ string ToString(long number); string StringListToCSV(StringList list); string IdListToCSV(IdList list); void StringExplode(string str, string separator, StringVector& results); +string Trim(const std::string& str, const std::string& whitespace = " \t"); } diff --git a/media/mediaManager.cpp b/media/mediaManager.cpp index 670a158..5618817 100644 --- a/media/mediaManager.cpp +++ b/media/mediaManager.cpp @@ -112,8 +112,7 @@ cMediaManager::cMediaManager() cMediaManager::~cMediaManager(){ try { - tntdb::Statement stmt = connection.prepare("VACUUM"); - stmt.execute(); + connection.execute("VACUUM"); } catch (const std::exception& e) { esyslog("UPnP\tFailed to vacuum database '%s': '%s'", databaseFile.c_str(), e.what()); } @@ -466,6 +465,14 @@ cMediaManager::BrowseFlag cMediaManager::ToBrowseFlag(const std::string& browseF return NumBrowseFlags; } +void cMediaManager::Housekeeping(){ + try { + connection.execute("VACUUM"); + } catch (const std::exception& e) { + esyslog("UPnP\tFailed to vacuum database '%s': '%s'", databaseFile.c_str(), e.what()); + } +} + bool cMediaManager::Initialise(){ try { @@ -614,9 +621,12 @@ bool cMediaManager::Initialise(){ bool cMediaManager::CheckIntegrity(){ - tntdb::Statement enableForeignKeys = connection.prepare("PRAGMA foreign_keys = ON"); - - enableForeignKeys.execute(); + connection.execute("PRAGMA foreign_keys = ON"); + connection.execute("PRAGMA page_size = 4096"); + connection.execute("PRAGMA cache_size = 16384"); + connection.execute("PRAGMA temp_store = MEMORY"); + connection.execute("PRAGMA synchronous = OFF"); + connection.execute("PRAGMA locking_mode = EXCLUSIVE"); tntdb::Statement checkTable = connection.prepare( "SELECT name FROM sqlite_master WHERE type='table' AND name=:table;" @@ -747,7 +757,6 @@ bool cMediaManager::ScanURI(const string& uri, cUPnPResourceProvider* provider){ } } - isyslog("UPnP\tUnsupported resource: '%s' skipped.", uri.c_str()); return false; } else { diff --git a/plugins/provider/fileProvider/fileProvider.cpp b/plugins/provider/fileProvider/fileProvider.cpp index 15abc10..cbc84c2 100644 --- a/plugins/provider/fileProvider/fileProvider.cpp +++ b/plugins/provider/fileProvider/fileProvider.cpp @@ -7,6 +7,11 @@ #include <plugin.h> #include <fstream> +#include <sstream> +#include <tools/string.h> +#include <vdr/plugin.h> +#include <pwd.h> +#include <unistd.h> using namespace std; @@ -18,31 +23,44 @@ private: StringMap directoryMap; FILE* fileFD; + bool IsRootContainer(const string& uri){ + if(uri.find(GetRootContainer(), 0) != 0){ + isyslog("RecProvider\tUri does not contain the root."); + return false; + } else { + return true; + } + } + bool Load(const string& filename) { - bool result = false; if (access(filename.c_str(), F_OK) == 0) { isyslog("loading %s", filename.c_str()); ifstream file; file.open(filename.c_str(), ifstream::in); + if(!file.is_open()) + return false; string line; int pos; while(getline(file, line)){ if(line.length() > 0 && line[0] != '#'){ if((pos = line.find_first_of(':')) != string::npos){ - directoryMap[line.substr(0,pos)] = line.substr(pos+1); + directoryMap[tools::Trim(line.substr(0,pos))] = tools::Trim(line.substr(pos+1)); } } } + return true; } - return result; + return false; } string GetFile(const string& uri){ - string mountPoint = uri.substr(6, uri.find_first_of('/',6) - 7); + string mountPoint = uri.substr(7, uri.find_first_of('/',7) - 7); string file; if(!mountPoint.empty() && !directoryMap[mountPoint].empty()){ - file = directoryMap[mountPoint] + uri.substr(uri.find_first_of('/',6)); + file = directoryMap[mountPoint]; + if(uri.find_first_of('/', 7) != string::npos) + file += uri.substr(uri.find_first_of('/',7)); } return file; @@ -60,6 +78,14 @@ private: public: + FileProvider() + : fileFD(NULL) + { + stringstream file; + file << cPlugin::ConfigDirectory(PLUGIN_NAME_I18N) << "/directories.conf"; + Load(file.str()); + } + virtual string ProvidesSchema() { return "file"; } virtual string GetRootContainer() { @@ -68,7 +94,8 @@ public: virtual bool IsContainer(const string& uri) { struct stat fileStat; - if(GetFileStat(uri, fileStat) && S_ISDIR(fileStat.st_mode)) return true; + if(GetRootContainer().compare(uri) == 0 || (GetFileStat(uri, fileStat) && S_ISDIR(fileStat.st_mode))) + return true; return false; } @@ -95,22 +122,52 @@ public: DIR* dirHandle; struct dirent* dirEntry; - if((dirHandle = opendir(GetFile(uri).c_str())) == NULL){ - return list; - } + if(GetRootContainer().compare(uri) == 0){ + for( StringMap::iterator it = directoryMap.begin(); it != directoryMap.end(); ++it ) { + list.push_back( it->first + "/" ); + } + } else { + if((dirHandle = opendir(GetFile(uri).c_str())) == NULL){ + return list; + } - string filename; - while ((dirEntry = readdir(dirHandle)) != NULL) { - filename = dirEntry->d_name; - if(filename.compare(".") || filename.compare("..")){ - list.push_back(filename); + string filename; + while ((dirEntry = readdir(dirHandle)) != NULL) { + filename = dirEntry->d_name; + if( filename.compare(".") != 0 && filename.compare("..") != 0 ) { + if(dirEntry->d_type == DT_DIR) { + filename += "/"; + } + list.push_back(filename); + } } + closedir(dirHandle); } - closedir(dirHandle); return list; } + virtual bool GetMetadata(const string& uri, cMetadata& metadata){ + if(!IsRootContainer(uri)) return false; + + if(!cUPnPResourceProvider::GetMetadata(uri, metadata)) return false; + + if(GetRootContainer().compare(uri) == 0){ + metadata.SetProperty(cMetadata::Property(property::object::KEY_TITLE, string("File system"))); + metadata.SetProperty(cMetadata::Property(property::object::KEY_DESCRIPTION, string("Access files on the file system"))); + } + + struct passwd *pw; + if((pw = getpwuid(getuid())) == NULL){ + metadata.SetProperty(cMetadata::Property(property::object::KEY_CREATOR, string("Klaus Schmidinger"))); + } else { + string name(pw->pw_gecos); name = name.substr(0,name.find(",,,",0)); + metadata.SetProperty(cMetadata::Property(property::object::KEY_CREATOR, name)); + } + + return true; + } + virtual bool Seekable() const { return true; } diff --git a/server/server.cpp b/server/server.cpp index 1dfe605..b397a94 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -159,6 +159,12 @@ bool cMediaServer::Stop(){ return true; } +void cMediaServer::Housekeeping(){ + if(mMediaManager){ + mMediaManager->Housekeeping(); + } +} + bool cMediaServer::Initialize(){ string address; uint16_t port = 0; @@ -91,7 +91,8 @@ cString cPluginUpnp::Active(void) void cPluginUpnp::Housekeeping(void) { - // Perform any cleanup or other regular tasks. + if(mMediaServer) + mMediaServer->Housekeeping(); } void cPluginUpnp::MainThreadHook(void) |