X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5..62f0db333dd61a779e0545142a4f6d2c7daad52e:/lib/service/servicefs.cpp diff --git a/lib/service/servicefs.cpp b/lib/service/servicefs.cpp index ad40f0af..a225ae07 100644 --- a/lib/service/servicefs.cpp +++ b/lib/service/servicefs.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -11,22 +12,43 @@ #include #include +class eStaticServiceFSInformation: public iStaticServiceInformation +{ + DECLARE_REF(eStaticServiceFSInformation); +public: + RESULT getName(const eServiceReference &ref, std::string &name); + int getLength(const eServiceReference &ref) { return -1; } +}; + +DEFINE_REF(eStaticServiceFSInformation); + +RESULT eStaticServiceFSInformation::getName(const eServiceReference &ref, std::string &name) +{ + name = ref.path; + return 0; +} + // eServiceFactoryFS -eServiceFactoryFS::eServiceFactoryFS(): ref(0) +eServiceFactoryFS::eServiceFactoryFS() { ePtr sc; - eServiceCenter::getInstance(sc); + eServiceCenter::getPrivInstance(sc); if (sc) - sc->addServiceFactory(eServiceFactoryFS::id, this); + { + std::list extensions; + sc->addServiceFactory(eServiceFactoryFS::id, this, extensions); + } + + m_service_information = new eStaticServiceFSInformation(); } eServiceFactoryFS::~eServiceFactoryFS() { ePtr sc; - eServiceCenter::getInstance(sc); + eServiceCenter::getPrivInstance(sc); if (sc) sc->removeServiceFactory(eServiceFactoryFS::id); } @@ -48,23 +70,96 @@ RESULT eServiceFactoryFS::record(const eServiceReference &ref, ePtr &ptr) { - ptr = new eServiceFS(ref.path.c_str()); + ptr = new eServiceFS(ref.path.c_str(), ref.getName().length() ? ref.getName().c_str() : 0); return 0; } +RESULT eServiceFactoryFS::info(const eServiceReference &ref, ePtr &ptr) +{ + ptr = m_service_information; + return 0; +} + +RESULT eServiceFactoryFS::offlineOperations(const eServiceReference &, ePtr &ptr) +{ + ptr = 0; + return -1; +} + // eServiceFS DEFINE_REF(eServiceFS); -eServiceFS::eServiceFS(const char *path): ref(0), path(path) +eServiceFS::eServiceFS(const char *path, const char *additional_extensions): path(path) { + m_list_valid = 0; + if (additional_extensions) + { + size_t slen=strlen(additional_extensions); + char buf[slen+1]; + char *tmp=0, *cmds = buf; + memcpy(buf, additional_extensions, slen+1); + + // strip spaces at beginning + while(cmds[0] == ' ') + { + ++cmds; + --slen; + } + + // strip spaces at the end + while(slen && cmds[slen-1] == ' ') + { + cmds[slen-1] = 0; + --slen; + } + + if (slen) + { + if (*cmds) + { + int id; + char buf2[16]; + while(1) + { + tmp = strchr(cmds, ' '); + if (tmp) + *tmp = 0; + if (strstr(cmds, "0x")) + { + if (sscanf(cmds, "0x%x:%s", &id, buf2) == 2) + m_additional_extensions[id].push_back(buf2); + else + eDebug("parse additional_extension (%s) failed", cmds); + } + else + { + if (sscanf(cmds, "%d:%s", &id, buf2) == 2) + m_additional_extensions[id].push_back(buf2); + else + eDebug("parse additional_extension (%s) failed", cmds); + } + if (!tmp) + break; + cmds = tmp+1; + while (*cmds && *cmds == ' ') + ++cmds; + } + } + } + } } eServiceFS::~eServiceFS() { } -RESULT eServiceFS::getContent(std::list &list) +int lower(char c) +{ + return std::tolower(static_cast(c)); +} + +RESULT eServiceFS::getContent(std::list &list, bool sorted) { DIR *d=opendir(path.c_str()); if (!d) @@ -74,7 +169,7 @@ RESULT eServiceFS::getContent(std::list &list) if (!(strcmp(e->d_name, ".") && strcmp(e->d_name, ".."))) continue; - eString filename; + std::string filename; filename = path; filename += e->d_name; @@ -97,16 +192,183 @@ RESULT eServiceFS::getContent(std::list &list) list.push_back(service); } else { - eServiceReference service(eServiceFactoryFS::id, - eServiceReference::isDirectory| - eServiceReference::canDescent|eServiceReference::mustDescent| - eServiceReference::shouldSort|eServiceReference::sort1, - filename); - service.data[0] = 0; - list.push_back(service); + size_t e = filename.rfind('.'); + if (e != std::string::npos && e+1 < filename.length()) + { + std::string extension = filename.substr(e+1); + std::transform(extension.begin(), extension.end(), extension.begin(), lower); + int type = getServiceTypeForExtension(extension); + + if (type == -1) + { + ePtr sc; + eServiceCenter::getPrivInstance(sc); + type = sc->getServiceTypeForExtension(extension); + } + + if (type != -1) + { + eServiceReference service(type, + 0, + filename); + service.data[0] = 0; + list.push_back(service); + } + } } } + closedir(d); + + if (sorted) + list.sort(iListableServiceCompare(this)); + return 0; } -eAutoInitP0 init_eServiceFactoryFS(eAutoInitNumbers::service+1, "eServiceFactoryFS"); +// The first argument of this function is a format string to specify the order and +// the content of the returned list +// useable format options are +// R = Service Reference (as swig object .. this is very slow) +// S = Service Reference (as python string object .. same as ref.toString()) +// C = Service Reference (as python string object .. same as ref.toCompareString()) +// N = Service Name (as python string object) +// when exactly one return value per service is selected in the format string, +// then each value is directly a list entry +// when more than one value is returned per service, then the list is a list of +// python tuples +// unknown format string chars are returned as python None values ! +PyObject *eServiceFS::getContent(const char* format, bool sorted) +{ + ePyObject ret; + std::list tmplist; + int retcount=1; + + if (!format || !(retcount=strlen(format))) + format = "R"; // just return service reference swig object ... + + if (!getContent(tmplist, sorted)) + { + int services=tmplist.size(); + ePtr sptr; + eServiceCenterPtr service_center; + + if (strchr(format, 'N')) + eServiceCenter::getPrivInstance(service_center); + + ret = PyList_New(services); + std::list::iterator it(tmplist.begin()); + + for (int cnt=0; cnt < services; ++cnt) + { + eServiceReference &ref=*it++; + ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject(); + for (int i=0; i < retcount; ++i) + { + ePyObject tmp; + switch(format[i]) + { + case 'R': // service reference (swig)object + tmp = NEW_eServiceReference(ref); + break; + case 'C': // service reference compare string + tmp = PyString_FromString(ref.toCompareString().c_str()); + break; + case 'S': // service reference string + tmp = PyString_FromString(ref.toString().c_str()); + break; + case 'N': // service name + if (service_center) + { + service_center->info(ref, sptr); + if (sptr) + { + std::string name; + sptr->getName(ref, name); + if (name.length()) + tmp = PyString_FromString(name.c_str()); + } + } + if (!tmp) + tmp = PyString_FromString(""); + break; + default: + if (tuple) + { + tmp = Py_None; + Py_INCREF(Py_None); + } + break; + } + if (tmp) + { + if (tuple) + PyTuple_SET_ITEM(tuple, i, tmp); + else + PyList_SET_ITEM(ret, cnt, tmp); + } + } + if (tuple) + PyList_SET_ITEM(ret, cnt, tuple); + } + } + return ret ? (PyObject*)ret : (PyObject*)PyList_New(0); +} + +RESULT eServiceFS::getNext(eServiceReference &ptr) +{ + if (!m_list_valid) + { + m_list_valid = 1; + int res = getContent(m_list); + if (res) + return res; + } + + if (!m_list.size()) + { + ptr = eServiceReference(); + return -ERANGE; + } + + ptr = m_list.front(); + m_list.pop_front(); + return 0; +} + +int eServiceFS::compareLessEqual(const eServiceReference &a, const eServiceReference &b) +{ + /* directories first */ + if ((a.flags & ~b.flags) & eServiceReference::isDirectory) + return 1; + else if ((~a.flags & b.flags) & eServiceReference::isDirectory) + return 0; + /* sort by filename */ + else + return a.path < b.path; +} + +RESULT eServiceFS::startEdit(ePtr &res) +{ + res = 0; + return -1; +} + +int eServiceFS::getServiceTypeForExtension(const char *str) +{ + for (std::map >::iterator sit(m_additional_extensions.begin()); sit != m_additional_extensions.end(); ++sit) + { + for (std::list::iterator eit(sit->second.begin()); eit != sit->second.end(); ++eit) + { + if (*eit == str) + return sit->first; + } + } + return -1; +} + +int eServiceFS::getServiceTypeForExtension(const std::string &str) +{ + return getServiceTypeForExtension(str.c_str()); +} + +eAutoInitPtr init_eServiceFactoryFS(eAutoInitNumbers::service+1, "eServiceFactoryFS");