1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
5 #include <lib/service/servicefs.h>
6 #include <lib/service/service.h>
7 #include <lib/service/servicedvb.h>
8 #include <lib/base/init_num.h>
9 #include <lib/base/init.h>
11 #include <sys/types.h>
15 class eStaticServiceFSInformation: public iStaticServiceInformation
17 DECLARE_REF(eStaticServiceFSInformation);
19 RESULT getName(const eServiceReference &ref, std::string &name);
20 int getLength(const eServiceReference &ref) { return -1; }
23 DEFINE_REF(eStaticServiceFSInformation);
25 RESULT eStaticServiceFSInformation::getName(const eServiceReference &ref, std::string &name)
33 eServiceFactoryFS::eServiceFactoryFS()
35 ePtr<eServiceCenter> sc;
37 eServiceCenter::getPrivInstance(sc);
40 std::list<std::string> extensions;
41 sc->addServiceFactory(eServiceFactoryFS::id, this, extensions);
44 m_service_information = new eStaticServiceFSInformation();
47 eServiceFactoryFS::~eServiceFactoryFS()
49 ePtr<eServiceCenter> sc;
51 eServiceCenter::getPrivInstance(sc);
53 sc->removeServiceFactory(eServiceFactoryFS::id);
56 DEFINE_REF(eServiceFactoryFS)
59 RESULT eServiceFactoryFS::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
65 RESULT eServiceFactoryFS::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
71 RESULT eServiceFactoryFS::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
73 ptr = new eServiceFS(ref.path.c_str(), ref.getName().length() ? ref.getName().c_str() : 0);
77 RESULT eServiceFactoryFS::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
79 ptr = m_service_information;
83 RESULT eServiceFactoryFS::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
91 DEFINE_REF(eServiceFS);
93 eServiceFS::eServiceFS(const char *path, const char *additional_extensions): path(path)
96 if (additional_extensions)
98 size_t slen=strlen(additional_extensions);
100 char *tmp=0, *cmds = buf;
101 memcpy(buf, additional_extensions, slen+1);
103 // strip spaces at beginning
104 while(cmds[0] == ' ')
110 // strip spaces at the end
111 while(slen && cmds[slen-1] == ' ')
125 tmp = strchr(cmds, ' ');
128 if (strstr(cmds, "0x"))
130 if (sscanf(cmds, "0x%x:%s", &id, buf2) == 2)
131 m_additional_extensions[id].push_back(buf2);
133 eDebug("parse additional_extension (%s) failed", cmds);
137 if (sscanf(cmds, "%d:%s", &id, buf2) == 2)
138 m_additional_extensions[id].push_back(buf2);
140 eDebug("parse additional_extension (%s) failed", cmds);
145 while (*cmds && *cmds == ' ')
153 eServiceFS::~eServiceFS()
159 return std::tolower(static_cast<unsigned char>(c));
162 RESULT eServiceFS::getContent(std::list<eServiceReference> &list, bool sorted)
164 DIR *d=opendir(path.c_str());
167 while (dirent *e=readdir(d))
169 if (!(strcmp(e->d_name, ".") && strcmp(e->d_name, "..")))
172 std::string filename;
175 filename += e->d_name;
178 if (::stat(filename.c_str(), &s) < 0)
181 if (S_ISDIR(s.st_mode))
184 if (S_ISDIR(s.st_mode))
186 eServiceReference service(eServiceFactoryFS::id,
187 eServiceReference::isDirectory|
188 eServiceReference::canDescent|eServiceReference::mustDescent|
189 eServiceReference::shouldSort|eServiceReference::sort1,
192 list.push_back(service);
195 size_t e = filename.rfind('.');
196 if (e != std::string::npos && e+1 < filename.length())
198 std::string extension = filename.substr(e+1);
199 std::transform(extension.begin(), extension.end(), extension.begin(), lower);
200 int type = getServiceTypeForExtension(extension);
204 ePtr<eServiceCenter> sc;
205 eServiceCenter::getPrivInstance(sc);
206 type = sc->getServiceTypeForExtension(extension);
211 eServiceReference service(type,
215 list.push_back(service);
218 eDebug("unhandled extension %s", extension.c_str());
225 list.sort(iListableServiceCompare(this));
230 // The first argument of this function is a format string to specify the order and
231 // the content of the returned list
232 // useable format options are
233 // R = Service Reference (as swig object .. this is very slow)
234 // S = Service Reference (as python string object .. same as ref.toString())
235 // C = Service Reference (as python string object .. same as ref.toCompareString())
236 // N = Service Name (as python string object)
237 // when exactly one return value per service is selected in the format string,
238 // then each value is directly a list entry
239 // when more than one value is returned per service, then the list is a list of
241 // unknown format string chars are returned as python None values !
242 PyObject *eServiceFS::getContent(const char* format, bool sorted)
245 std::list<eServiceReference> tmplist;
248 if (!format || !(retcount=strlen(format)))
249 format = "R"; // just return service reference swig object ...
251 if (!getContent(tmplist, sorted))
253 int services=tmplist.size();
254 ePtr<iStaticServiceInformation> sptr;
255 eServiceCenterPtr service_center;
257 if (strchr(format, 'N'))
258 eServiceCenter::getPrivInstance(service_center);
260 ret = PyList_New(services);
261 std::list<eServiceReference>::iterator it(tmplist.begin());
263 for (int cnt=0; cnt < services; ++cnt)
265 eServiceReference &ref=*it++;
266 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
267 for (int i=0; i < retcount; ++i)
272 case 'R': // service reference (swig)object
273 tmp = NEW_eServiceReference(ref);
275 case 'C': // service reference compare string
276 tmp = PyString_FromString(ref.toCompareString().c_str());
278 case 'S': // service reference string
279 tmp = PyString_FromString(ref.toString().c_str());
281 case 'N': // service name
284 service_center->info(ref, sptr);
288 sptr->getName(ref, name);
290 tmp = PyString_FromString(name.c_str());
294 tmp = PyString_FromString("<n/a>");
307 PyTuple_SET_ITEM(tuple, i, tmp);
309 PyList_SET_ITEM(ret, cnt, tmp);
313 PyList_SET_ITEM(ret, cnt, tuple);
316 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
319 RESULT eServiceFS::getNext(eServiceReference &ptr)
324 int res = getContent(m_list);
331 ptr = eServiceReference();
335 ptr = m_list.front();
340 int eServiceFS::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
342 /* directories first */
343 if ((a.flags & ~b.flags) & eServiceReference::isDirectory)
345 else if ((~a.flags & b.flags) & eServiceReference::isDirectory)
347 /* sort by filename */
349 return a.path < b.path;
352 RESULT eServiceFS::startEdit(ePtr<iMutableServiceList> &res)
358 int eServiceFS::getServiceTypeForExtension(const char *str)
360 for (std::map<int, std::list<std::string> >::iterator sit(m_additional_extensions.begin()); sit != m_additional_extensions.end(); ++sit)
362 for (std::list<std::string>::iterator eit(sit->second.begin()); eit != sit->second.end(); ++eit)
371 int eServiceFS::getServiceTypeForExtension(const std::string &str)
373 return getServiceTypeForExtension(str.c_str());
376 eAutoInitPtr<eServiceFactoryFS> init_eServiceFactoryFS(eAutoInitNumbers::service+1, "eServiceFactoryFS");