home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / jockey / xorg_driver.py < prev   
Encoding:
Python Source  |  2008-11-24  |  14.0 KB  |  337 lines

  1. # (c) 2007 Canonical Ltd.
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License along
  14. # with this program; if not, write to the Free Software Foundation, Inc.,
  15. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16.  
  17. '''Abstract handler for a restricted X.org graphics driver.'''
  18.  
  19. import os.path, logging
  20.  
  21. import XKit.xutils
  22. import XKit.xorgparser
  23.  
  24. from handlers import KernelModuleHandler
  25. from oslib import OSLib
  26.  
  27. # dummy stub for xgettext
  28. def _(x): return x
  29.  
  30. #--------------------------------------------------------------------#
  31.  
  32. class XorgDriverHandler(KernelModuleHandler):
  33.     '''Abstract class for a restricted X.org graphics driver.'''
  34.  
  35.     def __init__(self, backend, module, driver_package, xorg_driver,
  36.         alt_free_driver, extra_conf_options={}, add_modules=[],
  37.             disable_modules=[], remove_modules=[], name=None, description=None,
  38.             rationale=None):
  39.         '''Create handler for a particular X.org graphics driver.
  40.         
  41.         This usually consists of a kernel module and a driver package, plus
  42.         some xorg.conf configuration.
  43.  
  44.         - backend, module, driver_package, name, description, rationale: as in
  45.           KernelModuleHandler
  46.         - xorg_driver: name of the X.org driver as it appears in xorg.conf
  47.         - alt_free_driver: free fallback driver if this one gets disabled
  48.         - extra_conf_options: dictionary of extra "Option"s that go into the
  49.           Device section of xorg.conf
  50.         - add_modules: list of modules that get added to the "Module" section
  51.           of xorg.conf when enabling this driver (and removed when disabling)
  52.         - remove_modules: list of modules that get removed from the "Module"
  53.           section of xorg.conf when enabling this driver (and added when disabling)
  54.         '''
  55.         KernelModuleHandler.__init__(self, backend, module, name, description,
  56.             rationale)
  57.         self.package = driver_package
  58.         self.xorg_driver = xorg_driver
  59.         self.alt_free_driver = alt_free_driver
  60.         self.extra_conf_options = extra_conf_options
  61.         self.add_modules = add_modules
  62.         self.disable_modules = disable_modules
  63.         self.remove_modules = remove_modules
  64.         
  65.         if os.path.exists(OSLib.inst.xorg_conf_path):
  66.             try:
  67.                 self.xorg_conf = XKit.xutils.XUtils(OSLib.inst.xorg_conf_path)
  68.             except XKit.xorgparser.ParseException:
  69.                 # for now, do not mess up an already broken xorg.conf any
  70.                 # further; TODO: UI dialog question to start from scratch
  71.                 self.xorg_conf = None
  72.         else:
  73.             self.xorg_conf = XKit.xutils.XUtils()
  74.  
  75.     def id(self):
  76.         '''Return a unique identifier of the handler.'''
  77.  
  78.         i = 'xorg:' + self.module
  79.         if self.driver_vendor:
  80.             i += ':' + self.driver_vendor.replace(' ', '_')
  81.         return i
  82.  
  83.     def can_change(self):
  84.         if self.xorg_conf:
  85.             return None
  86.         else:
  87.             # translators: %s is the path to xorg.conf
  88.             return _('Reconfiguring X.org video drivers is not '
  89.                 'possible: %s is invalid.') % OSLib.inst.xorg_conf_path
  90.  
  91.     def enabled(self):
  92.         if self.xorg_conf:
  93.             try:
  94.                 driver = self.xorg_conf.getDriver('Device', 0)
  95.             except (XKit.xorgparser.OptionException, XKit.xorgparser.SectionException), error:
  96.                 driver = None
  97.                 logging.debug('XorgDriverHandler.enabled() [module: %s, package: %s, xorg driver: %s): exception %s, considering disabled',
  98.                     self.module, self.package, self.xorg_driver, str(error))
  99.                 logging.debug('%s', str(self.xorg_conf.globaldict))
  100.                 return False
  101.             
  102.             if self.xorg_conf.isDriverEnabled(self.xorg_driver) == False:
  103.                 driver = None
  104.                 logging.debug('XorgDriverHandler isDriverEnabled (%s, %s, %s): xorg.conf driver %s, considering disabled' % (
  105.                     self.module, self.package, self.xorg_driver, str(driver)))
  106.                 return False
  107.         
  108.             logging.debug('XorgDriverHandler(%s, %s, %s): xorg.conf driver matches' % (
  109.                     self.module, self.package, self.xorg_driver))
  110.         return KernelModuleHandler.enabled(self)
  111.  
  112.     def used(self):
  113.         '''Return if the handler is currently in use.'''
  114.  
  115.         # if we just enabled the driver, it cannot possibly be in use yet
  116.         # TODO: it would be much better to ask X directly, or at least parse
  117.         # /var/log/Xorg.0.log
  118.         if self.changed() and self.enabled():
  119.             return False
  120.         return KernelModuleHandler.used(self)
  121.  
  122.     def _mod_status(self, module, action):
  123.         '''Check if a module is handled in current configuration.
  124.  
  125.         action can be "Load" or "Disable".
  126.         '''
  127.         for i in xrange(len(self.xorg_conf.globaldict['Module'])):
  128.             try:
  129.                 modules = self.xorg_conf.getValue('Module', action, i)
  130.             except XKit.xorgparser.OptionException:
  131.                 # there is no matching action
  132.                 continue
  133.             
  134.             # see if it's a list or a string
  135.             if type(modules) == type(''): # string
  136.                 if modules == module:
  137.                     return True
  138.             else: # list
  139.                 for mod in modules:
  140.                     if mod == module:
  141.                         return True
  142.         return False
  143.     
  144.     def _mod_enabled(self, module):
  145.         #See whether the xorg.conf has a module set to "Load"
  146.         return self._mod_status(module, 'Load')
  147.     
  148.     def _mod_disabled(self, module):
  149.         #See whether the xorg.conf has a module set to "Disable"
  150.         return self._mod_status(module, 'Disable')
  151.     
  152.     def enable(self):
  153.         if not self.xorg_conf:
  154.             logging.error('XorgDriverHandler.enable(): invalid xorg.conf, skipping')
  155.             return False
  156.  
  157.         KernelModuleHandler.enable(self)
  158.  
  159.         # do not mangle xorg.conf if package installation has been aborted
  160.         if not OSLib.inst.package_installed(self.package):
  161.             return
  162.         
  163.         # see if the same proprietary driver is in use
  164.         # in the xorg.conf. If so do not create a backup
  165.         has_proprietary = False
  166.         it = 0
  167.         for section in self.xorg_conf.globaldict['Device']:
  168.             try:
  169.                 driver = self.xorg_conf.getDriver('Device', it)
  170.                 if driver == self.xorg_driver:
  171.                     has_proprietary = True
  172.                     break
  173.             except XKit.xorgparser.OptionException:
  174.                 # no driver is specified
  175.                 pass
  176.             it += 1
  177.         
  178.         # backup the current xorg.conf
  179.         if os.path.exists(OSLib.inst.xorg_conf_path):
  180.             if not has_proprietary:
  181.                 open(os.path.join(OSLib.inst.backup_dir, self.xorg_driver +
  182.                     '.oldconf'), 'w').write(
  183.                     open(OSLib.inst.xorg_conf_path).read())
  184.         else:
  185.             open(os.path.join(OSLib.inst.backup_dir, self.xorg_driver + '.noconf'), 'w')
  186.         
  187.         relevant_devices = []
  188.         
  189.         if len(self.xorg_conf.globaldict['Device']) == 0:
  190.             # Create a new Device section. "device" = position of the section
  191.             device = self.xorg_conf.makeSection('Device', identifier='Default Device')
  192.             relevant_devices.append(device)
  193.             # Set the driver
  194.             self.xorg_conf.setDriver('Device', self.xorg_driver, device)
  195.         else:
  196.             # Get the relevant sections by checking the ServerLayout section
  197.             # in case of multiple screens layouts or modify all the Device
  198.             # sections
  199.             devices = self.xorg_conf.getDevicesInUse()
  200.             if len(devices) > 0:
  201.                 relevant_devices = devices
  202.             else:
  203.                 relevant_devices = self.xorg_conf.globaldict['Device'].keys()
  204.             for device in relevant_devices:
  205.                 self.xorg_conf.setDriver('Device', self.xorg_driver, device)
  206.         logging.debug('XorgDriverHandler device sections (%s)' % (
  207.             str(self.xorg_conf.globaldict['Device'])))
  208.         
  209.         module_sections = self.xorg_conf.globaldict['Module']
  210.         have_modules = len(module_sections) > 0
  211.         
  212.         if have_modules:
  213.             for section in module_sections:
  214.                 for mod in self.remove_modules:
  215.                     self.xorg_conf.removeOption('Module', 'Load', value=mod, position=section)
  216.         
  217.         if self.add_modules:
  218.             if not have_modules:
  219.                 module_section = self.xorg_conf.makeSection('Module')
  220.             else:
  221.                 module_section = 0 #the 1st module section
  222.             
  223.             for mod in self.add_modules:
  224.                 if not self._mod_enabled(mod):
  225.                     self.xorg_conf.addOption('Module', 'Load', mod, optiontype=None, position=module_section, reference=True)
  226.         
  227.         if self.disable_modules:
  228.             for mod in self.disable_modules:
  229.                 if not self._mod_disabled(mod):
  230.                     self.xorg_conf.addOption('Module', 'Disable', mod, optiontype=None, position=module_section, reference=True)
  231.         
  232.         for device_section in relevant_devices:
  233.             for k, v in self.extra_conf_options.iteritems():
  234.                 self.xorg_conf.addOption('Device', k, v, optiontype='Option', position=device_section)
  235.         
  236.         self.enable_config_hook()
  237.         
  238.         self.xorg_conf.writeFile(OSLib.inst.xorg_conf_path)
  239.  
  240.         return False
  241.  
  242.     def disable(self):
  243.         if not self.xorg_conf:
  244.             logging.error('XorgDriverHandler.enable(): invalid xorg.conf, skipping')
  245.             return False
  246.  
  247.         KernelModuleHandler.disable(self)
  248.  
  249.         # do not mangle xorg.conf if package uninstallation has been aborted
  250.         if OSLib.inst.package_installed(self.package):
  251.             return
  252.  
  253.         noconf = os.path.join(OSLib.inst.backup_dir, self.xorg_driver + '.noconf')
  254.         oldconf = os.path.join(OSLib.inst.backup_dir, self.xorg_driver + '.oldconf')
  255.  
  256.         # if we previously didn't have an xorg.conf, delete it
  257.         if os.path.exists(noconf):
  258.             logging.debug('XorgDriverHandler.disable(%s): previously had no xorg.conf, deleting xorg.conf', self.xorg_driver)
  259.             os.unlink(noconf)
  260.             if os.path.exists(OSLib.inst.xorg_conf_path):
  261.                 os.unlink(OSLib.inst.xorg_conf_path)
  262.             self.xorg_conf = XKit.xutils.XUtils()
  263.         # if we have the previous xorg.conf, restore that
  264.         elif os.path.exists(oldconf):
  265.             logging.debug('XorgDriverHandler.disable(%s): restoring xorg.conf backup', self.xorg_driver)
  266.             open(OSLib.inst.xorg_conf_path, 'w').write(open(oldconf).read())
  267.             os.unlink(oldconf)
  268.             self.xorg_conf = XKit.xutils.XUtils(OSLib.inst.xorg_conf_path)
  269.         else: # no backup, so mangle current config manually
  270.             logging.debug('XorgDriverHandler.disable(%s): missing xorg.conf, reversing changes from enable()', self.xorg_driver)
  271.             relevant_devices = []
  272.             
  273.             if len(self.xorg_conf.globaldict['Device']) > 0:
  274.                 devices = self.xorg_conf.getDevicesInUse()
  275.                 if len(devices) > 0:
  276.                     relevant_devices = devices
  277.                 else:
  278.                     relevant_devices.append(0)
  279.                 
  280.                 module_sections = self.xorg_conf.globaldict['Module']
  281.         
  282.                 have_modules = len(module_sections) > 0
  283.                 
  284.                 if have_modules:
  285.                     for section in module_sections:
  286.                         for mod in self.add_modules:
  287.                             self.xorg_conf.removeOption('Module', 'Load', value=mod, position=section)
  288.                         
  289.                         for mod in self.disable_modules:
  290.                             self.xorg_conf.removeOption('Module', 'Disable', value=mod, position=section)
  291.                 
  292.                 if self.remove_modules:
  293.                     if not have_modules:
  294.                         module_section = self.xorg_conf.makeSection('Module')
  295.                     else:
  296.                         module_section = 0 #the 1st module section
  297.                     
  298.                     for mod in self.remove_modules:
  299.                         if not self._mod_enabled(mod):
  300.                             self.xorg_conf.addOption('Module', 'Load', mod,
  301.                                 optiontype=None, position=module_section,
  302.                                 reference=True)
  303.                     
  304.                 for device_section in relevant_devices:
  305.                     self.xorg_conf.setDriver('Device', self.alt_free_driver, device_section)
  306.                     
  307.                     for k, v in self.extra_conf_options.iteritems():
  308.                         self.xorg_conf.removeOption('Device', k, v, position=device_section)
  309.                 
  310.             self.disable_config_hook()
  311.  
  312.             logging.debug('XorgDriverHandler.disable(%s): writing restored xorg.conf', self.xorg_driver)
  313.             self.xorg_conf.writeFile(OSLib.inst.xorg_conf_path)
  314.  
  315.         return False
  316.  
  317.     def enable_config_hook(self):
  318.         '''Custom self.xorg_config changes after driver, modules, and extra
  319.         driver options have been changed.
  320.         '''
  321.         pass
  322.  
  323.     def disable_config_hook(self):
  324.         '''Custom self.xorg_config changes after driver, modules, and extra
  325.         driver options have been changed.
  326.         '''
  327.         pass
  328.  
  329.     def enables_composite(self):
  330.         '''Return whether this driver enables the composite extension.
  331.         
  332.         Note that this is true if and only if the current driver does *not*
  333.         support composite, but this driver does.'''
  334.  
  335.         return False
  336.  
  337.