trunk 20080912
[gitenigma.git] / src / enigma_dyn_wap.cpp
blobc66bc6b3f3309b57ea397ba686fb3d937d852a11
1 /*
2 * $Id: enigma_dyn_wap.cpp,v 1.11 2005/10/12 20:46:27 digi_casi Exp $
4 * (C) 2005 by digi_casi <digi_casi@tuxbox.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <map>
23 #include <time.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <dirent.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
31 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <net/if.h>
34 #include <arpa/inet.h>
35 #include <linux/if_ether.h>
36 #include <iomanip>
37 #include <iostream>
38 #include <fstream>
40 #include <enigma.h>
41 #include <enigma_main.h>
42 #include <enigma_standby.h>
43 #include <timer.h>
44 #include <lib/driver/eavswitch.h>
45 #include <lib/dvb/dvb.h>
46 #include <lib/dvb/edvb.h>
47 #include <lib/dvb/epgcache.h>
48 #include <lib/dvb/servicestructure.h>
49 #include <lib/dvb/decoder.h>
50 #include <lib/dvb/dvbservice.h>
51 #include <lib/dvb/service.h>
52 #include <lib/dvb/record.h>
53 #include <lib/dvb/serviceplaylist.h>
55 #include <lib/system/info.h>
56 #include <lib/system/http_dyn.h>
57 #include <lib/system/econfig.h>
58 #include <enigma_dyn.h>
59 #include <enigma_dyn_utils.h>
60 #include <enigma_dyn_epg.h>
61 #include <enigma_dyn_wap.h>
63 using namespace std;
65 extern eString zap[5][5];
66 extern eString getCurService();
67 extern bool onSameTP(const eServiceReferenceDVB& ref1, const eServiceReferenceDVB &ref2); // implemented in timer.cpp
69 struct countTimer
71 int &count;
72 bool repeating;
73 countTimer(int &count,bool repeating)
74 :count(count), repeating(repeating)
78 void operator()(ePlaylistEntry *se)
80 if (se->type&ePlaylistEntry::isRepeating)
82 if (repeating)
83 ++count;
85 else
87 if (!repeating)
88 ++count;
93 static eString admin2(eString command)
95 if (command == "shutdown")
97 if (eSystemInfo::getInstance()->canShutdown())
98 eZap::getInstance()->quit();
100 else
101 if (command == "reboot")
102 eZap::getInstance()->quit(4);
103 else
104 if (command == "restart")
105 eZap::getInstance()->quit(2);
106 else
107 if (command == "wakeup")
109 if (eZapStandby::getInstance())
110 eZapStandby::getInstance()->wakeUp(0);
112 else
113 if (command == "standby")
115 if (eZapStandby::getInstance())
116 eZapMain::getInstance()->gotoStandby();
119 return "<?xml version=\"1.0\"?><!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\"><wml><card title=\"Info\"><p>Command " + command + " initiated.</p></card></wml>";
122 class eWapNavigatorListDirectory: public Object
124 eString &result;
125 eString origpath;
126 eString path;
127 eServiceInterface &iface;
128 public:
129 eWapNavigatorListDirectory(eString &result, eString origpath, eString path, eServiceInterface &iface): result(result), origpath(origpath), path(path), iface(iface)
131 eDebug("path: %s", path.c_str());
133 void addEntry(const eServiceReference &e)
135 #ifndef DISABLE_FILE
136 if (eDVB::getInstance()->recorder && !e.path && !e.flags)
138 if (!onSameTP(eDVB::getInstance()->recorder->recRef,(eServiceReferenceDVB&)e))
139 return;
141 #endif
142 eString serviceRef = ref2string(e);
144 if (!(e.flags & eServiceReference::isDirectory))
145 result += "<a href=\"/wap?mode=zapto,path=" + serviceRef + "\">";
146 else
147 result += "<a href=\"/wap?mode=zap,path=" + serviceRef + "\">";
149 eService *service = iface.addRef(e);
150 if (!service)
151 result += "N/A";
152 else
154 result += filter_string(service->service_name);
155 iface.removeRef(e);
158 result += "</a>";
159 result += "<br/>\n";
163 static eString getWapZapContent(eString path)
165 eString tpath, result;
167 unsigned int pos = 0, lastpos = 0, temp = 0;
169 if ((path.find(";", 0)) == eString::npos)
170 path = ";" + path;
172 while ((pos = path.find(";", lastpos)) != eString::npos)
174 lastpos = pos + 1;
175 if ((temp = path.find(";", lastpos)) != eString::npos)
176 tpath = path.mid(lastpos, temp - lastpos);
177 else
178 tpath = path.mid(lastpos, strlen(path.c_str()) - lastpos);
180 eServiceReference current_service = string2ref(tpath);
181 eServiceInterface *iface = eServiceInterface::getInstance();
183 // first pass thru is to get all user bouquets
184 eWapNavigatorListDirectory navlist(result, path, tpath, *iface);
185 Signal1<void, const eServiceReference&> signal;
186 signal.connect(slot(navlist, &eWapNavigatorListDirectory::addEntry));
187 iface->enterDirectory(current_service, signal);
188 eDebug("entered");
189 iface->leaveDirectory(current_service);
190 eDebug("exited");
193 return result;
196 struct getWapEntryString
198 std::stringstream &result;
199 bool repeating;
201 getWapEntryString(std::stringstream &result, bool repeating)
202 :result(result), repeating(repeating)
206 void operator()(ePlaylistEntry* se)
208 if (!repeating && se->type & ePlaylistEntry::isRepeating)
209 return;
210 if (repeating && !(se->type & ePlaylistEntry::isRepeating))
211 return;
212 tm startTime = *localtime(&se->time_begin);
213 time_t time_end = se->time_begin + se->duration;
214 tm endTime = *localtime(&time_end);
216 eString description = se->service.descr;
217 eString channel = getLeft(description, '/');
218 if (!channel)
220 eService *service = eDVB::getInstance()->settings->getTransponders()->searchService(se->service);
221 if (service)
222 channel = filter_string(service->service_name);
224 if (!channel)
225 channel = "No channel available";
227 description = getRight(description, '/');
228 if (!description)
229 description = "No description available";
231 result << std::setw(2) << startTime.tm_mday << '.'
232 << std::setw(2) << startTime.tm_mon+1 << ". - "
233 << std::setw(2) << startTime.tm_hour << ':'
234 << std::setw(2) << startTime.tm_min
235 << " / "
236 << std::setw(2) << endTime.tm_mday << '.'
237 << std::setw(2) << endTime.tm_mon+1 << ". - "
238 << std::setw(2) << endTime.tm_hour << ':'
239 << std::setw(2) << endTime.tm_min
240 << "<br/>"
241 << channel
242 << "<br/>"
243 << description
244 << "<br/>";
248 static eString wapTimerList(void)
250 std::stringstream result;
251 eString tmp = readFile(TEMPLATE_DIR + "wapTimerList.tmp");
253 int count = 0;
254 eTimerManager::getInstance()->forEachEntry(countTimer(count, false));
255 if (count)
257 result << std::setfill('0');
258 if (!eTimerManager::getInstance()->getTimerCount())
259 result << eString("No timer events available");
260 else
261 eTimerManager::getInstance()->forEachEntry(getWapEntryString(result, 0));
263 else
264 result << eString("No timer events available");
266 tmp.strReplace("#BODY#", result.str());
268 return tmp;
270 static eString wapEPG(int page)
272 std::stringstream result;
273 eString description;
274 result << std::setfill('0');
276 eService* current;
278 eDVBServiceController *sapi=eDVB::getInstance()->getServiceAPI();
279 if (!sapi)
280 return "No EPG available";
282 eServiceReference ref = sapi->service;
284 current = eDVB::getInstance()->settings->getTransponders()->searchService(ref);
286 if (!current)
287 return "No EPG available";
289 eServiceReferenceDVB &rref = (eServiceReferenceDVB&)ref;
290 eEPGCache::getInstance()->Lock();
291 const timeMap* evt = eEPGCache::getInstance()->getTimeMap(rref);
293 if (!evt)
294 return "No EPG available";
295 else
297 timeMap::const_iterator It;
298 int tsidonid = (rref.getTransportStreamID().get()<<16)|rref.getOriginalNetworkID().get();
300 int i = 0;
301 for(It=evt->begin(); It!= evt->end(); ++It)
303 if ((i >= page * 25) && (i < (page + 1) * 25))
305 EITEvent event(*It->second, tsidonid);
306 LocalEventData led;
307 led.getLocalData(&event, &description);
308 tm* t = localtime(&event.start_time);
310 result << std::setw(2) << t->tm_mday << '.'
311 << std::setw(2) << t->tm_mon+1 << ". - "
312 << std::setw(2) << t->tm_hour << ':'
313 << std::setw(2) << t->tm_min << ' '
314 << "<br/>";
316 result << "<a href=\"/wap?mode=epgDetails"
317 << ",path=" << ref2string(ref)
318 << ",ID=" << std::hex << event.event_id << std::dec
319 << "\">"
320 << filter_string(description)
321 << "</a><br/>\n";
323 i++;
325 if (i >= (page + 1) * 25)
327 page++;
328 result << "<a href=\"wap?mode=epg,page=" << eString().sprintf("%d", page) << "\">Next Page</a><br/>";
331 eEPGCache::getInstance()->Unlock();
333 eString tmp = readFile(TEMPLATE_DIR + "wapepg.tmp");
334 tmp.strReplace("#CHANNEL#", filter_string(current->service_name));
335 tmp.strReplace("#BODY#", result.str());
336 return tmp;
339 static eString wapAddTimerEvent(eString opts)
341 eString result;
343 std::map<eString, eString> opt = getRequestOptions(opts, ',');
344 eString serviceRef = opt["path"];
345 eString eventID = opt["ID"];
346 eString eventStartTime = opt["start"];
347 eString eventDuration = opt["duration"];
348 eString channel = httpUnescape(opt["channel"]);
349 eString description = httpUnescape(opt["descr"]);
350 if (description == "")
351 description = "No description available";
353 int eventid;
354 sscanf(eventID.c_str(), "%x", &eventid);
356 int timeroffset = 0;
357 if ((eConfig::getInstance()->getKey("/enigma/timeroffset", timeroffset)) != 0)
358 timeroffset = 0;
360 int start = atoi(eventStartTime.c_str()) - (timeroffset * 60);
361 int duration = atoi(eventDuration.c_str()) + (2 * timeroffset * 60);
363 ePlaylistEntry entry(string2ref(serviceRef), start, duration, eventid, ePlaylistEntry::stateWaiting | ePlaylistEntry::RecTimerEntry | ePlaylistEntry::recDVR);
364 entry.service.descr = channel + "/" + description;
366 if (eTimerManager::getInstance()->addEventToTimerList(entry) == -1)
367 result += "Timer event could not be added because time of the event overlaps with an already existing event.";
368 else
369 result += "Timer event was created successfully.";
370 eTimerManager::getInstance()->saveTimerList(); //not needed, but in case enigma crashes ;-)
371 return result;
374 static eString wapEPGDetails(eString serviceRef, eString eventID)
376 eString result;
377 eService *current = NULL;
378 eString ext_description;
379 std::stringstream record;
380 int eventid;
381 eString description = "No description available";
383 sscanf(eventID.c_str(), "%x", &eventid);
384 eDebug("[ENIGMA_DYN] getEPGDetails: serviceRef = %s, ID = %04x", serviceRef.c_str(), eventid);
386 // search for the event... to get the description...
387 eDVBServiceController *sapi=eDVB::getInstance()->getServiceAPI();
388 if (sapi)
390 eServiceReference ref(string2ref(serviceRef));
391 current = eDVB::getInstance()->settings->getTransponders()->searchService((eServiceReferenceDVB&)ref);
392 if (current)
394 EITEvent *event = eEPGCache::getInstance()->lookupEvent((eServiceReferenceDVB&)ref, eventid);
395 if (event)
397 LocalEventData led;
398 led.getLocalData(event, &description, 0, &ext_description);
399 if (!ext_description)
400 ext_description = "No detailed information available";
401 #ifndef DISABLE_FILE
402 record << "<a href=\"/wap?mode=addTimerEvent"
403 << ",path=" << ref2string(ref)
404 << ",ID=" << std::hex << event->event_id << std::dec
405 << ",start=" << event->start_time
406 << ",duration=" << event->duration
407 << ",descr=" << filter_string(description)
408 << ",channel=" << filter_string(current->service_name)
409 << "\">Record</a>";
410 #endif
411 delete event;
416 result = readFile(TEMPLATE_DIR + "wapEPGDetails.tmp");
417 result.strReplace("#EVENT#", filter_string(description));
418 result.strReplace("#RECORD#", record.str());
419 result.strReplace("#BODY#", filter_string(ext_description));
421 return result;
424 static eString wap_web_root(eString request, eString dirpath, eString opts, eHTTPConnection *content)
426 eString result;
428 std::map<eString,eString> opt = getRequestOptions(opts, ',');
429 eString mode = opt["mode"];
430 eString spath = opt["path"];
432 content->local_header["Content-Type"]="text/vnd.wap.wml";
434 if (mode == "admin")
436 eString command = opt["command"];
437 result = admin2(command);
439 else
440 if (mode == "zap")
442 if (opts.find("path") == eString::npos)
443 spath = zap[ZAPMODETV][ZAPSUBMODEBOUQUETS];
444 result = readFile(TEMPLATE_DIR + "wapzap.tmp");
445 result.strReplace("#BODY#", getWapZapContent(spath));
447 else
448 if (mode == "zapto")
450 eServiceReference current_service = string2ref(spath);
452 if (!(current_service.flags&eServiceReference::isDirectory)) // is playable
453 eZapMain::getInstance()->playService(current_service, eZapMain::psSetMode|eZapMain::psDontAdd);
455 result = "<?xml version=\"1.0\"?><!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\"><wml><card title=\"Info\"><p>Zap complete.</p></card></wml>";
457 else
458 if (mode == "epg")
460 eString page = opt["page"];
461 result = wapEPG(atoi(page.c_str()));
463 else
464 if (mode == "epgDetails")
466 eString eventID = opt["ID"];
467 result = wapEPGDetails(spath, eventID);
469 else
470 if (mode == "addTimerEvent")
472 result = wapAddTimerEvent(opts);
473 result = "<?xml version=\"1.0\"?><!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\"><wml><card title=\"Info\"><p>" + result + "</p></card></wml>";
476 else
477 if (mode == "timer")
479 result = wapTimerList();
481 else
482 if (mode == "cleanupTimerList")
484 eTimerManager::getInstance()->cleanupEvents();
485 eTimerManager::getInstance()->saveTimerList(); //not needed, but in case enigma crashes ;-)
486 result = "<?xml version=\"1.0\"?><!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\"><wml><card title=\"Info\"><p>Timers cleaned up.</p></card></wml>";
488 else
489 if (mode == "clearTimerList")
491 eTimerManager::getInstance()->clearEvents();
492 eTimerManager::getInstance()->saveTimerList(); //not needed, but in case enigma crashes ;-)
493 result = "<?xml version=\"1.0\"?><!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\"><wml><card title=\"Info\"><p>Timer list cleared.</p></card></wml>";
495 else
497 result = readFile(TEMPLATE_DIR + "wap.tmp");
498 result = getEITC(result, "HTML");
499 result.strReplace("#SERVICE#", getCurService());
502 return result;
505 void ezapWapInitializeDyn(eHTTPDynPathResolver *dyn_resolver, bool lockWeb)
507 dyn_resolver->addDyn("GET", "/wap", wap_web_root, lockWeb);