show media selector instead of hardcoded /hdd/ scan
[enigma2.git] / lib / python / Plugins / Extensions / MediaScanner / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2 from os import path as os_path, walk as os_walk
3 from string import lower
4
5 def getExtension(file):
6         p = file.rfind('.')
7         if p == -1:
8                 ext = ""
9         else:
10                 ext = file[p+1:]
11
12         return lower(ext)
13
14 class Scanner:
15         def __init__(self, name, extensions = [], paths_to_scan = [], description = "", openfnc = None):
16                 self.extensions = extensions
17                 self.name = name
18                 self.paths_to_scan = paths_to_scan
19                 self.description = description
20                 self.openfnc = openfnc
21
22         def checkFile(self, filename):
23                 return True
24
25         def handleFile(self, res, filename, ext):
26                 if (self.extensions is None or ext in self.extensions) and self.checkFile(filename):
27                         res.setdefault(self, []).append(filename)
28
29         def __repr__(self):
30                 return "<Scanner " + self.name + ">"
31
32         def open(self, list, *args, **kwargs):
33                 if self.openfnc is not None:
34                         self.openfnc(list, *args, **kwargs)
35
36 class ScanPath:
37         def __init__(self, path, with_subdirs = False):
38                 self.path = path
39                 self.with_subdirs = with_subdirs
40
41         def __repr__(self):
42                 return self.path + "(" + str(self.with_subdirs) + ")"
43
44         # we will use this in a set(), so we need to implement __hash__ and __cmp__
45         def __hash__(self):
46                 return self.path.__hash__() ^ self.with_subdirs.__hash__()
47
48         def __cmp__(self, other):
49                 if self.path < other.path:
50                         return -1
51                 elif self.path > other.path:
52                         return +1
53                 else:
54                         return self.with_subdirs.__cmp__(other.with_subdirs)
55
56 #scanner = [
57 #               Scanner(extensions = ["jpg", "jpe", "jpeg"], 
58 #                       paths_to_scan = 
59 #                               [
60 #                                       ScanPath(path = "DCIM", with_subdirs = True),
61 #                                       ScanPath(path = "", with_subdirs = False),
62 #                               ],
63 #                       name = "Pictures", 
64 #                       description = "View Photos..."
65 #               ),
66 #
67 #               Scanner(extensions = ["mpg", "vob", "ts"], 
68 #                       paths_to_scan =
69 #                               [
70 #                                       ScanPath(path = ""),
71 #                                       ScanPath(path = "movie", with_subdirs = True),
72 #                               ],
73 #                       name = "Movie",
74 #                       description = "View Movies..."
75 #               ),
76 #
77 #               Scanner(extensions = ["mp3", "ogg"], 
78 #                       name = "Media",
79 #                       paths_to_scan = 
80 #                               [
81 #                                       ScanPath(path = "", with_subdirs = False),
82 #                               ],
83 #                       description = "Play music..."
84 #               ),
85 #
86 #               Scanner(extensions = ["ipk"], 
87 #                       name = "Packages",
88 #                       paths_to_scan = 
89 #                               [
90 #                                       ScanPath(path = ""),
91 #                               ],
92 #                       description = "Install software..."
93 #               ),
94 #       ]
95
96 def scanDevice(mountpoint):
97         from Components.PluginComponent import plugins
98
99         scanner = [ ]
100
101         for p in plugins.getPlugins(PluginDescriptor.WHERE_FILESCAN):
102                 l = p()
103                 if not isinstance(l, list):
104                         l = [l]
105                 scanner += l
106
107         print "scanner:", scanner
108
109         res = { }
110
111         # merge all to-be-scanned paths, with priority to 
112         # with_subdirs.
113
114         paths_to_scan = set()
115
116         # first merge them all...
117         for s in scanner:
118                 paths_to_scan.update(set(s.paths_to_scan))
119
120         # ...then remove with_subdir=False when same path exists
121         # with with_subdirs=True
122         for p in set(paths_to_scan):
123                 if p.with_subdirs == True and ScanPath(path=p.path) in paths_to_scan:
124                         paths_to_scan.remove(ScanPath(path=p.path))
125
126         # convert to list
127         paths_to_scan = list(paths_to_scan)
128
129         # now scan the paths
130         for p in paths_to_scan:
131                 path = os_path.join(mountpoint, p.path)
132
133                 for root, dirs, files in os_walk(path):
134                         for f in files:
135                                 ext = getExtension(f)
136                                 pathname = os_path.join(root, f)
137                                 for s in scanner:
138                                         s.handleFile(res, pathname, ext)
139
140                         # if we really don't want to scan subdirs, stop here.
141                         if not p.with_subdirs:
142                                 del dirs[:]
143
144         # res is a dict with scanner -> [files]
145         return res
146
147 def execute(option):
148         print "execute", option
149         if option is None:
150                 return
151
152         (_, scanner, files, session) = option
153         scanner.open(files, session)
154
155
156 def mountpoint_choosen(option):
157         if option is None:
158                 return
159
160         from Screens.ChoiceBox import ChoiceBox
161
162         (description, mountpoint, session) = option
163         res = scanDevice(mountpoint)
164
165         list = [ (r.description, r, res[r], session) for r in res ]
166
167         if list == [ ]:
168                 print "nothing found"
169                 return
170
171         session.openWithCallback(execute, ChoiceBox, 
172                 title = "The following files were found...",
173                 list = list)
174
175 def scan(session):
176         from Screens.ChoiceBox import ChoiceBox
177
178         from Components.Harddisk import harddiskmanager
179
180         parts = [ (r.description, r.mountpoint, session) for r in harddiskmanager.getMountedPartitions() ]
181         session.openWithCallback(mountpoint_choosen, ChoiceBox, title = "Please Select Medium to be Scanned", list = parts)
182
183 def main(session, **kwargs):
184         scan(session)
185
186 def Plugins(**kwargs):
187         return PluginDescriptor(name="MediaScanner", description="Scan Files...", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)