Home | Trees | Indices | Help |
---|
|
1 # -*- coding: utf-8 -*- 2 # Elisa - Home multimedia server 3 # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 4 # All rights reserved. 5 # 6 # This file is available under one of two license agreements. 7 # 8 # This file is licensed under the GPL version 3. 9 # See "LICENSE.GPL" in the root of this distribution including a special 10 # exception to use Elisa with Fluendo's plugins. 11 # 12 # The GPL part of Elisa is also available under a commercial licensing 13 # agreement from Fluendo. 14 # See "LICENSE.Elisa" in the root directory of this distribution package 15 # for details on that license. 16 17 18 """ 19 Media data access support 20 """ 21 22 23 __maintainer__ = 'Philippe Normand <philippe@fluendo.com>' 24 25 from elisa.core import common, component, media_uri 26 from elisa.core.utils import network 27 from elisa.core.bus import bus_message 28 from elisa.base_components.media_provider import MediaProvider 29 from elisa.extern import upnp_content_directory 30 from twisted.internet import defer, threads 31 3234 """ 35 36 37 TODO: 38 39 - implement blocking_next_location 40 """ 41 name = "upnp_media" 42 4728249 MediaProvider.initialize(self) 50 common.application.bus.register(self._bus_message_received, 51 bus_message.ComponentsLoaded)5254 import louie 55 msg = bus_message.CoherenceDevice('Coherence.UPnP.ControlPoint.MediaServer.detected', 56 self._detected_media_server, 57 louie.Any) 58 common.application.bus.send_message(msg) 59 60 msg = bus_message.CoherenceDevice('Coherence.UPnP.ControlPoint.MediaServer.removed', 61 self._removed_media_server, 62 louie.Any) 63 common.application.bus.send_message(msg)6466 uri = "upnp%s" % control_url[4:] 67 media_manager = common.application.media_manager 68 if media_manager.enabled: 69 media = media_manager.get_source_for_uri(uri) 70 else: 71 media = None 72 return media is not None7375 new_uri = media_uri.MediaUri(uri) 76 if uri.scheme == 'upnp': 77 new_uri.scheme = 'http' 78 return new_uri79 84 8890 device = client.device 91 friendly_name = device.get_friendly_name() 92 93 self.info('Browsing services on device %s' % friendly_name) 94 self.debug('Device USN is: %r', usn) 95 96 services = device.get_services() 97 self.info("Device has %s services" % len(services)) 98 for service in services: 99 self.info("Service type: %s" % service.get_type()) 100 cds1 = "urn:schemas-upnp-org:service:ContentDirectory:1" 101 cds2 = "urn:schemas-upnp-org:service:ContentDirectory:2" 102 if service.get_type() in (cds1, cds2): 103 #service.subscribe() 104 control_url = service.get_control_url() 105 if not self._service_in_db(control_url): 106 self.device_cache[usn] = (control_url, friendly_name) 107 dfr = self._browse(client, 0, requested_count=0, 108 friendly_name=friendly_name, 109 parent_id=-1) 110 dfr.addCallback(self._build_menus, friendly_name, 111 control_url, 0) 112 else: 113 self._build_menus(None, friendly_name, control_url, 0)114116 if usn in self.device_cache: 117 control_url, friendly_name = self.device_cache[usn] 118 del self.device_cache[usn] 119 self.info("Device %s disappeared", friendly_name) 120 uri = "upnp:%s#0" % control_url[5:] 121 action_type = bus_message.MediaLocation.ActionType.LOCATION_REMOVED 122 msg = bus_message.LocalNetworkLocation(action_type, 123 str(friendly_name), 124 'upnp', uri) 125 common.application.bus.send_message(msg)126127 - def _browse(self, client, container_id, starting_index=0, 128 requested_count=0, friendly_name="", parent_id=None):129 """ Create an UPnP client and return a Deferred 130 """ 131 try: 132 client = client.content_directory 133 except: 134 pass 135 control_url = client.url 136 137 self.debug("Browsing %r", control_url) 138 139 if hasattr(client, 'new_browse'): 140 browse = client.new_browse 141 else: 142 browse = client.browse 143 144 dfr = browse(container_id, starting_index=starting_index, 145 requested_count=requested_count) 146 dfr.addCallback(self._add_to_cache, container_id, control_url, 147 friendly_name, client, parent_id) 148 return dfr149150 - def _add_to_cache(self, results, container_id, control_url, friendly_name, 151 client, parent_id, child=None):152 if not child: 153 root = upnp_content_directory.buildHierarchy(results['items'], 154 container_id, 155 friendly_name, False) 156 self.store_in_cache(control_url, container_id, friendly_name, 157 root, client) 158 if container_id != 0: 159 root.parentID = parent_id 160 161 else: 162 root = child 163 164 165 166 self.store_in_cache(control_url, root.id, friendly_name, root,client) 167 for child in root.children: 168 if isinstance(child, upnp_content_directory.Folder): 169 self._add_to_cache(None, container_id, control_url, 170 friendly_name, client, parent_id, child=child) 171 else: 172 ## for url in child.urls.keys(): 173 ## self.store_in_cache(url,None, 174 ## friendly_name, child,client) 175 self.store_in_cache(control_url, child.id, friendly_name, 176 child,client) 177 return root.children178180 for item_id, (uri, item, client) in self.cache.iteritems(): 181 if item.id == id: 182 return (uri, item.name, item) 183 return (None, None, None)184187 if container_id is not None: 188 uri = "%s#%s" % (control_url, container_id) 189 else: 190 uri = control_url 191 #data.parentID = container_id 192 #if uri not in self.cache or (len(data.children) > len(self.cache[uri][1].children) and self.cache[uri][1].children != data.children): 193 self.debug("Storing %s (%s) to cache", uri, data.name)#, data.parentID) 194 self.cache[uri] = (friendly_name, data,client)195 199 211213 # TODO: remove this method, when we have a good http media_provider 214 # => grant scan access to the media_scanner 215 return {}216 219221 file_type = 'directory' 222 mime_type = '' 223 name, container, dummy = self.cache.get(str(self._get_upnp_target(uri)), 224 (None,None, None)) 225 if isinstance(container, upnp_content_directory.Item): 226 file_type = container.get_media_type() 227 228 media_type = {'file_type': file_type, 'mime_type': mime_type} 229 return media_type230232 real_uri = None 233 name, container, dummy = self.cache.get(str(self._get_upnp_target(uri)), 234 (None,None, None)) 235 if isinstance(container, upnp_content_directory.Item): 236 real_uri = media_uri.MediaUri(self._get_best_uri(container)) 237 return real_uri238240 parent = None 241 searched_uri = media_uri.MediaUri(for_uri) 242 searched_uri.fragment = None 243 244 def find_parent(folder_uri, cached_item): 245 p = None 246 247 if isinstance(cached_item, upnp_content_directory.Folder): 248 for child in cached_item.children: 249 if isinstance(child, upnp_content_directory.Item): 250 urls = child.get_urls() 251 keys = urls.keys() 252 keys.sort() 253 child_uri = keys[0] 254 if child_uri == str(searched_uri): 255 p = folder_uri 256 else: 257 f_uri = media_uri.MediaUri(folder_uri) 258 f_uri.fragment = child.id 259 p = find_parent(f_uri, child) 260 if p: 261 break 262 return p263 264 if for_uri.scheme == 'http': 265 for uri, (name, cached_item, dummy) in self.cache.iteritems(): 266 parent = find_parent(uri, cached_item) 267 if parent: 268 parent = media_uri.MediaUri(uri.replace('http','upnp')) 269 break 270 271 else: 272 for_uri = self._get_upnp_target(for_uri) 273 name, cached_item, dummy = self.cache.get(str(for_uri), 274 (None, None, None)) 275 if cached_item: 276 found = None 277 for uri, (short_name, item, d) in self.cache.iteritems(): 278 if item.id == cached_item.parentID: 279 parent = media_uri.MediaUri(uri.replace('http','upnp')) 280 break 281 return parent284 is_dir = True 285 upnp_uri = self._get_upnp_target(uri) 286 friendly_name, folder, client = self.cache.get(upnp_uri,(None,None, 287 None)) 288 if folder: 289 is_dir = isinstance(folder, upnp.content_directory.Folder) 290 return is_dir291293 dfr = self.get_direct_children(uri, []) 294 295 def check_media_type(media_type): 296 file_type = media_type.get('file_type') 297 return file_type in media_types298 299 def final(result): 300 has_children = False 301 for dummy, r in result: 302 if r: 303 has_children = True 304 break 305 return has_children 306 307 def check_children(result): 308 dfrs = [] 309 for child in result: 310 d = self.get_media_type(child[0]) 311 d.addCallback(check_media_type) 312 dfrs.append(d) 313 dfr2 = defer.DeferredList(dfrs) 314 dfr2.addCallback(final) 315 return dfr2 316 317 dfr.addCallback(check_children) 318 return dfr 319 320322 dfr = defer.Deferred() 323 uri = self._get_upnp_target(uri) 324 control_url = self._get_control_url(uri) 325 friendly_name, folder, client = self.cache.get(str(uri),(None,None,None)) 326 327 if folder and isinstance(folder, upnp_content_directory.Folder): 328 if folder.children: 329 folder_children = folder.children 330 self._process_children(folder_children, control_url, children) 331 dfr.callback(children) 332 else: 333 dfr2 = self._browse(client, folder.id, 334 friendly_name=folder.name, 335 parent_id=folder.parentID) 336 dfr2.addCallback(self._process_children, control_url, children, 337 dfr) 338 else: 339 dfr.callback(children) 340 return dfr341344 for child in folder_children: 345 child_uri = "upnp:%s#%s" % (control_url[5:], child.id) 346 is_dir = isinstance(child, upnp_content_directory.Folder) 347 348 if is_dir: 349 child_type = 'directory' 350 else: 351 child_type = 'file' 352 353 child_uri = media_uri.MediaUri(child_uri) 354 if isinstance(child.name, str): 355 child.name = child.name.decode('utf-8') 356 child_uri.label = child.name.encode('utf-8') 357 children.append((child_uri,{})) 358 359 if dfr: 360 dfr.callback(children) 361 362 return children363365 my_address = network.get_host_address() 366 child_uri = None 367 for uri, protocolInfo in item.urls_by_protocol.iteritems(): 368 remote_protocol,remote_network,remote_content_format,dummy = protocolInfo.split(':') 369 if remote_network == my_address: 370 child_uri = uri 371 break 372 373 if not child_uri: 374 urls = item.get_urls() 375 keys = filter(lambda u: not u.startswith('file'), urls.keys()) 376 keys.sort() 377 child_uri = keys[0] 378 return child_uri379381 http_uri = media_uri.MediaUri(uri) 382 http_uri.scheme = 'http' 383 return common.application.media_manager.open(http_uri, mode=mode)384386 upnp_uri = self._get_upnp_target(uri) 387 control_url = self._get_control_url(upnp_uri) 388 friendly_name, folder, client = self.cache.get(str(upnp_uri), 389 (None,None,None)) 390 391 def strip(child): 392 if uri.scheme == 'http': 393 next_uri = media_uri.MediaUri(root) 394 else: 395 next_uri = media_uri.MediaUri(uri) 396 next_uri.fragment = child.id 397 next_uri.label = child.name 398 return next_uri399 400 def get_first_child(children): 401 first_child = None 402 if children: 403 first_child = children[0] 404 first_child = strip(first_child) 405 return first_child 406 407 408 def go_up(p_uri, p_folder, cur_f): 409 idx = 0 410 for child in p_folder.children: 411 if child.id == cur_f.id: 412 break 413 idx += 1 414 if idx == len(p_folder.children) -1: 415 p = self._get_parent(p_uri) 416 r = None 417 if not p: 418 p = root 419 fname, parent_folder, c = self.cache.get(str(self._get_upnp_target(p)), 420 (None,None,None)) 421 r = go_up(p, parent_folder, p_folder) 422 else: 423 try: 424 r = p_folder.children[idx+1] 425 except IndexError: 426 r = None 427 return r 428 429 dfr = defer.Deferred() 430 431 if folder and isinstance(folder, upnp_content_directory.Folder): 432 if len(folder.children): 433 dfr.callback(get_first_child(folder.children)) 434 else: 435 dfr = self._browse(client, folder.id,friendly_name=folder.name, 436 parent_id=folder.parentID) 437 dfr.addCallback(get_first_child) 438 439 else: 440 item = folder 441 parent_uri = self._get_parent(uri) 442 if parent_uri: 443 fname, parent_folder, c = self.cache.get(str(self._get_upnp_target(parent_uri)), 444 (None,None,None)) 445 446 idx = parent_folder.children.index(item) 447 try: 448 next_child = parent_folder.children[idx+1] 449 except IndexError: 450 # let's go up level 451 next_child = go_up(parent_uri, parent_folder, item) 452 453 if isinstance(next_child, upnp_content_directory.Folder): 454 if len(next_child.children): 455 dfr.callback(get_first_child(next_child.children)) 456 else: 457 dfr = self._browse(client, next_child.id, 458 friendly_name=next_child.name, 459 parent_id=next_child.parentID) 460 dfr.addCallback(get_first_child) 461 462 elif isinstance(next_child, upnp_content_directory.Item): 463 dfr.callback(strip(next_child)) 464 else: 465 dfr.callback(None) 466 return dfr 467
Home | Trees | Indices | Help |
---|
Generated by Epydoc 3.0beta1 on Wed Jan 16 19:11:04 2008 | http://epydoc.sourceforge.net |