fixes bug #288
[enigma2.git] / lib / service / service.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/estring.h>
3 #include <lib/python/python.h>
4 #include <lib/service/service.h>
5 #include <lib/base/init_num.h>
6 #include <lib/base/init.h>
7 #include <lib/python/python.h>
8
9 static std::string encode(const std::string s)
10 {
11         int len = s.size();
12         std::string res;
13         int i;
14         for (i=0; i<len; ++i)
15         {
16                 unsigned char c = s[i];
17                 if ((c == ':') || (c < 32) || (c == '%'))
18                 {
19                         res += "%";
20                         char hex[8];
21                         snprintf(hex, 8, "%02x", c);
22                         res += hex;
23                 } else
24                         res += c;
25         }
26         return res;
27 }
28
29 static std::string decode(const std::string s)
30 {
31         int len = s.size();
32         std::string res;
33         int i;
34         for (i=0; i<len; ++i)
35         {
36                 unsigned char c = s[i];
37                 if (c != '%')
38                         res += c;
39                 else
40                 {
41                         i += 2;
42                         if (i >= len)
43                                 break;
44                         char t[3] = {s[i - 1], s[i], 0};
45                         unsigned char r = strtoul(t, 0, 0x10);
46                         if (r)
47                                 res += r;
48                 }
49         }
50         return res;
51 }
52
53
54 eServiceReference::eServiceReference(const std::string &string)
55 {
56         const char *c=string.c_str();
57         int pathl=0;
58
59         if (!string.length())
60                 type = idInvalid;
61         else if ( sscanf(c, "%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%n", &type, &flags, &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7], &pathl) < 8 )
62         {
63                 memset( data, 0, sizeof(data) );
64                 eDebug("find old format eServiceReference string");
65                 if ( sscanf(c, "%d:%d:%x:%x:%x:%x:%n", &type, &flags, &data[0], &data[1], &data[2], &data[3], &pathl) < 2 )
66                         type = idInvalid;
67         }
68
69         if (pathl)
70         {
71                 const char *pathstr = c+pathl;
72                 const char *namestr = strchr(pathstr, ':');
73                 if (namestr)
74                 {
75                         if (pathstr != namestr)
76                                 path.assign(pathstr, namestr-pathstr);
77                         if (*(namestr+1))
78                                 name=namestr+1;
79                 }
80                 else
81                         path=pathstr;
82         }
83         
84         path = decode(path);
85         name = decode(name);
86 }
87
88 std::string eServiceReference::toString() const
89 {
90         std::string ret;
91         ret += getNum(type);
92         ret += ":";
93         ret += getNum(flags);
94         for (unsigned int i=0; i<sizeof(data)/sizeof(*data); ++i)
95                 ret+=":"+ getNum(data[i], 0x10);
96         ret+=":"+encode(path); /* we absolutely have a problem when the path contains a ':' (for example: http://). we need an encoding here. */
97         if (name.length())
98                 ret+=":"+encode(name);
99         return ret;
100 }
101
102 std::string eServiceReference::toCompareString() const
103 {
104         std::string ret;
105         ret += getNum(type);
106         ret += ":0";
107         for (unsigned int i=0; i<sizeof(data)/sizeof(*data); ++i)
108                 ret+=":"+getNum(data[i], 0x10);
109         ret+=":"+encode(path);
110         return ret;
111 }
112
113 eServiceCenter *eServiceCenter::instance;
114
115 eServiceCenter::eServiceCenter()
116 {
117         if (!instance)
118         {
119                 eDebug("settings instance.");
120                 instance = this;
121         }
122 }
123
124 eServiceCenter::~eServiceCenter()
125 {
126         if (instance == this)
127         {
128                 eDebug("clear instance");
129                 instance = 0;
130         }
131 }
132
133 DEFINE_REF(eServiceCenter);
134
135 RESULT eServiceCenter::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
136 {
137         std::map<int,ePtr<iServiceHandler> >::iterator i = handler.find(ref.type);
138         if (i == handler.end())
139         {
140                 ptr = 0;
141                 return -1;
142         }
143         return i->second->play(ref, ptr);
144 }
145
146 RESULT eServiceCenter::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
147 {
148         std::map<int,ePtr<iServiceHandler> >::iterator i = handler.find(ref.type);
149         if (i == handler.end())
150         {
151                 ptr = 0;
152                 return -1;
153         }
154         return i->second->record(ref, ptr);
155 }
156
157 RESULT eServiceCenter::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
158 {
159         std::map<int,ePtr<iServiceHandler> >::iterator i = handler.find(ref.type);
160         if (i == handler.end())
161         {
162                 ptr = 0;
163                 return -1;
164         }
165         return i->second->list(ref, ptr);
166 }
167
168 RESULT eServiceCenter::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
169 {
170         std::map<int,ePtr<iServiceHandler> >::iterator i = handler.find(ref.type);
171         if (i == handler.end())
172         {
173                 ptr = 0;
174                 return -1;
175         }
176         return i->second->info(ref, ptr);
177 }
178
179 RESULT eServiceCenter::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
180 {
181         std::map<int,ePtr<iServiceHandler> >::iterator i = handler.find(ref.type);
182         if (i == handler.end())
183         {
184                 ptr = 0;
185                 return -1;
186         }
187         return i->second->offlineOperations(ref, ptr);
188 }
189
190 RESULT eServiceCenter::addServiceFactory(int id, iServiceHandler *hnd, std::list<std::string> &extensions)
191 {
192         handler.insert(std::pair<int,ePtr<iServiceHandler> >(id, hnd));
193         this->extensions[id]=extensions;
194         return 0;
195 }
196
197 RESULT eServiceCenter::removeServiceFactory(int id)
198 {
199         handler.erase(id);
200         extensions.erase(id);
201         return 0;
202 }
203
204 int eServiceCenter::getServiceTypeForExtension(const char *str)
205 {
206         for (std::map<int, std::list<std::string> >::iterator sit(extensions.begin()); sit != extensions.end(); ++sit)
207         {
208                 for (std::list<std::string>::iterator eit(sit->second.begin()); eit != sit->second.end(); ++eit)
209                 {
210                         if (*eit == str)
211                                 return sit->first;
212                 }
213         }
214         return -1;
215 }
216
217 int eServiceCenter::getServiceTypeForExtension(const std::string &str)
218 {
219         return getServiceTypeForExtension(str.c_str());
220 }
221
222         /* default handlers */
223 RESULT iServiceHandler::info(const eServiceReference &, ePtr<iStaticServiceInformation> &ptr)
224 {
225         ptr = 0;
226         return -1;
227 }
228
229 #include <lib/service/event.h>
230
231 RESULT iStaticServiceInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
232 {
233         evt = 0;
234         return -1;
235 }
236
237 int iStaticServiceInformation::getLength(const eServiceReference &ref)
238 {
239         return -1;
240 }
241
242 int iStaticServiceInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
243 {
244         return 0;
245 }
246
247 RESULT iServiceInformation::getEvent(ePtr<eServiceEvent> &evt, int m_nownext)
248 {
249         evt = 0;
250         return -1;
251 }
252
253 int iStaticServiceInformation::getInfo(const eServiceReference &ref, int w)
254 {
255         return -1;
256 }
257
258 std::string iStaticServiceInformation::getInfoString(const eServiceReference &ref, int w)
259 {
260         return "";
261 }
262
263 PyObject *iStaticServiceInformation::getInfoObject(const eServiceReference &ref, int w)
264 {
265         Py_RETURN_NONE;
266 }
267
268 int iServiceInformation::getInfo(int w)
269 {
270         return -1;
271 }
272
273 std::string iServiceInformation::getInfoString(int w)
274 {
275         return "";
276 }
277
278 PyObject* iServiceInformation::getInfoObject(int w)
279 {
280         Py_RETURN_NONE;
281 }
282
283 int iStaticServiceInformation::setInfo(const eServiceReference &ref, int w, int v)
284 {
285         return -1;
286 }
287
288 int iStaticServiceInformation::setInfoString(const eServiceReference &ref, int w, const char *v)
289 {
290         return -1;
291 }
292
293 int iServiceInformation::setInfo(int w, int v)
294 {
295         return -1;
296 }
297
298 int iServiceInformation::setInfoString(int w, const char *v)
299 {
300         return -1;
301 }
302
303 eAutoInitPtr<eServiceCenter> init_eServiceCenter(eAutoInitNumbers::service, "eServiceCenter");