Package elisa :: Package plugins :: Package good :: Package gvfs_plugin :: Module gnomevfs_media
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.good.gvfs_plugin.gnomevfs_media

  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  __maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>' 
 18   
 19  from elisa.base_components.media_provider import MediaProvider 
 20  from elisa.core.media_file import MediaFile 
 21  from elisa.core.media_uri import MediaUri 
 22  from elisa.core.utils import misc 
 23  from elisa.core.bus import bus_message 
 24  from elisa.core import common 
 25  import os, re 
 26   
 27  import gnomevfs 
 28  from twisted.internet import defer, threads 
 29  from elisa.core.utils import deferred_action 
 30   
31 -class GnomevfsMedia(MediaProvider):
32 33 hidden_file_pattern = re.compile("\..*") 34
35 - def __init__(self):
36 MediaProvider.__init__(self) 37 self.cwd = gnomevfs.URI(os.getcwd()) 38 self.smb_groups = [] 39 self._def_action = deferred_action.DeferredActionsManager()
40
41 - def _uri_join(self, uri, filename):
42 if uri.scheme == 'smb': 43 if uri.path == '/': 44 # we're browsing SMB workgroups. GnomeVFS doesn't support 45 # smb://workgroup/host .. so we remove the workgroup 46 # name from the uri 47 f_uri = MediaUri('smb://' + filename) 48 if filename not in self.smb_groups: 49 self.smb_groups.append(str(f_uri)) 50 else: 51 f_uri = uri.join(filename) 52 in_workgroup = self._uri_in_group(f_uri) 53 if in_workgroup: 54 f_uri = MediaUri('smb://%s' % filename) 55 else: 56 f_uri = uri.join(filename) 57 return f_uri
58
59 - def _uri_in_group(self, f_uri):
60 return len(filter(lambda group_uri: str(f_uri).startswith(group_uri), 61 self.smb_groups)) > 0
62
63 - def initialize(self):
64 uri = "smb:///" 65 action_type = bus_message.MediaLocation.ActionType.LOCATION_ADDED 66 # FIXME: "Samba shares" should not be shown to the user. Instead, 67 # the tree of workgroups should be flattened and all the machines on 68 # the local network should be added under "Home network" 69 msg = bus_message.LocalNetworkLocation(action_type, "Samba shares", 70 'smb', uri, 71 media_types=['video','audio', 72 'image'], 73 theme_icon='network_share_icon')
74 # TODO: re-enable that when i figure out why it makes elisa segfault when 75 # running in the office with various SMB shares 76 #common.application.bus.send_message(msg) 77 78
79 - def supported_uri_schemes__get(self):
80 return {'smb' : 0, 'sftp' : 250, 'http' : 250, 'ftp' : 250}
81 82
83 - def is_directory(self, uri):
84 return self._def_action.insert_action(0, self._blocking_is_directory, 85 uri)
86 87
88 - def _blocking_is_directory(self, uri):
89 is_dir = False 90 if str(uri).find('m3u') == -1: 91 try: 92 info = gnomevfs.get_file_info(str(uri)).type 93 except Exception, exc: 94 # Sorry, But I can't figure out how all the possible gnomevfs 95 # exceptions are named.... 96 # ... you lazy 97 pass 98 else: 99 if info == gnomevfs.FILE_TYPE_DIRECTORY: 100 is_dir = True 101 elif info == gnomevfs.FILE_TYPE_SYMBOLIC_LINK: 102 try: 103 gnomevfs.open_directory(str(uri)) 104 except: 105 pass 106 else: 107 is_dir = True 108 109 return is_dir
110
111 - def has_children_with_types(self, uri, media_types):
112 return self._def_action.insert_action(0, self._blocking_has_children_with_types, uri, media_types)
113 114
115 - def _blocking_has_children_with_types(self, uri, media_types):
116 has_children = False 117 if self._blocking_is_directory(uri): 118 try: 119 contents = gnomevfs.open_directory(str(uri)) 120 except Exception, error: 121 self.warning("Could not list directory %r: %s", uri, error) 122 else: 123 while contents and not has_children: 124 try: 125 filename = contents.next().name 126 except StopIteration: 127 break 128 try: 129 child_uri = uri.join(filename) 130 media_type = self._blocking_get_media_type(child_uri) 131 if media_type: 132 has_children = media_type['file_type'] in media_types 133 except UnicodeDecodeError: 134 ## give a message here? 135 continue 136 return has_children
137 138
139 - def _open_directory(self, uri):
140 try: 141 handle = gnomevfs.open_directory(str(uri)) 142 except (gnomevfs.NotADirectoryError, 143 gnomevfs.ServiceNotAvailableError), exc: 144 self.warning("Problem accessing %s : %s" % (uri,exc)) 145 self.warning("Exception type: %s" % exc.__class__) 146 handle = None 147 return handle
148
149 - def get_media_type(self, uri):
150 return self._def_action.insert_action(0, self._blocking_get_media_type, uri)
151
152 - def _blocking_get_media_type(self, uri):
153 file_type = '' 154 mime_type = '' 155 156 if not self._blocking_is_directory(uri): 157 mime_type, file_type = misc.get_media_infos_from_mime(uri) 158 # TODO: if nothing useful found, use the metadata_manager? 159 #file_type = 'audio' 160 else: 161 file_type = 'directory' 162 163 return { 'file_type' : file_type, 164 'mime_type' : mime_type }
165
166 - def get_direct_children(self, uri, children_with_info):
167 return self._def_action.insert_action(0, self._blocking_get_direct_children, uri, children_with_info)
168
169 - def _blocking_get_direct_children(self, uri, children_with_info):
170 # FIXME: Got to check the children first 171 # maybe we are loading them again... 172 if self._blocking_is_directory(uri): 173 handle = self._open_directory(uri) 174 index = 0 175 if handle: 176 for i in handle: 177 if self.hidden_file_pattern.match(i.name): 178 continue 179 #file_type = self.get_file_type(child_uri) 180 try: 181 child = self._uri_join(uri, unicode(i.name)) 182 #child = uri.join(unicode(i.name)) 183 children_with_info.append( (child, {}) ) 184 index += 1 185 except UnicodeDecodeError, e: 186 self.warning("UnicodeDecodeError with filename %s/%s" % (uri, i.name)) 187 188 return children_with_info
189
190 - def open(self, uri, mode='r'):
191 return self._def_action.insert_action(0, self._blocking_open, uri, mode)
192
193 - def _blocking_open(self, uri, mode='r'):
194 gnome_mode = gnomevfs.OPEN_READ 195 if mode == "w": 196 gnome_mode = gnomevfs.OPEN_WRITE 197 # The other are currently not supported 198 ret = None 199 if not self._blocking_is_directory(uri): 200 try: 201 handle = gnomevfs.Handle(str(uri)) 202 except Exception, exc: 203 # Currently I don't know what Exceptions might be raised by 204 # gnomevfs.Handle 205 self.info("Could not open %s : %s" % (uri, exc)) 206 # FIXME: should raise it so that caller gets warned 207 else: 208 ret = MediaFile(self, handle) 209 return ret
210
211 - def clean(self):
212 self._def_action.stop()
213
214 - def next_location(self, uri, root=None):
215 return self._def_action.insert_action(0, self._blocking_next_location, 216 uri,root=root)
217
218 - def read(self, media_file, size=-1):
219 return self._def_action.insert_action(0, self._blocking_read, 220 media_file, size=size)
221
222 - def _blocking_next_location(self, uri, root=None):
223 file = uri.filename 224 parent = uri.parent 225 children = self._blocking_get_direct_children(uri.parent,[]) 226 227 files = [ uri.filename for (uri, metadata) in children ] 228 files.sort() 229 230 try: 231 index = files.index(file) +1 232 except ValueError: 233 index = 0 234 235 try: 236 filename = files[index] 237 next_uri = parent + filename 238 except IndexError: 239 next_uri = None 240 241 return next_uri
242
243 - def _blocking_previous_location(self, uri):
244 file = uri.filename 245 parent = uri.parent 246 children = [] 247 self._blocking_get_direct_children(uri.parent,children) 248 249 files = [ uri.filename for uri in children ] 250 files.sort() 251 252 try: 253 index = files.index(file) -1 254 except ValueError: 255 index = 0 256 257 try: 258 filename = files[index] 259 next_uri = parent + '/' + filename 260 except IndexError: 261 next_uri = None 262 263 return next_uri
264
265 - def _blocking_read(self, media_file, size=-1):
266 handle = media_file.descriptor 267 data = "" 268 if size == -1: 269 buffer_size = 1000 270 while True: 271 try: 272 data_chunk = handle.read(buffer_size) 273 data += data_chunk 274 except gnomevfs.EOFError, error: 275 break 276 else: 277 try: 278 data = handle.read(size) 279 except gnomevfs.EOFError, error: 280 # FIXME: raise exception ? 281 self.warning(error) 282 return data
283