summaryrefslogtreecommitdiff
path: root/plugins/__init__.py
blob: 2e31655f96220616ca3b8a7ee7c11ae3ae8817c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import os
import sys
import logging

# { className => [module, className, instance, msg] }
_plugins=None
PLUGIN_MODULE=0
PLUGIN_CLASS=1
PLUGIN_INSTANCE=2
PLUGIN_MSG=3


class IPlaylist:
   def ensureVisible(self, song_id):
       raise Exception("TODO implement")

def loadPlugins():
    """(Re)load all modules in the plugins directory."""
    global _plugins
    _plugins={}
    for file in os.listdir('plugins'):
        if file[-3:]=='.py' and file!='__init__.py':
            name=file[:-3]  # name without ext
            mod='plugins.%s'%(name) # mod name
            className='plugin%s'%(name) # classname
            
            _plugins[className.lower()]=[mod, className, None, None]
            loadPlugin(className, None)

def setPluginMessage(name, msg):
    global _plugins
    try:
        _plugins[name.lower()][PLUGIN_MSG]=msg
    except:
        try:
            _plugins["plugin%s"%(name.lower())][PLUGIN_MODULE]=msg
        except:
            pass

def getPlugin(name):
    global _plugins
    try:
        return _plugins[name.lower()][PLUGIN_INSTANCE]
    except:
        try:
            return _plugins["plugin%s"%(name.lower())][PLUGIN_INSTANCE]
        except:
            return None

def loadPlugin(className, parent):
    """Constructs a plugin."""
    global _plugins
    entry=_plugins[className.lower()]
    mod=entry[PLUGIN_MODULE]
    # ensure we get the latest version
    try:
        try:
            sys.modules[mod]
            reimport=True
        except:
            reimport=False
        
        if reimport:
            reload(sys.modules[mod])
        else:
            module=__import__(mod, globals(), locals(), className, -1)
            
    except Exception, e:
        _plugins[className.lower()][PLUGIN_MSG]=str(e)
        _plugins[className.lower()][PLUGIN_INSTANCE]=None
        logging.warning("Failed to load plugin %s: %s %s"%(className, str(type(e)), str(e)))
        return None
    
    module=sys.modules[mod]
    _plugins[className.lower()][PLUGIN_MSG]=None
    
    if parent:
        # instantiate the plugin
        _plugins[className.lower()][PLUGIN_INSTANCE]=module.__dict__[className](parent)
    else:
        _plugins[className.lower()][PLUGIN_INSTANCE]=None
    return _plugins[className.lower()][PLUGIN_INSTANCE]

def listImplementors(interface, loaded = True):
   """Return a list of plugin-instances that implement an interface"""
   global _plugins
   return map(lambda plugin: plugin[PLUGIN_INSTANCE]
           , filter(lambda plugin: isinstance(plugin[PLUGIN_INSTANCE], interface)
               and ((loaded != None and plugin[PLUGIN_INSTANCE].loaded == loaded) or (loaded == None)), _plugins.values()))

def listPlugins():
    """Get the list of plugins available as { className => [mod, className, instance, msg] }."""
    global _plugins
    return _plugins


loadPlugins()