1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 __maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>'
19
20 from menu_entry_builder import MenuEntryBuilder
21
22 from elisa.core.observers.list import ListObserver, ListObservable
23 from elisa.core.bus import bus_message
24 from elisa.core.utils import misc
25 from elisa.core import common
26 from elisa.core.media_manager import MediaProviderNotFound
27 from elisa.core.media_uri import MediaUri, ParseException
28
29 from elisa.extern.coherence.et import parse_xml
30
31 from twisted.internet import defer
32
33 import platform, os, re
34
35
37
38 - def __init__(self, model, handle_call, icon=None, config=None):
48
49
86
87 - def removed(self, elements, position):
88
89 for element in elements:
90 element_id = id(element)
91
92 if self._location_map.has_key(element_id):
93 for model in self._location_map[element_id]:
94 try:
95 self._model.children.remove(model)
96 except ValueError:
97
98
99 pass
100
101 del self._location_map[element_id]
102
104 location_id = id(location)
105
106 if not self._location_map.has_key(location_id):
107 self._location_map[location_id] = []
108
109 for model in models:
110 self._location_map[location_id].append(model)
111
112
113
115 """
116 each Location has some parameters
117 """
123
144
146 """
147 This class can handle a special MenuEntry-XML-Tag and create
148 MenuNodeModels according to the data it gets.
149 """
150
151 """
152 The XDG directories mapped to the elisa internal media type
153 """
154 xdg_media_types = {
155 'XDG_MUSIC_DIR' : ['audio'],
156 'XDG_PICTURES_DIR' : ['image'],
157 'XDG_VIDEOS_DIR' : ['video']
158 }
159
160 """
161 The different bus_messages mapped to the location_type
162 """
163 location_map = {bus_message.DeviceAction : 'device',
164 bus_message.ForeignApplication : 'app',
165 bus_message.InternetLocation : 'internet',
166 bus_message.LocalNetworkLocation : 'network'
167 }
168
169 default_config = { 'auto_locations' : 1,
170 'locations' : []}
171
172
186
187
190
193
196
198 parent_node = node.find('ParentNode')
199 show_on_empty = False
200 if parent_node != None:
201 plugin_registry = common.application.plugin_registry
202
203
204 parent = plugin_registry.create_component('base:menu_node_model')
205 parent.children = plugin_registry.create_component('base:list_model')
206 parent.children.activity = parent.activity
207
208 self._set_icon(parent, parent_node.find('Icon'))
209
210 parent.text = self._make_label(parent_node.find('Label'))
211 if parent_node.get('show-on-empty', 'False').upper() == 'TRUE':
212 show_on_empty = True
213 self.model_configs[parent] = self.model_configs[real_parent]
214 else:
215 parent = real_parent
216
217
218 lObserver = FilteredLocationObserver(parent,
219 self.activity.handle_menu_entry,
220 icon=node.find('Icon'),
221 config=node.find('Configuration')
222 )
223
224 for filter in node.findall('Filter'):
225 filter_type = filter.get('type', None)
226 if filter_type == None:
227 self.warning("Ignoring Filter without type: %s" % filter)
228 elif filter_type == 'media_type':
229 lObserver.media_types.add(filter.text)
230 elif filter_type == 'location_type':
231 lObserver.location_types.add(filter.text)
232 elif filter_type == 'uri_scheme':
233 lObserver.uri_schemes.add(filter.text)
234
235 lObserver.inserted(self._locations, 0)
236 self._locations.add_observer(lObserver)
237 self._observers.append(lObserver)
238 if real_parent != parent:
239 if len(parent.children) != 0 or show_on_empty:
240 parent.has_children = True
241 parent.activity = real_parent.activity
242 parent.children.activity = self
243 real_parent.children.append(parent)
244
245 return defer.succeed([])
246
248 xdg_ok = True
249 config_home = os.path.expanduser(os.getenv('XDG_CONFIG_HOME',
250 '~/.config'))
251 user_dirs_file = os.path.join(config_home, 'user-dirs.dirs')
252
253
254 if not os.path.exists(user_dirs_file):
255 self.debug("Executing xdg-user-dirs-update")
256 retval = os.system('xdg-user-dirs-update')
257 if retval != 0:
258 self.debug("xdg-user-dirs-update program not found")
259 xdg_ok = False
260
261 if xdg_ok:
262 variables = filter(lambda i: i.startswith('XDG'),
263 os.environ.keys())
264
265 for xdg in self.xdg_media_types.keys():
266 if xdg not in variables:
267 self.debug('XDG variables not found in os.environ, loading %r',
268 user_dirs_file)
269 key_val_re = re.compile('(.*)="(.*)"')
270 for line in open(user_dirs_file).readlines():
271 match = key_val_re.search(line)
272 if match and not match.groups()[0].startswith('#'):
273 var, value = match.groups()
274 self.debug('Found XDG variable %s, injecting in os.environ',
275 var)
276 value = misc.env_var_expand(value)
277 os.environ[var] = value
278 else:
279 self.debug("XDG variables %r already in os.environ",
280 variables)
281
283 from win32 import tools
284 d = tools.get_multimedia_dir()
285
286 os.environ['XDG_MUSIC_DIR'] = d['My Music'].encode('utf8')
287 os.environ['XDG_PICTURES_DIR'] = d['My Pictures'].encode('utf8')
288 os.environ['XDG_VIDEOS_DIR'] = d['My Video'].encode('utf8')
289
290 - def _add_location(self, location_uri, media, location_type='local',
291 theme_icon=None):
292 current_locations = [ l.uri for l in self._locations ]
293 if location_uri in current_locations:
294 self.warning('Location %s given twice', location_uri)
295 else:
296 new_location = Location()
297 if theme_icon:
298 new_location.theme_icon = theme_icon
299 new_location.location_type = location_type
300 new_location.uri = location_uri
301 new_location.media_types = media
302 self._locations.append(new_location)
303 self.info("Added %r (%r)", location_uri, media)
304
306
307
308 self._load_user_media_locations()
309
310
311 self._load_default_media_locations()
312
313 self.debug("Loaded Locations: %s", self._locations)
314
340
395
421