[MerlinSkinThemes] - add aarch64 support by dreamer-flt
[enigma2-plugins.git] / zapstatistic / src / plugin.py
1 # -*- coding: UTF-8 -*-
2 # Zap Statistic by AliAbdul
3 from Components.ActionMap import ActionMap
4 from Components.config import config
5 from Components.Label import Label
6 from Components.MenuList import MenuList
7 from Components.MultiContent import MultiContentEntryText
8 from enigma import eListboxPythonMultiContent, eServiceReference, gFont
9 from os import environ
10 from Plugins.Plugin import PluginDescriptor\r
11 from Screens.ChoiceBox import ChoiceBox
12 from Screens.ParentalControlSetup import ProtectedScreen
13 from Screens.Screen import Screen
14 from ServiceReference import ServiceReference
15 from time import gmtime, localtime, strftime, time
16 from Tools.Directories import fileExists
17 from xml.etree.cElementTree import parse
18
19 def decode_charset(str, charset):
20         try:
21                 uni = unicode(str, charset, 'strict')
22         except:
23                 uni = str
24         return uni
25
26 ###########################################################
27
28 def deformXml(xml):
29         xml = xml.replace("&", "&")
30         xml = xml.replace("'", "'")
31         xml = xml.replace("<", "&lt;")
32         xml = xml.replace(">", "&gt;")
33         xml = xml.replace('"', "&quot;")
34         return xml
35
36 def reformXml(xml):
37         xml = xml.replace("&amp;", "&")
38         xml = xml.replace("&apos;", "'")
39         xml = xml.replace("&lt;", "<")
40         xml = xml.replace("&gt;", ">")
41         xml = xml.replace("&quot;", '"')
42         return xml
43
44 ###########################################################
45
46 class ZapEntry:
47         def __init__(self, ref, begin=None, end=None):
48                 self.ref = ref
49                 self.name = ServiceReference(eServiceReference(ref)).getServiceName()
50                 if begin:
51                         self.begin = begin
52                 else:
53                         self.begin = time()
54                 self.end = end
55
56         def stop(self):
57                 self.end = time()
58
59 ###########################################################
60
61 class DurationZapEntry:
62         def __init__(self, zapentry):
63                 self.ref = zapentry.ref
64                 self.name = zapentry.name
65                 duration = zapentry.end - zapentry.begin
66                 self.duration = strftime("%H:%M:%S", gmtime(duration))
67                 t = localtime(zapentry.begin)
68                 self.begin = "%02d.%02d. %02d:%02d:%02d" % (t[2], t[1], t[3], t[4], t[5])
69
70 ###########################################################
71
72 class CombinedZapEntry:
73         def __init__(self, zapentry):
74                 self.ref = zapentry.ref
75                 self.name = zapentry.name
76                 self.duration = zapentry.end - zapentry.begin
77
78         def addDuration(self, zapentry):
79                 self.duration = self.duration + zapentry.end - zapentry.begin
80
81         def getDurationText(self):
82                 return strftime("%H:%M:%S", gmtime(self.duration))
83
84 ###########################################################
85
86 class ZapStatistic:
87         def __init__(self):
88                 self.xmlFile = "/etc/zapstatistic.xml"
89                 self.zapEntries = []
90                 self.currentEntry = None
91
92         def loadZapEntries(self):
93                 if fileExists(self.xmlFile):
94                         try:
95                                 menu = parse(self.xmlFile).getroot()
96                                 for item in menu.findall("entry"):
97                                         ref = item.get("ref") or None
98                                         if ref:
99                                                 ref = decode_charset(ref, "UTF-8").encode("UTF-8")
100                                                 ref = reformXml(ref)
101                                         begin = item.get("begin") or None
102                                         end = item.get("end") or None
103                                         if ref and begin and end:
104                                                 self.zapEntries.append(ZapEntry(ref, float(begin), float(end)))
105                         except:
106                                 print "[ZapStatistic] Error while reading xml file"
107
108         def saveZapEntries(self):
109                 xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<zapstatistic>\n'
110                 for x in self.zapEntries:
111                         if not x.end:
112                                 x.end = time()
113                         xml += '\t<entry ref="%s" begin="%s" end ="%s" />\n' % (decode_charset(deformXml(x.ref), "UTF-8"), str(x.begin), str(x.end))
114                 xml += '</zapstatistic>'
115                 try:
116                         f = open(self.xmlFile, "w")
117                         f.write(xml.encode("UTF-8"))
118                         f.close()
119                 except:
120                         print "[ZapStatistic] Error while writing xml file"
121
122         def handlePlayServiceCommand(self, ref):
123                 self.handleStopServiceCommand()
124                 if ref:
125                         self.currentEntry = ZapEntry(ref.toString())
126
127         def handleStopServiceCommand(self):
128                 if self.currentEntry:
129                         self.currentEntry.stop()
130                         self.zapEntries.append(self.currentEntry)
131                         self.currentEntry = None
132
133 zapstatistic = ZapStatistic()
134
135 ###########################################################
136
137 global PlayService
138 global StopService
139 PlayService = None
140 StopService = None
141
142 def playService(ref, checkParentalControl=True, forceRestart=False):
143         if PlayService:
144                 zapstatistic.handlePlayServiceCommand(ref)
145                 PlayService(ref, checkParentalControl, forceRestart)
146
147 def stopService():
148         if StopService:
149                 zapstatistic.handleStopServiceCommand()
150                 StopService()
151
152 ###########################################################
153
154 class ZapStatisticBrowserList(MenuList):
155         def __init__(self, list, enableWrapAround=False):
156                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
157                 self.l.setItemHeight(25)
158                 self.l.setFont(0, gFont("Regular", 20))
159
160 def ZapStatisticBrowserListEntry(entry):
161         res = [entry]
162         t_begin = localtime(entry.begin)
163         t_end = localtime(entry.end)
164         res.append(MultiContentEntryText(pos=(0, 0), size=(240, 25), font=0, text="%02d.%02d. %02d:%02d:%02d - %02d:%02d:%02d" % (t_begin[2], t_begin[1], t_begin[3], t_begin[4], t_begin[5], t_end[3], t_end[4], t_end[5])))
165         res.append(MultiContentEntryText(pos=(250, 0), size=(310, 25), font=0, text=entry.name))
166         return res
167
168 def ZapStatisticBrowserDurationListEntry(entry):
169         res = [entry]
170         res.append(MultiContentEntryText(pos=(0, 0), size=(240, 25), font=0, text="%s (%s)" % (entry.duration, entry.begin)))
171         res.append(MultiContentEntryText(pos=(250, 0), size=(310, 25), font=0, text=entry.name))
172         return res
173
174 def ZapStatisticBrowserCombinedListEntry(entry):
175         res = [entry]
176         res.append(MultiContentEntryText(pos=(0, 0), size=(150, 25), font=0, text="%s" % (entry.getDurationText())))
177         res.append(MultiContentEntryText(pos=(160, 0), size=(400, 25), font=0, text=entry.name))
178         return res
179
180 ###########################################################
181
182 class ZapStatisticDurationScreen(Screen):
183         SORT_NAME_ASCENDING = 0
184         SORT_NAME_DESCENDING = 1
185         SORT_DURATION_ASCENDING = 2
186         SORT_DURATION_DESCENDING = 3
187         skin = """
188                 <screen position="center,center" size="560,450" title="%s" >
189                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />
190                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />
191                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />
192                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />
193                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
194                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
195                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
196                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
197                         <widget name="list" position="0,40" size="560,400" scrollbarMode="showOnDemand" />
198                 </screen>""" % _("Zap Statistic")
199
200         def __init__(self, session):
201                 Screen.__init__(self, session)
202
203                 self.sortType = self.SORT_NAME_ASCENDING
204
205                 self["key_red"] = Label(_("Sort (name+)"))
206                 self["key_green"] = Label(_("Sort (name-)"))
207                 self["key_yellow"] = Label(_("Sort (duration+)"))
208                 self["key_blue"] = Label(_("Sort (duration-)"))
209                 self["list"] = ZapStatisticBrowserList([])
210
211                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
212                         {
213                                 "ok": self.play,
214                                 "cancel": self.close,
215                                 "red": self.sortByNameAscending,
216                                 "green": self.sortByNameDescending,
217                                 "yellow": self.sortByDurationAscending,
218                                 "blue": self.sortByDurationDescending
219                         }, prio=-1)
220
221                 self.onLayoutFinish.append(self.buildList)
222
223         def sortList(self, l):
224                 if self.sortType == self.SORT_NAME_ASCENDING:
225                         return l.sort(key=self.buildSortNameKey, reverse=False)
226                 elif self.sortType == self.SORT_NAME_DESCENDING:
227                         return l.sort(key=self.buildSortNameKey, reverse=True)
228                 elif self.sortType == self.SORT_DURATION_ASCENDING:
229                         return l.sort(key=self.buildSortDurationKey, reverse=False)
230                 elif self.sortType == self.SORT_DURATION_DESCENDING:
231                         return l.sort(key=self.buildSortDurationKey, reverse=True)
232                 else:
233                         return l
234
235         def buildSortNameKey(self, x):
236                 try: name = x.name
237                 except: name = ""
238                 return (name and name.lower() or "")
239
240         def buildSortDurationKey(self, x):
241                 try: name = str(x.duration)
242                 except: name = ""
243                 return (name and name.lower() or "")
244
245         def buildList(self):
246                 list = []
247                 l = []
248                 for x in zapstatistic.zapEntries:
249                         l.append(DurationZapEntry(x))
250                 self.sortList(l)
251                 for x in l:
252                         list.append(ZapStatisticBrowserDurationListEntry(x))
253                 self["list"].setList(list)
254
255         def play(self):
256                 cur = self["list"].getCurrent()
257                 if cur:
258                         entry = cur[0]
259                         self.session.nav.playService(eServiceReference(entry.ref))
260
261         def sortByNameAscending(self):
262                 self.sortType = self.SORT_NAME_ASCENDING
263                 self.buildList()
264
265         def sortByNameDescending(self):
266                 self.sortType = self.SORT_NAME_DESCENDING
267                 self.buildList()
268
269         def sortByDurationAscending(self):
270                 self.sortType = self.SORT_DURATION_ASCENDING
271                 self.buildList()
272
273         def sortByDurationDescending(self):
274                 self.sortType = self.SORT_DURATION_DESCENDING
275                 self.buildList()
276
277 ###########################################################
278
279 class ZapStatisticCombinedScreen(Screen):
280         SORT_NAME_ASCENDING = 0
281         SORT_NAME_DESCENDING = 1
282         SORT_DURATION_ASCENDING = 2
283         SORT_DURATION_DESCENDING = 3
284         skin = """
285                 <screen position="center,center" size="560,450" title="%s" >
286                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />
287                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />
288                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />
289                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />
290                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
291                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
292                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
293                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
294                         <widget name="list" position="0,40" size="560,400" scrollbarMode="showOnDemand" />
295                 </screen>""" % _("Zap Statistic")
296
297         def __init__(self, session):
298                 Screen.__init__(self, session)
299
300                 self.list = []
301                 self.sortType = self.SORT_DURATION_DESCENDING
302
303                 self["key_red"] = Label(_("Sort (name+)"))
304                 self["key_green"] = Label(_("Sort (name-)"))
305                 self["key_yellow"] = Label(_("Sort (duration+)"))
306                 self["key_blue"] = Label(_("Sort (duration-)"))
307                 self["list"] = ZapStatisticBrowserList([])
308
309                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
310                         {
311                                 "ok": self.play,
312                                 "cancel": self.close,
313                                 "red": self.sortByNameAscending,
314                                 "green": self.sortByNameDescending,
315                                 "yellow": self.sortByDurationAscending,
316                                 "blue": self.sortByDurationDescending
317                         }, prio=-1)
318
319                 self.onLayoutFinish.append(self.buildList)
320
321         def sortList(self, l):
322                 if self.sortType == self.SORT_NAME_ASCENDING:
323                         return l.sort(key=self.buildSortNameKey, reverse=False)
324                 elif self.sortType == self.SORT_NAME_DESCENDING:
325                         return l.sort(key=self.buildSortNameKey, reverse=True)
326                 elif self.sortType == self.SORT_DURATION_ASCENDING:
327                         return l.sort(key=self.buildSortDurationKey, reverse=False)
328                 elif self.sortType == self.SORT_DURATION_DESCENDING:
329                         return l.sort(key=self.buildSortDurationKey, reverse=True)
330                 else:
331                         return l
332
333         def buildSortNameKey(self, x):
334                 try: name = x.name
335                 except: name = ""
336                 return (name and name.lower() or "")
337
338         def buildSortDurationKey(self, x):
339                 try: name = x.getDurationText()
340                 except: name = ""
341                 return (name and name.lower() or "")
342
343         def buildList(self):
344                 list = []
345                 if len(self.list) == 0:
346                         for x in zapstatistic.zapEntries:
347                                 added = False
348                                 for y in self.list:
349                                         if x.ref == y.ref:
350                                                 y.addDuration(x)
351                                                 added = True
352                                                 break
353                                 if added == False:
354                                         self.list.append(CombinedZapEntry(x))
355                 self.sortList(self.list)
356                 for x in self.list:
357                         list.append(ZapStatisticBrowserCombinedListEntry(x))
358                 self["list"].setList(list)
359
360         def play(self):
361                 cur = self["list"].getCurrent()
362                 if cur:
363                         entry = cur[0]
364                         self.session.nav.playService(eServiceReference(entry.ref))
365
366         def sortByNameAscending(self):
367                 self.sortType = self.SORT_NAME_ASCENDING
368                 self.buildList()
369
370         def sortByNameDescending(self):
371                 self.sortType = self.SORT_NAME_DESCENDING
372                 self.buildList()
373
374         def sortByDurationAscending(self):
375                 self.sortType = self.SORT_DURATION_ASCENDING
376                 self.buildList()
377
378         def sortByDurationDescending(self):
379                 self.sortType = self.SORT_DURATION_DESCENDING
380                 self.buildList()
381
382 ###########################################################
383
384 class ZapStatisticScreen(Screen, ProtectedScreen):
385         SORT_NAME_ASCENDING = 0
386         SORT_NAME_DESCENDING = 1
387         SORT_DATE_ASCENDING = 2
388         SORT_DATE_DESCENDING = 3
389         skin = """
390                 <screen position="center,center" size="560,450" title="%s" >
391                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />
392                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />
393                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />
394                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />
395                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
396                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
397                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
398                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
399                         <widget name="list" position="0,40" size="560,400" scrollbarMode="showOnDemand" />
400                 </screen>""" % _("Zap Statistic")
401
402         def __init__(self, session):
403                 Screen.__init__(self, session)
404                 ProtectedScreen.__init__(self)
405
406                 self.session = session
407                 self.sortType = self.SORT_DATE_ASCENDING
408
409                 self["key_red"] = Label(_("Delete"))
410                 self["key_green"] = Label(" ")
411                 self["key_yellow"] = Label(" ")
412                 self["key_blue"] = Label(_("Durations"))
413                 self["list"] = ZapStatisticBrowserList([])
414
415                 self["actions"] = ActionMap(["ColorActions", "OkCancelActions", "InfobarMenuActions"],
416                         {
417                                 "ok": self.play,
418                                 "cancel": self.close,
419                                 "red": self.delete,
420                                 "green": self.sortByName,
421                                 "yellow": self.sortByDate,
422                                 "blue": self.duration,\r
423                                 "mainMenu": self.menu
424                         }, prio=-1)
425
426                 self.onLayoutFinish.append(self.buildList)
427
428         def updateLabels(self):
429                 self["key_green"].setText(_("Sort (name+)"))
430                 self["key_yellow"].setText(_("Sort (date+)"))
431                 if self.sortType == self.SORT_NAME_ASCENDING:
432                         self["key_green"].setText(_("Sort (name-)"))
433                 if self.sortType == self.SORT_DATE_ASCENDING:
434                         self["key_yellow"].setText(_("Sort (date-)"))
435
436         def sortList(self, l):
437                 if self.sortType == self.SORT_NAME_ASCENDING:
438                         return l.sort(key=self.buildSortNameKey, reverse=False)
439                 elif self.sortType == self.SORT_NAME_DESCENDING:
440                         return l.sort(key=self.buildSortNameKey, reverse=True)
441                 elif self.sortType == self.SORT_DATE_ASCENDING:
442                         return l.sort(key=self.buildSortDateKey, reverse=False)
443                 elif self.sortType == self.SORT_DATE_DESCENDING:
444                         return l.sort(key=self.buildSortDateKey, reverse=True)
445                 else:
446                         return l
447
448         def buildSortNameKey(self, x):
449                 try: name = x.name
450                 except: name = ""
451                 return (name and name.lower() or "")
452
453         def buildSortDateKey(self, x):
454                 try: name = str(x.begin)
455                 except: name = ""
456                 return (name and name.lower() or "")
457
458         def buildList(self):
459                 list = []
460                 l = zapstatistic.zapEntries
461                 self.sortList(l)
462                 for x in l:
463                         list.append(ZapStatisticBrowserListEntry(x))
464                 self["list"].setList(list)
465                 self.updateLabels()
466
467         def isProtected(self):
468                 return config.ParentalControl.setuppinactive.value and config.ParentalControl.configured.value
469
470         def pinEntered(self, result):
471                 if result is None:
472                         self.close()
473                 elif not result:
474                         self.close()
475
476         def play(self):
477                 cur = self["list"].getCurrent()
478                 if cur:
479                         entry = cur[0]
480                         self.session.nav.playService(eServiceReference(entry.ref))
481
482         def delete(self):
483                 cur = self["list"].getCurrent()
484                 if cur:
485                         entry = cur[0]
486                         idx = 0
487                         for x in zapstatistic.zapEntries:
488                                 if x == entry:
489                                         del zapstatistic.zapEntries[idx]
490                                         break
491                                 else:
492                                         idx += 1
493                         self.buildList()
494
495         def deleteAll(self):
496                 if len(zapstatistic.zapEntries):
497                         del zapstatistic.zapEntries
498                         zapstatistic.zapEntries = []
499                         self.buildList()
500
501         def sortByName(self):
502                 if self["key_green"].getText() == _("Sort (name-)"):
503                         self.sortType = self.SORT_NAME_DESCENDING
504                 else:
505                         self.sortType = self.SORT_NAME_ASCENDING
506                 self.buildList()
507
508         def sortByNameAscending(self):
509                 self.sortType = self.SORT_NAME_ASCENDING
510                 self.buildList()
511
512         def sortByNameDescending(self):
513                 self.sortType = self.SORT_NAME_DESCENDING
514                 self.buildList()
515
516         def sortByDate(self):
517                 if self["key_yellow"].getText() == _("Sort (date-)"):
518                         self.sortType = self.SORT_DATE_DESCENDING
519                 else:
520                         self.sortType = self.SORT_DATE_ASCENDING
521                 self.buildList()
522
523         def sortByDateAscending(self):
524                 self.sortType = self.SORT_DATE_ASCENDING
525                 self.buildList()
526
527         def sortByDateDescending(self):
528                 self.sortType = self.SORT_DATE_DESCENDING
529                 self.buildList()
530
531         def duration(self):
532                 self.session.open(ZapStatisticDurationScreen)
533
534         def combined(self):
535                 self.session.open(ZapStatisticCombinedScreen)
536
537         def menu(self):
538                 list = []\r
539                 list.append((_("Play entry"), self.play))\r
540                 list.append((_("Delete entry"), self.delete))\r
541                 list.append((_("Delete all entries"), self.deleteAll))\r
542                 list.append((_("Sort by name (ascending)"), self.sortByNameAscending))\r
543                 list.append((_("Sort by name (descending)"), self.sortByNameDescending))\r
544                 list.append((_("Sort by date (ascending)"), self.sortByDateAscending))\r
545                 list.append((_("Sort by date (descending)"), self.sortByDateDescending))\r
546                 list.append((_("Show duration window"), self.duration))\r
547                 list.append((_("Show combined duration window"), self.combined))\r
548                 list.append((_("Close plugin"), self.close))\r
549                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title=_("Please choose a function..."), list=list)
550
551         def menuCallback(self, callback=None):\r
552                 if callback is not None:\r
553                         callback[1]()
554
555 ###########################################################
556
557 def main(session, **kwargs):
558         session.open(ZapStatisticScreen)
559
560 def sessionstart(reason, **kwargs):
561         if reason == 0:
562                 zapstatistic.loadZapEntries()
563                 session = kwargs["session"]
564                 global PlayService
565                 global StopService
566                 PlayService = session.nav.playService
567                 StopService = session.nav.stopService
568                 session.nav.playService = playService
569                 session.nav.stopService = stopService
570
571 def autostart(reason, **kwargs):
572         if reason == 1:
573                 zapstatistic.saveZapEntries()
574
575 def Plugins(**kwargs):
576         return [PluginDescriptor(name=_("Zap Statistic"), description=_("Shows the watched services with some statistic"), where=PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
577                 PluginDescriptor(where=PluginDescriptor.WHERE_SESSIONSTART, fnc=sessionstart),
578                 PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=autostart)]