conduit r1769 - in trunk: . conduit/dataproviders conduit/modules/FileModule conduit/platform



Author: jstowers
Date: Mon Oct 20 19:57:45 2008
New Revision: 1769
URL: http://svn.gnome.org/viewvc/conduit?rev=1769&view=rev

Log:
2008-10-20  John Stowers  <john stowers gmail com>

	* conduit/platform/FileGio.py:
	* conduit/platform/FileGnomeVfs.py:
	* conduit/platform/__init__.py: Change the base class interface as necessary
    to add a GIO VolumeMonitor implementation
	* conduit/dataproviders/VolumeFactory.py: Derive directly from HalFactory
    and no longer use the Vfs.VolumeMonitor implementations to monitor volumes,
    it was not in the spirit of what other derived classes were using VF for
	* conduit/dataproviders/HalFactory.py: Doc updates.
	* conduit/modules/FileModule/FileModule.py: Use the VolumeMonitor class
    directly, and no longer through VolumeFactory. 
    Fixes #557105



Modified:
   trunk/ChangeLog
   trunk/conduit/dataproviders/HalFactory.py
   trunk/conduit/dataproviders/VolumeFactory.py
   trunk/conduit/modules/FileModule/FileModule.py
   trunk/conduit/platform/FileGio.py
   trunk/conduit/platform/FileGnomeVfs.py
   trunk/conduit/platform/__init__.py

Modified: trunk/conduit/dataproviders/HalFactory.py
==============================================================================
--- trunk/conduit/dataproviders/HalFactory.py	(original)
+++ trunk/conduit/dataproviders/HalFactory.py	Mon Oct 20 19:57:45 2008
@@ -34,14 +34,16 @@
         self.item_removed(device_udi)
 
     def _get_properties(self, device):
+        buf = {}
         try:
             device_dbus_obj = self.bus.get_object("org.freedesktop.Hal" ,device)
-            buffer = {}
             for x, y in device_dbus_obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device").items():
-                buffer[str(x)] = str(y)
-            return buffer
+                #DBus *still* does not marshal dbus.String to str correctly,
+                #so we force it to
+                buf[str(x)] = str(y)
         except:
-            return {}
+            log.warn("Could not get HAL properties for %s" % device_udi)
+        return buf
 
     def probe(self):
         """ Enumerate HAL for any entries of interest """

Modified: trunk/conduit/dataproviders/VolumeFactory.py
==============================================================================
--- trunk/conduit/dataproviders/VolumeFactory.py	(original)
+++ trunk/conduit/dataproviders/VolumeFactory.py	Mon Oct 20 19:57:45 2008
@@ -1,81 +1,31 @@
 import logging
-log = logging.getLogger("dataproviders.SimpleFactory")
+log = logging.getLogger("dataproviders.VolumeFactory")
 
 import conduit
-import conduit.dataproviders.SimpleFactory as SimpleFactory
-import conduit.utils as Utils
-import conduit.Vfs as Vfs
+import conduit.dataproviders.HalFactory as HalFactory
 
-import dbus
-
-class VolumeFactory(SimpleFactory.SimpleFactory):
+class VolumeFactory(HalFactory.HalFactory):
     """ 
-    Generic factory for dataproviders that are removable file system based
+    Generic factory for dataproviders that are removable file system based, or
+    more technically, that have the volume capability defined in HAL. This 
+    usually results in them being mounted as removable volumes.
     """
 
-    def __init__(self, **kwargs):
-        SimpleFactory.SimpleFactory.__init__(self, **kwargs)
-
-        self.vol_monitor = Vfs.VolumeMonitor()
-        self.bus = dbus.SystemBus()
-
-        if Utils.dbus_service_available('org.freedesktop.Hal', self.bus):
-            log.info("HAL Initialized")
-            self.vol_monitor.connect("volume-mounted",self._volume_mounted_cb)
-            self.vol_monitor.connect("volume-unmounted",self._volume_unmounted_cb)
-        else:
-            log.warn("HAL Could not be Initialized")
-
-    def _volume_mounted_cb(self, monitor, device_udi):
-        log.info("Volume mounted, udi: %s" % device_udi)
-        if device_udi :
-            props = self._get_properties(device_udi)
-            if self.is_interesting(device_udi, props):
-                mount, label = self._get_device_info(props)
-                kwargs = { "mount": mount, "label": label }
-                self.item_added(device_udi, **kwargs)
-        return True
-
-    def _volume_unmounted_cb(self, monitor, device_udi):
-        log.info("Volume unmounted, udi: %s" % device_udi)
-        if device_udi :
-            if self.is_interesting(device_udi, self._get_properties(device_udi)):
-                self.item_removed(device_udi)
-        return False
-
-    def _get_properties(self, device_udi):
-        try:
-            device_dbus_obj = self.bus.get_object("org.freedesktop.Hal" ,device_udi)
-            return device_dbus_obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device")
-        except:
-            return {}
-
-    def _get_device_info(self, properties):
-        """
-        Returns the mount point and label in a 2-tuple
-        """
-        if properties.has_key("volume.mount_point"):
-            mount = str(properties["volume.mount_point"])
-        else:
-            mount = ""
-        if properties.has_key("volume.label"):
-            label = str(properties["volume.label"])
-        else:
-            label = ""
-
-        return (mount, label)
-        
     def probe(self):
         """
         Called after VolumeFactory is initialised to detect already connected volumes
         """
-        for device_udi in self.vol_monitor.get_mounted_volumes():
-            if device_udi != None:
-                props = self._get_properties(device_udi)
-                if self.is_interesting(device_udi, props):
-                    mount, label = self._get_device_info(props)
-                    kwargs = { "mount": mount, "label": label }
-                    self.item_added(device_udi, **kwargs)
+        for device_udi in self.hal.FindDeviceByCapability("volume"):
+            props = self._get_properties(device_udi)
+            
+            #convert the mountpoint to a string uri because that is what 
+            #all the folder dataproviders work on
+            if props.get("volume.mount_point"):
+                props["mount"] = "file://" + str(props["volume.mount_point"])
+                log.debug("Adjusted mount: %s", props["mount"])
+
+            if self.is_interesting(device_udi, props):
+                self.item_added(device_udi, **kwargs)
 
     def get_args(self, udi, **kwargs):
         """ VolumeFactory passes mount point and udi to dataproviders """

Modified: trunk/conduit/modules/FileModule/FileModule.py
==============================================================================
--- trunk/conduit/modules/FileModule/FileModule.py	(original)
+++ trunk/conduit/modules/FileModule/FileModule.py	Mon Oct 20 19:57:45 2008
@@ -7,7 +7,7 @@
 import conduit.dataproviders.DataProvider as DataProvider
 import conduit.dataproviders.DataProviderCategory as DataProviderCategory
 import conduit.dataproviders.File as FileDataProvider
-import conduit.dataproviders.VolumeFactory as VolumeFactory
+import conduit.dataproviders.SimpleFactory as SimpleFactory
 import conduit.dataproviders.AutoSync as AutoSync
 import conduit.utils as Utils
 import conduit.Vfs as Vfs
@@ -133,12 +133,26 @@
         elif event == self._monitor.MONITOR_EVENT_DELETED:
             self.handle_deleted(event_uri)
 
-class RemovableDeviceFactory(VolumeFactory.VolumeFactory):
+class RemovableDeviceFactory(SimpleFactory.SimpleFactory):
 
     def __init__(self, **kwargs):
-        VolumeFactory.VolumeFactory.__init__(self, **kwargs)
+        SimpleFactory.SimpleFactory.__init__(self, **kwargs)
         self._volumes = {}
         self._categories = {}
+        self._vm = Vfs.VolumeMonitor()
+        self._vm.connect("volume-mounted",self._volume_mounted_cb)
+        self._vm.connect("volume-unmounted",self._volume_unmounted_cb)
+
+    def _volume_mounted_cb(self, monitor, device_udi, mount, label):
+        log.info("Volume mounted, %s : (%s : %s)" % (device_udi,mount,label))
+        if device_udi:
+            self._check_preconfigured(device_udi, mount, label)
+            self.item_added(device_udi, mount=mount, label=label)
+
+    def _volume_unmounted_cb(self, monitor, device_udi):
+        log.info("Volume unmounted, %s" % device_udi)
+        if device_udi and device_udi in self._volumes:
+            self.item_removed(device_udi)
 
     def _make_class(self, udi, folder, name):
         log.info("Creating preconfigured folder dataprovider: %s" % folder)
@@ -152,67 +166,61 @@
         klass = type(
                 "FolderTwoWay",
                 (FolderTwoWay,),
-                info
-                )
+                info)
         return klass
 
+    def _check_preconfigured(self, udi, mountUri, label):
+        #check for the presence of a mount/.conduit group file
+        #which describe the folder sync groups, and their names,
+        try:
+            groups = FileDataProvider.read_removable_volume_group_file(mountUri)
+        except Exception, e:
+            log.warn("Error reading volume group file: %s" % e)
+            groups = ()
+            
+        if len(groups) > 0:
+            self._volumes[udi] = []
+            for relativeUri,name in groups:
+                klass = self._make_class(
+                                    udi=udi,
+                                    #uri is relative, make it absolute
+                                    folder="%s%s" % (mountUri,relativeUri),
+                                    name=name)
+                self._volumes[udi].append(klass)
+        else:
+            klass = self._make_class(
+                                udi=udi,
+                                folder=mountUri,
+                                name=None)
+            self._volumes[udi] = [klass]
+
+    def probe(self):
+        """
+        Called after initialised to detect already connected volumes
+        """
+        volumes = self._vm.get_mounted_volumes()
+        for device_udi in volumes:
+            if device_udi:
+                mount,label = volumes[device_udi]
+                self._check_preconfigured(device_udi, mount, label)
+                self.item_added(device_udi, mount=mount, label=label)
+            if device_udi:
+                mount,label = volumes[device_udi]
+                self.item_added(device_udi, mount=mount, label=label)
+
     def emit_added(self, klass, initargs, category):
         """
         Override emit_added to allow duplictes. The custom key is based on
         the folder and the udi to allow multiple preconfigured groups per
         usb key
         """
-        return VolumeFactory.VolumeFactory.emit_added(self, 
+        return SimpleFactory.SimpleFactory.emit_added(self, 
                         klass, 
                         initargs, 
                         category, 
                         customKey="%s-%s" % (klass.DEFAULT_FOLDER, klass._udi_)
                         )
 
-    def is_interesting(self, udi, props):
-        if props.has_key("info.parent") and props.has_key("info.parent") != "":
-            prop2 = self._get_properties(props["info.parent"])
-            if prop2.has_key("storage.removable") and prop2["storage.removable"] == True:
-                mount,label = self._get_device_info(props)
-                log.info("Detected removable volume %s %s" % (label,mount))
-
-                #short circuit the logic here to test if this is a volume being
-                #unmounted. Its still interesting, we just dont make a 
-                #klass for it
-                if udi in self._volumes and not mount:
-                    log.debug("This is a FileModule being removed")
-                    del(self._volumes[udi])
-                    return True
-
-                #check for the presence of a mount/.conduit group file
-                #which describe the folder sync groups, and their names,
-                mountUri = "file://%s" % mount
-                try:
-                    groups = FileDataProvider.read_removable_volume_group_file(mountUri)
-                except Exception, e:
-                    log.warn("Error reading volume group file: %s" % e)
-                    groups = ()
-                    
-                if len(groups) > 0:
-                    self._volumes[udi] = []
-                    for relativeUri,name in groups:
-                        klass = self._make_class(
-                                            udi=udi,
-                                            #uri is relative, make it absolute
-                                            folder="%s%s" % (mountUri,relativeUri),
-                                            name=name)
-                        self._volumes[udi].append(klass)
-                else:
-                    if Vfs.uri_is_on_removable_volume(mountUri):
-                        klass = self._make_class(
-                                            udi=udi,
-                                            folder=mountUri,
-                                            name=None)
-                        self._volumes[udi] = [klass]
-                        
-                return True
-        return False
-    
     def get_category(self, udi, **kwargs):
         if not self._categories.has_key(udi):
             self._categories[udi] = DataProviderCategory.DataProviderCategory(

Modified: trunk/conduit/platform/FileGio.py
==============================================================================
--- trunk/conduit/platform/FileGio.py	(original)
+++ trunk/conduit/platform/FileGio.py	Mon Oct 20 19:57:45 2008
@@ -276,7 +276,27 @@
             return False, None
 
 class VolumeMonitor(conduit.platform.VolumeMonitor):
-    pass
+
+    def __init__(self):
+        conduit.platform.VolumeMonitor.__init__(self)
+        self._vm = gio.volume_monitor_get()
+        self._vm.connect("mount-added", self._mounted_cb)
+        self._vm.connect("mount-removed", self._unmounted_cb)
+
+    def _mounted_cb(self, sender, mount):
+        self.emit("volume-mounted", 
+            mount.get_uuid(),
+            mount.get_root().get_uri(),
+            mount.get_name())
+
+    def _unmounted_cb(self, sender, mount):
+        self.emit("volume-unmounted", mount.get_uuid())
+
+    def get_mounted_volumes(self):
+        vols = {}
+        for m in self._vm.get_mounts():
+            vols[m.get_uuid()] = (m.get_root().get_uri(), m.get_name())
+        return vols
 
 class FileMonitor(conduit.platform.FileMonitor):
     pass

Modified: trunk/conduit/platform/FileGnomeVfs.py
==============================================================================
--- trunk/conduit/platform/FileGnomeVfs.py	(original)
+++ trunk/conduit/platform/FileGnomeVfs.py	Mon Oct 20 19:57:45 2008
@@ -182,19 +182,19 @@
     def is_on_removale_volume(self):
         path = self.get_local_path()
         if path:
-            return VolumeMonitor().volume_is_removable(path)
+            return gnomevfs.VolumeMonitor().get_volume_for_path(path).is_user_visible()
         return False
 
     def get_removable_volume_root_uri(self):
         path = self.get_local_path()
         if path:
-            return VolumeMonitor().volume_get_root_uri(path)
+            return gnomevfs.VolumeMonitor().get_volume_for_path(path).get_activation_uri()
         return False
 
     def get_filesystem_type(self):
         path = self.get_local_path()
         if path:
-            return VolumeMonitor().volume_get_fstype(path)
+            return gnomevfs.VolumeMonitor().get_volume_for_path(path).get_filesystem_type()
         return None
 
     @staticmethod
@@ -287,23 +287,23 @@
     def __init__(self):
         conduit.platform.VolumeMonitor.__init__(self)
         self._vm = gnomevfs.VolumeMonitor()
-        self._vm.connect("volume-mounted", self._mounted_unmounted_cb, "volume-mounted")
-        self._vm.connect("volume-unmounted", self._mounted_unmounted_cb, "volume-unmounted")
+        self._vm.connect("volume-mounted", self._mounted_cb)
+        self._vm.connect("volume-unmounted", self._unmounted_cb)
 
-    def _mounted_unmounted_cb(self, sender, volume, signalname):
-        self.emit(signalname, volume.get_hal_udi())
+    def _mounted_cb(self, sender, volume):
+        self.emit("volume-mounted", 
+            volume.get_hal_udi(),
+            volume.get_activation_uri(),
+            volume.get_display_name())
 
-    def get_mounted_volumes(self):
-        return [volume.get_hal_udi() for volume in self._vm.get_mounted_volumes()]
-
-    def volume_is_removable(self, path):
-        return self._vm.get_volume_for_path(path).is_user_visible()
+    def _unmounted_cb(self, sender, volume):
+        self.emit("volume-unmounted", volume.get_hal_udi())
 
-    def volume_get_fstype(self, path):
-        return self._vm.get_volume_for_path(path).get_filesystem_type()
-
-    def volume_get_root_uri(self, path):
-        return self._vm.get_volume_for_path(path).get_activation_uri()
+    def get_mounted_volumes(self):
+        vols = {}
+        for v in self._vm.get_mounted_volumes():
+            vols[v.get_hal_udi()] = (v.get_activation_uri(), v.get_display_name())
+        return vols
 
 class FileMonitor(conduit.platform.FileMonitor):
 

Modified: trunk/conduit/platform/__init__.py
==============================================================================
--- trunk/conduit/platform/__init__.py	(original)
+++ trunk/conduit/platform/__init__.py	Mon Oct 20 19:57:45 2008
@@ -97,25 +97,21 @@
 class VolumeMonitor(gobject.GObject):
     __gsignals__ = {
         "volume-mounted" :      (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [
-            gobject.TYPE_STRING]),      #udi
+            gobject.TYPE_STRING,        #udi/uuid
+            gobject.TYPE_STRING,        #mount point
+            gobject.TYPE_STRING]),      #label
         "volume-unmounted" :    (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [
-            gobject.TYPE_STRING])       #udi
+            gobject.TYPE_STRING])       #udi/uuid
 
     }
     def __init__(self):
         gobject.GObject.__init__(self)
 
     def get_mounted_volumes(self):
-        return []
-
-    def volume_is_removable(self, path):
-        return False
-
-    def volume_get_fstype(self, path):
-        return None
-
-    def volume_get_root_uri(self, path):
-        return None
+        """
+        @returs: Dict of mounted volumes, uuid : (mount, name) 
+        """
+        return {}
 
 class FileMonitor(gobject.GObject):
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]