Merge branch 'bug_293_indicate_unhandled_key' into experimental
[enigma2.git] / lib / python / Components / PluginComponent.py
1 from os import path as os_path, listdir as os_listdir
2 from traceback import print_exc
3 from sys import stdout
4
5 from Tools.Directories import fileExists
6 from Tools.Import import my_import
7 from Plugins.Plugin import PluginDescriptor
8 import keymapparser
9
10 class PluginComponent:
11         def __init__(self):
12                 self.plugins = {}
13                 self.pluginList = [ ]
14                 self.setPluginPrefix("Plugins.")
15                 self.resetWarnings()
16
17         def setPluginPrefix(self, prefix):
18                 self.prefix = prefix
19
20         def addPlugin(self, plugin):
21                 self.pluginList.append(plugin)
22                 for x in plugin.where:
23                         self.plugins.setdefault(x, []).append(plugin)
24                         if x == PluginDescriptor.WHERE_AUTOSTART:
25                                 plugin(reason=0)
26
27         def removePlugin(self, plugin):
28                 self.pluginList.remove(plugin)
29                 for x in plugin.where:
30                         self.plugins[x].remove(plugin)
31                         if x == PluginDescriptor.WHERE_AUTOSTART:
32                                 plugin(reason=1)
33
34         def readPluginList(self, directory):
35                 """enumerates plugins"""
36
37                 categories = os_listdir(directory)
38
39                 new_plugins = [ ]
40
41                 for c in categories:
42                         directory_category = directory + c
43                         if not os_path.isdir(directory_category):
44                                 continue
45                         open(directory_category + "/__init__.py", "a").close()
46                         for pluginname in os_listdir(directory_category):
47                                 path = directory_category + "/" + pluginname
48                                 if os_path.isdir(path):
49                                         if fileExists(path + "/plugin.pyc") or fileExists(path + "/plugin.py"):
50                                                 try:
51                                                         plugin = my_import('.'.join(["Plugins", c, pluginname, "plugin"]))
52
53                                                         if not plugin.__dict__.has_key("Plugins"):
54                                                                 print "Plugin %s doesn't have 'Plugin'-call." % (pluginname)
55                                                                 continue
56
57                                                         plugins = plugin.Plugins(path=path)
58                                                 except Exception, exc:
59                                                         print "Plugin ", c + "/" + pluginname, "failed to load:", exc
60                                                         print_exc(file=stdout)
61                                                         print "skipping plugin."
62                                                         self.warnings.append( (c + "/" + pluginname, str(exc)) )
63                                                         continue
64
65                                                 # allow single entry not to be a list
66                                                 if not isinstance(plugins, list):
67                                                         plugins = [ plugins ]
68
69                                                 for p in plugins:
70                                                         p.updateIcon(path)
71                                                         new_plugins.append(p)
72
73                                                 if fileExists(path + "/keymap.xml"):
74                                                         try:
75                                                                 keymapparser.readKeymap(path + "/keymap.xml")
76                                                         except Exception, exc:
77                                                                 print "keymap for plugin %s/%s failed to load: " % (c, pluginname), exc
78                                                                 self.warnings.append( (c + "/" + pluginname, str(exc)) )
79
80                 # build a diff between the old list of plugins and the new one
81                 # internally, the "fnc" argument will be compared with __eq__
82                 plugins_added = [p for p in new_plugins if p not in self.pluginList]
83                 plugins_removed = [p for p in self.pluginList if not p.internal and p not in new_plugins]
84
85                 for p in plugins_removed:
86                         self.removePlugin(p)
87
88                 for p in plugins_added:
89                         self.addPlugin(p)
90
91         def getPlugins(self, where):
92                 """Get list of plugins in a specific category"""
93
94                 if not isinstance(where, list):
95                         where = [ where ]
96                 res = [ ]
97
98                 for x in where:
99                         res.extend(self.plugins.get(x, [ ]))
100
101                 return  res
102
103         def getPluginsForMenu(self, menuid):
104                 res = [ ]
105                 for p in self.getPlugins(PluginDescriptor.WHERE_MENU):
106                         res += p(menuid)
107                 return res
108
109         def clearPluginList(self):
110                 self.pluginList = []
111                 self.plugins = {}
112
113         def shutdown(self):
114                 for p in self.pluginList[:]:
115                         self.removePlugin(p)
116
117         def resetWarnings(self):
118                 self.warnings = [ ]
119
120         def getNextWakeupTime(self):
121                 wakeup = -1
122                 for p in self.pluginList:
123                         current = p.getWakeupTime()
124                         if current > -1 and (wakeup > current or wakeup == -1):
125                                 wakeup = current
126                 return int(wakeup)
127
128 plugins = PluginComponent()