Author: dmeyer
Date: Tue Mar 11 16:55:52 2008
New Revision: 3181

Log:
Use gobject_thread for dbus. This makes it possible to
run hal in the normal notifier mainloop. This is the
first step to include the hwmon/thumbnailer code in
the main beacon daemon to remove the extra process.


Modified:
   trunk/beacon/src/server/hwmon/hal.py

Modified: trunk/beacon/src/server/hwmon/hal.py
==============================================================================
--- trunk/beacon/src/server/hwmon/hal.py        (original)
+++ trunk/beacon/src/server/hwmon/hal.py        Tue Mar 11 16:55:52 2008
@@ -4,6 +4,7 @@
 # -----------------------------------------------------------------------------
 # $Id$
 #
+# http://people.freedesktop.org/~david/hal-spec/hal-spec.html#interface-manager
 # -----------------------------------------------------------------------------
 # kaa.beacon.server - A virtual filesystem with metadata
 # Copyright (C) 2006-2008 Dirk Meyer
@@ -49,7 +50,10 @@
 # only supports the glib mainloop and no generic one.
 from dbus.mainloop.glib import DBusGMainLoop
 DBusGMainLoop(set_as_default=True)
-kaa.main.select_notifier('gtk', x11=False)
+
+# hal needs dbus
+kaa.gobject_set_threaded()
+# kaa.main.select_notifier('gtk', x11=False)
 
 # kaa.beacon imports
 from kaa.beacon.server.config import config
@@ -62,74 +66,87 @@
 # HAL signals
 signals = kaa.Signals('add', 'remove', 'changed', 'failed')
 
[EMAIL PROTECTED](kaa.MAINTHREAD)
+def emit_signal(signal, *args):
+    """
+    Wrapper to emit the signal in the main thread.
+    """
+    return signals[signal].emit(*args)
+
 
 class Device(object):
     """
     A device object
+    FIXME: lock because dbus and mainthread use this object
     """
     def __init__(self, prop, bus):
         self.udi = prop['info.udi']
         self.prop = prop
-        self._eject = False
         self._bus = bus
 
     # -------------------------------------------------------------------------
     # Public API
     # -------------------------------------------------------------------------
 
-    def mount(self, umount=False):
+    @kaa.threaded(kaa.GOBJECT)
+    def mount(self):
         """
-        Mount or umount the device.
+        Mount the device.
+        FIXME: use HAL API
         """
-        if self.prop.get('volume.mount_point') and not umount:
+        if self.prop.get('volume.mount_point'):
             # already mounted
             return False
         for device, mountpoint, type, options in fstab():
             if device == self.prop['block.device'] and \
                    (options.find('users') >= 0 or os.getuid() == 0):
                 cmd = ('mount', self.prop['block.device'])
-                if umount:
-                    cmd = ('umount', self.prop['block.device'])
                 break
         else:
-            if umount:
-                cmd = ("pumount", self.prop.get('volume.mount_point'))
-            else:
-                cmd = ("pmount-hal", self.udi)
-        proc = kaa.Process(cmd)
-        proc.signals['stdout'].connect(log.warning)
-        proc.signals['stderr'].connect(log.error)
-        proc.start()
+            cmd = ("pmount-hal", self.udi)
+        os.system(' '.join(cmd))
         return True
 
 
+    @kaa.threaded(kaa.GOBJECT)
     def eject(self):
         """
         Eject the device. This includes umounting and removing from
         the list. Devices that can't be ejected (USB sticks) are only
         umounted and removed from the list.
+        FIXME: use HAL API
         """
-        if self.prop.get('volume.mount_point'):
-            # umount before eject
-            self._eject = True
-            return self.mount(umount=True)
         # remove from list
         _device_remove(self.udi)
+        if self.prop.get('volume.mount_point'):
+            # umount before eject
+            for device, mountpoint, type, options in fstab():
+                if device == self.prop['block.device'] and \
+                       (options.find('users') >= 0 or os.getuid() == 0):
+                    cmd = ('umount', self.prop['block.device'])
+                    break
+            else:
+                cmd = ("pumount", self.prop.get('volume.mount_point'))
+            os.system(' '.join(cmd))
         if self.prop.get('volume.is_disc'):
             eject(self.prop['block.device'])
-
+            
 
     def __getattr__(self, attr):
+        """
+        Return attribute based on the properties.
+        """
         return getattr(self.prop, attr)
 
 
     # -------------------------------------------------------------------------
-    # Callbacks
+    # Callbacks called in the GOBJECT thread
     # -------------------------------------------------------------------------
 
     def _modified(self, num_changes, change_list):
         """
         Device was modified (mount, umount..)
+        Called by dbus in GOBJECT thread
         """
         for c in change_list:
             if c[0] == 'volume.mount_point':
@@ -142,23 +159,27 @@
     def _property_update(self, prop):
         """
         Update internal property list and call signal.
+        Called by dbus in GOBJECT thread
         """
+        prop = dict(prop)
         prop['info.parent'] = self.prop.get('info.parent')
-        if not prop.get('volume.mount_point') and self._eject:
-            self.prop = prop
-            return self.eject()
-        signals['changed'].emit(self, prop)
+        emit_signal('changed', self, prop).wait()
         self.prop = prop
 
 
 
 # -----------------------------------------------------------------------------
 # Connection handling
+#
+# All functions below this point are called in the GOBJECT thread. The used
+# global variables are only used by this functions, but they modify the device
+# objects. This needs a lock.
 # -----------------------------------------------------------------------------
 
 _bus = None
 _connection_timeout = 5
 
[EMAIL PROTECTED](kaa.GOBJECT)
 def start():
     """
     Connect to DBUS and start to connect to HAL.
@@ -173,7 +194,7 @@
         # unable to connect to dbus
         if not _connection_timeout:
             # give up
-            signals['failed'].emit('unable to connect to dbus')
+            emit_signal('failed', 'unable to connect to dbus')
             return False
         kaa.OneShotTimer(start).start(2)
         return False
@@ -181,7 +202,7 @@
         obj = _bus.get_object('org.freedesktop.Hal', 
'/org/freedesktop/Hal/Manager')
     except Exception, e:
         # unable to connect to hal
-        signals['failed'].emit('hal not found on dbus')
+        emit_signal('failed', 'hal not found on dbus')
         return False
     hal = dbus.Interface(obj, 'org.freedesktop.Hal.Manager')
     hal.GetAllDevices(reply_handler=_device_all, error_handler=log.error)
@@ -200,6 +221,7 @@
 def _device_all(device_names):
     """
     HAL callback with the list of all known devices.
+    Called by dbus in GOBJECT thread.
     """
     for name in device_names:
         obj = _bus.get_object("org.freedesktop.Hal", str(name))
@@ -211,6 +233,7 @@
 def _device_new(udi):
     """
     HAL callback for a new device.
+    Called by dbus in GOBJECT thread.
     """
     obj = _bus.get_object("org.freedesktop.Hal", udi)
     obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device",
@@ -218,9 +241,11 @@
                          error_handler=log.error)
 
 
[EMAIL PROTECTED](kaa.GOBJECT)
 def _device_remove(udi):
     """
     HAL callback when a device is removed.
+    Called by dbus in GOBJECT thread or by eject
     """
     if udi in _blockdevices:
         del _blockdevices[udi]
@@ -238,21 +263,23 @@
     _devices.remove(dev)
     # signal changes
     if isinstance(dev.prop.get('info.parent'), dict):
-        signals['remove'].emit(dev)
+        emit_signal('remove', dev)
 
 
 def _device_add(prop, udi, removable=False):
     """
     HAL callback for property list of a new device. If removable is set to
     False this functions tries to detect if it is removable or not.
+    Called by dbus in GOBJECT thread.
     """
+    prop = dict(prop)
     if not 'volume.mount_point' in prop:
         if 'linux.sysfs_path' in prop and 'block.device' in prop:
             _blockdevices[udi] = prop
             for dev in _devices:
                 if dev.prop.get('info.parent') == udi:
                     dev.prop['info.parent'] = prop
-                    signals['add'].emit(dev)
+                    emit_signal('add', dev)
         return
 
     if prop.get('block.device').startswith('/dev/mapper') or \
@@ -298,12 +325,23 @@
     if parent:
         prop['info.parent'] = parent
         # signal changes
-        signals['add'].emit(dev)
+        emit_signal('add', dev)
 
 
 if __name__ == '__main__':      
+    def changed(dev, prop):
+        print 'changed', dev.get('info.parent')
+        print
+    def remove(dev):
+        print 'lost', dev
     def new_device(dev):
+        print kaa.is_mainthread()
         print dev.udi
+        dev.mount()
+        kaa.OneShotTimer(dev.eject).start(1)
+    kaa.gobject_set_threaded()
     signals['add'].connect(new_device)
+    signals['changed'].connect(changed)
+    signals['remove'].connect(remove)
     start()
     kaa.main.run()

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to