more work on servicem2ts
[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 RESULT eServiceCenter::addFactoryExtension(int id, const char *extension)
205 {
206         std::map<int, std::list<std::string> >::iterator it = extensions.find(id);
207         if (it == extensions.end())
208                 return -1;
209         it->second.push_back(extension);
210         return 0;
211 }
212
213 RESULT eServiceCenter::removeFactoryExtension(int id, const char *extension)
214 {
215         std::map<int, std::list<std::string> >::iterator it = extensions.find(id);
216         if (it == extensions.end())
217                 return -1;
218         it->second.remove(extension);
219         return 0;
220 }
221
222
223 int eServiceCenter::getServiceTypeForExtension(const char *str)
224 {
225         for (std::map<int, std::list<std::string> >::iterator sit(extensions.begin()); sit != extensions.end(); ++sit)
226         {
227                 for (std::list<std::string>::iterator eit(sit->second.begin()); eit != sit->second.end(); ++eit)
228                 {
229                         if (*eit == str)
230                                 return sit->first;
231                 }
232         }
233         return -1;
234 }
235
236 int eServiceCenter::getServiceTypeForExtension(const std::string &str)
237 {
238         return getServiceTypeForExtension(str.c_str());
239 }
240
241         /* default handlers */
242 RESULT iServiceHandler::info(const eServiceReference &, ePtr<iStaticServiceInformation> &ptr)
243 {
244         ptr = 0;
245         return -1;
246 }
247
248 #include <lib/service/event.h>
249
250 RESULT iStaticServiceInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
251 {
252         evt = 0;
253         return -1;
254 }
255
256 int iStaticServiceInformation::getLength(const eServiceReference &ref)
257 {
258         return -1;
259 }
260
261 int iStaticServiceInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
262 {
263         return 0;
264 }
265
266 RESULT iServiceInformation::getEvent(ePtr<eServiceEvent> &evt, int m_nownext)
267 {
268         evt = 0;
269         return -1;
270 }
271
272 int iStaticServiceInformation::getInfo(const eServiceReference &ref, int w)
273 {
274         return -1;
275 }
276
277 std::string iStaticServiceInformation::getInfoString(const eServiceReference &ref, int w)
278 {
279         return "";
280 }
281
282 PyObject *iStaticServiceInformation::getInfoObject(const eServiceReference &ref, int w)
283 {
284         Py_RETURN_NONE;
285 }
286
287 int iServiceInformation::getInfo(int w)
288 {
289         return -1;
290 }
291
292 std::string iServiceInformation::getInfoString(int w)
293 {
294         return "";
295 }
296
297 PyObject* iServiceInformation::getInfoObject(int w)
298 {
299         Py_RETURN_NONE;
300 }
301
302 int iStaticServiceInformation::setInfo(const eServiceReference &ref, int w, int v)
303 {
304         return -1;
305 }
306
307 int iStaticServiceInformation::setInfoString(const eServiceReference &ref, int w, const char *v)
308 {
309         return -1;
310 }
311
312 int iServiceInformation::setInfo(int w, int v)
313 {
314         return -1;
315 }
316
317 int iServiceInformation::setInfoString(int w, const char *v)
318 {
319         return -1;
320 }
321
322 eAutoInitPtr<eServiceCenter> init_eServiceCenter(eAutoInitNumbers::service, "eServiceCenter");