summaryrefslogtreecommitdiffstats
path: root/displayconfig/displayconfigabstraction.py
diff options
context:
space:
mode:
Diffstat (limited to 'displayconfig/displayconfigabstraction.py')
-rw-r--r--displayconfig/displayconfigabstraction.py3230
1 files changed, 0 insertions, 3230 deletions
diff --git a/displayconfig/displayconfigabstraction.py b/displayconfig/displayconfigabstraction.py
deleted file mode 100644
index f59b2ff..0000000
--- a/displayconfig/displayconfigabstraction.py
+++ /dev/null
@@ -1,3230 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import sys
-import string
-import math
-import subprocess
-import xf86misc
-import xorgconfig
-import ScanPCI
-import csv
-import re
-from execwithcapture import *
-
-"""Classes for dealing with X.org configuration in a sane way.
-
-The object model used here is fairly simple. An XSetup object represents
-the complete configuration of the server. The XSetup object contains one or
-more GfxCard objects. One for each graphics card present in the machine.
-Each GfxCard has one or more Screen objects with each Screen representing
-one 'output' on the graphics card.
-
-Each GfxCard object is also associated with a GfxCardModel object which
-describes the model of graphics card.
-
-Each Screen object is associated with a MonitorModel object which
-describes the model of monitor attached.
-
-"""
-
-FALLBACK_RESOLUTION = (800,600)
-
-# FIXME updating /etc/modules for fglrx.
-data_file_dir = "."
-def SetDataFileDir(dir_name):
- global data_file_dir
- data_file_dir = dir_name
-
-var_data_dir = "/var/lib/guidance-backends"
-def SetVarDataDir(dir_name):
- global var_data_dir
- var_data_dir = dir_name
-
-############################################################################
-class XSetup(object):
- """Represents the current configuration of the X.org X11 server.
-
-
- """
- # Map positions
- ABOVE = 0
- UNDER = 1
- LEFTOF = 2
- RIGHTOF = 3
-
- RESTART_NONE = 0
- RESTART_X = 1
- RESTART_SYSTEM = 2
-
- LAYOUT_SINGLE = 1 # These are bit flags.
- LAYOUT_CLONE = 2
- LAYOUT_DUAL = 4
- LAYOUT_SINGLE_XINERAMA = 256 # For internal use.
- LAYOUT_CLONE_XINERAMA = 512 # For internal use.
-
- POSITION_LEFTOF = 0
- POSITION_RIGHTOF = 1
- POSITION_ABOVE = 2
- POSITION_BELOW = 3
-
- ROLE_UNUSED = 0
- ROLE_PRIMARY = 1
- ROLE_SECONDARY = 2
-
- def __init__(self,xorg_config_filename='/etc/X11/xorg.conf',debug_scan_pci_filename=None,secondtry=False):
- self.screens = []
- self.gfxcards = []
- self.xorg_config, self.hasxorg = xorgconfig.readConfig(xorg_config_filename, check_exists=True)
- if not secondtry:
- self.xorg_config_filename = xorg_config_filename
- if self.xorg_config_filename == None:
- self.xorg_config_filename = '/etc/X11/xorg.conf';
- self.x_live_info = xf86misc.XF86Server()
-
- self.primary_screen = None
- self.secondary_screen = None
-
- pci_bus = ScanPCI.PCIBus(data_file_dir)
- if debug_scan_pci_filename is None:
- pci_bus.detect()
- else:
- pci_bus.loadFromFile(debug_scan_pci_filename)
-
- # First thing. Scan the PCI bus and find out how many Gfx cards we have.
- found_list = self._detectGfxCards(pci_bus)
- # list of (PCI_ID, PCIDevice, GfxCard) tuples
-
- found_list.sort()
-
- # Prepare some useful data structures.
- self.layout = self.LAYOUT_SINGLE
- self.xinerama = False
- self.orientation = self.POSITION_LEFTOF
-
- # Maps screen section names to xorg screens section objects.
- xorg_screen_name_dict = {}
- xorg_unused_screen_sections = self.xorg_config.getSections("Screen")
- for screen in xorg_unused_screen_sections:
- xorg_screen_name_dict[screen.identifier] = screen
-
- # Maps device sections names to xorg device sections
- xorg_device_name_dict = {}
- xorg_unused_device_sections = self.xorg_config.getSections("Device")
- for device in xorg_unused_device_sections:
- xorg_device_name_dict[device.identifier] = device
-
- # Maps device sections names to xorg device sections
- xorg_monitor_name_dict = {}
- xorg_monitor_sections = self.xorg_config.getSections("Monitor")
- for monitor in xorg_monitor_sections:
- xorg_monitor_name_dict[monitor.identifier] = monitor
-
- # Maps GfxCard objects to ScanPCI.PCIDevice objects.
- gfx_card_pcidevice_dict = {}
-
- #-------------------------------------------------------------------
- # Decode the server layout.
- server_layouts = self.xorg_config.getSections("ServerLayout")
- if len(server_layouts)==0:
- print "*** Error: couldn't find any ServerLayout sections"
- return
- layout = server_layouts[0] # Grab the first ServerLayout
-
- if len(layout.screen)==0:
- print "*** Error: no screens were specified in the ServerLayout section"
-
- # Handle leftof rightof below and above.
- (primary_name, secondary_name, layout, self.orientation) = self._decodeServerLayoutScreens(layout.screen)
-
- screen_list = [primary_name]
- if secondary_name is not None:
- screen_list.append(secondary_name)
-
- for screen_name in screen_list:
- if screen_name in xorg_screen_name_dict:
- screen_section = xorg_screen_name_dict[screen_name]
- if screen_section.device in xorg_device_name_dict:
-
- device_section = xorg_device_name_dict[screen_section.device]
-
- # Ok, we've now got a screen section and its device.
- gfx_card = None
-
- if device_section.busid is not None:
- # Try to match this device to a gfxcard by using the PCI bus ID.
- bus_id = self._canonicalPCIBusID(device_section.busid)
-
- # See if there is already a known gfxcard at this PCI ID.
- gfx_card = self.getGfxCardByPCIBusID(bus_id)
- if gfx_card is not None:
- # Let the gfxcard know that we have another device section for it to manage.
- gfx_card._addXDevice(device_section)
- try:
- xorg_unused_device_sections.remove(device_section)
- except ValueError:
- pass
- else:
- # Not known, look for a matching pci device instead.
- for pci_device_tuple in found_list:
- if pci_device_tuple[0]==bus_id:
- # Got a hit, create a gfxcard object.
- gfx_card = GfxCard( self, pci_id=bus_id, \
- x_device=device_section, \
- detected_model=pci_device_tuple[2])
-
- self.gfxcards.append(gfx_card)
- gfx_card_pcidevice_dict[gfx_card] = pci_device_tuple[1]
- xorg_unused_device_sections.remove(device_section)
- found_list.remove(pci_device_tuple)
- break
-
- else:
-
- # OK, no PCI ID, try matching to a PCI device by X driver name,
- # or if there is one only gfx card then just grab it.
- driver_name = device_section.driver
- for pci_device_tuple in found_list:
- if pci_device_tuple[2].getDriver()==driver_name \
- or pci_device_tuple[2].getProprietaryDriver()==driver_name \
- or len(found_list)==1:
- # Got a hit, create a gfxcard object.
- gfx_card = GfxCard( self, pci_id=pci_device_tuple[0], \
- x_device=device_section, \
- detected_model=pci_device_tuple[2])
-
- self.gfxcards.append(gfx_card)
- gfx_card_pcidevice_dict[gfx_card] = pci_device_tuple[1]
- xorg_unused_device_sections.remove(device_section)
- found_list.remove(pci_device_tuple)
- break
-
- if gfx_card is not None:
- # Look up the monitor section from the monitor name.
- monitor_section = None
- monitor_model = None
- if screen_section.monitor in xorg_monitor_name_dict:
- monitor_section = xorg_monitor_name_dict[screen_section.monitor]
- monitor_model = self._matchMonitor(monitor_section)
-
- screen = Screen(x_config_screen=screen_section, gfx_card=gfx_card, \
- x_config_monitor=monitor_section, monitor_model=monitor_model, \
- x_config=self.xorg_config)
- gfx_card._addScreen(screen)
-
- if self.primary_screen is None:
- self.primary_screen = screen
- elif self.secondary_screen is None:
- self.secondary_screen = screen
-
- xorg_unused_screen_sections.remove(screen_section)
-
- if self.primary_screen is not None and self.secondary_screen is not None:
- self.layout = layout
-
- #-------------------------------------------------------------------
- # Dualhead hardware detection.
- gfx_cards_needing_second_heads = []
-
- # Detect dualhead ATI cards
- for pci_device in pci_bus.devices:
- if pci_device.text is not None and pci_device.text.find("Secondary")!=-1:
-
- pci_device_id = "PCI:%i:%i:%i" % (pci_device.pci_bus, pci_device.pci_device, pci_device.pci_function)
-
- for gfx_card in self.gfxcards:
- if gfx_card.getPCIBusID() != pci_device_id:
- # Compare the first two numbers that make up a PCI bus id (e.g. middle part of PCI:1:0:0)
- if gfx_card.getPCIBusID().split(":")[1:-1] == [str(pci_device.pci_bus),str(pci_device.pci_device)]:
- if len(gfx_card.getScreens())<2:
- gfx_cards_needing_second_heads.append(gfx_card)
- found_list = [x for x in found_list if x[0]!=pci_device_id]
- break
-
- # Detect dualhead Intel cards
- for gfx_card in self.gfxcards:
- if gfx_card._getDetectedGfxCardModel().getDriver() in ['i740','i810', 'intel']:
- gfx_card_pci_id = gfx_card.getPCIBusID().split(":")[1:]
- base_pci_id = gfx_card_pci_id[:-1]
-
- for pci_device in pci_bus.devices:
- if gfx_card_pci_id != [str(pci_device.pci_bus),str(pci_device.pci_device),str(pci_device.pci_function)]:
- if base_pci_id == [str(pci_device.pci_bus),str(pci_device.pci_device)]:
- pci_device_id = "PCI:%i:%i:%i" % (pci_device.pci_bus, pci_device.pci_device, pci_device.pci_function)
- found_list = [x for x in found_list if x[0]!=pci_device_id]
- # Try to configure a second head later if not yet available
- if len(gfx_card.getScreens()) < 2:
- gfx_cards_needing_second_heads.append(gfx_card)
- break
-
- # Detect dualhead nVidia cards
- for gfx_card in self.gfxcards:
- if gfx_card._getDetectedGfxCardModel().getDriver() in ['nv','nvidia']:
- if self._isNVidiaCardDualhead(gfx_card_pcidevice_dict[gfx_card]):
- if len(gfx_card.getScreens())<2:
- if gfx_card not in gfx_cards_needing_second_heads:
- gfx_cards_needing_second_heads.append(gfx_card)
- continue
-
- # Detect dualhead Matrox cards. This info is from the Cards+ db.
- for gfx_card in self.gfxcards:
- if (gfx_card._getDetectedGfxCardModel().getMultiHead()>1) and (len(gfx_card.getScreens())<2):
- if gfx_card not in gfx_cards_needing_second_heads:
- gfx_cards_needing_second_heads.append(gfx_card)
-
- # Detect laptops. Dualhead/clone mode is standard functionality on laptops.
- # (but can be hard to detect).
- if os.path.isfile('/usr/sbin/laptop-detect'):
- if subprocess.call(['/usr/sbin/laptop-detect'])==0:
- if len(self.gfxcards)!=0:
- gfx_card = self.gfxcards[0]
- if gfx_card not in gfx_cards_needing_second_heads and \
- len(gfx_card.getScreens())<2:
- gfx_cards_needing_second_heads.append(gfx_card)
-
- # Match up the second heads with any loose sections in xorg.conf.
- for gfx_card in gfx_cards_needing_second_heads:
- screens = gfx_card.getScreens()
- # Try to find a loose xorg.conf Screen section that also
- # references this gfx card. That is probably the config
- # for the second screen.
- for screen_section in xorg_unused_screen_sections:
- if screen_section.device in xorg_device_name_dict:
- device_section = xorg_device_name_dict[screen_section.device]
-
- # Is this the second screen for the same PCI device aka gfxcard?
-
- # Note: even though the second head shows up as a separate PCI ID, the screen
- # section in xorg.conf still uses the primary PCI ID.
- if str(device_section.screen)=="1" and \
- self._canonicalPCIBusID(device_section.busid)==gfx_card.getPCIBusID():
-
- # Look up the monitor section from the monitor name.
- monitor_section = None
- monitor_model = None
- if screen_section.monitor in xorg_monitor_name_dict:
- monitor_section = xorg_monitor_name_dict[screen_section.monitor]
- monitor_model = self._matchMonitor(monitor_section)
-
- gfx_card._addXDevice(device_section)
- xorg_unused_device_sections.remove(device_section)
-
- screen = Screen(x_config_screen=screen_section, gfx_card=gfx_card, \
- x_config_monitor=monitor_section, monitor_model=monitor_model, \
- x_config=self.xorg_config)
- gfx_card._addScreen(screen)
- self.secondary_screen = screen
- xorg_unused_screen_sections.remove(screen_section)
- break
- else:
- # Couldn't anything in xorg.conf, just make an empty screen
- screen = Screen(gfx_card=gfx_card, x_config=self.xorg_config)
- gfx_card._addScreen(screen)
-
- #-------------------------------------------------------------------
- # Handle loose gfx card devices. Check that all PCI gfxcards are accounted for.
- for pci_device_tuple in found_list:
-
- bus_id = pci_device_tuple[0]
- for device_section in xorg_unused_device_sections:
- if bus_id == self._canonicalPCIBusID(device_section.busid):
- xorg_unused_device_sections.remove(device_section)
- break
- else:
- device_section = None
-
- # Got a hit, create a gfxcard object.
- gfx_card = GfxCard( self, pci_id=pci_device_tuple[0], \
- x_device=device_section, \
- detected_model=pci_device_tuple[2])
-
- gfx_card_pcidevice_dict[gfx_card] = pci_device_tuple[1]
- self.gfxcards.append(gfx_card)
-
- screen = None
- # See if this device section is referenced by a screen section.
- # if so, then we grab the screen section.
- if device_section is not None:
- for screen_section in xorg_unused_screen_sections:
- if screen_section.device==device_section.identifier:
-
- # Ok, we have found the screen section, monitor?
- monitor_section = None
- monitor_model = None
- if screen_section.monitor in xorg_monitor_name_dict:
- monitor_section = xorg_monitor_name_dict[screen_section.monitor]
- monitor_model = self._matchMonitor(monitor_section)
-
- screen = Screen(x_config_screen=screen_section, gfx_card=gfx_card, \
- x_config_monitor=monitor_section, monitor_model=monitor_model, \
- x_config=self.xorg_config)
- gfx_card._addScreen(screen)
- xorg_unused_screen_sections.remove(screen_section)
- break
-
- if screen is None:
- # Manually add a screen.
- screen = Screen(gfx_card=gfx_card, x_config=self.xorg_config)
- gfx_card._addScreen(screen)
-
- #-------------------------------------------------------------------
- # Sort the gfx cards by PCI id.
- def gfxcard_pci_sort(a,b): return cmp(a.getPCIBusID(),b.getPCIBusID())
- self.gfxcards.sort(gfxcard_pci_sort)
-
- # Hand out some randr live screens
- x_live_screens = self.x_live_info.getScreens()
- i = 0
- for gfx_card in self.gfxcards:
- for screen in gfx_card.getScreens():
- if i<len(x_live_screens) and self.getScreenRole(screen)!=XSetup.ROLE_UNUSED:
- screen._setXLiveScreen(x_live_screens[i])
- i += 1
-
- # Ensure that all of the screen roles have been handed out.
- if self.primary_screen is None:
- for screen in self.getAllScreens():
- if screen is not self.secondary_screen:
- self.primary_screen = screen
- break
- if self.secondary_screen is None:
- for screen in self.getAllScreens():
- if screen is not self.primary_screen:
- self.secondary_screen = screen
- break
-
- self._finalizeInit()
-
- if not self.hasxorg and not secondtry:
- """No xorg.conf, so we need to write a temporary one and reload from that one"""
- self.writeXorgConfig('/tmp/xorg.conf.displayconfig')
- self.__init__(xorg_config_filename='/tmp/xorg.conf.displayconfig',secondtry=True)
- return
-
- def _finalizeInit(self):
- for gfxcard in self.gfxcards:
- gfxcard._finalizeInit()
-
- # Check the 'layout' on the gfx cards to detect optimised configs.
- gfxcard = self.primary_screen._getGfxCard()
- if gfxcard._getDetectedLayout()!=XSetup.LAYOUT_SINGLE:
- # Something interesting is going on on this gfx card. The
- # secondary screen is in this case going to actually be the
- # other 'head' on this gfx card.
- if gfxcard.getScreens()[0] is not self.primary_screen:
- self.secondary_screen = gfxcard.getScreens()[0]
- else:
- self.secondary_screen = gfxcard.getScreens()[1]
-
- self.orientation = gfxcard._getDetectedDualheadOrientation()
- self.setLayout(gfxcard._getDetectedLayout())
-
- self.setLayout(self.layout) # Propogate any XINERAMA_SINGLE stuff out to the gfxcards.
- self.original_layout = self.layout
- self.original_orientation = self.orientation
- self.original_primary_screen = self.primary_screen
- self.original_secondary_screen = self.secondary_screen
-
- def _matchMonitor(self,monitor_section):
- monitor_model_db = GetMonitorModelDB()
-
- model_name = monitor_section.modelname
- if monitor_model_db.getMonitorByName(model_name) is not None:
- monitor_model = monitor_model_db.getMonitorByName(model_name)
- else:
-
- if monitor_section.getRow('horizsync') is not None and monitor_section.getRow('vertrefresh') is not None:
- # Create a monitor object for the monitor in the xconfig.
- # It is probably a Plug N Play monitor and as such doesn't
- # appear in our monitor DB.
- monitor_model = monitor_model_db.newCustomMonitor(name=model_name)
- monitor_model.setType(MonitorModel.TYPE_PLUGNPLAY)
-
- if monitor_section.vendorname is not None:
- monitor_model.setManufacturer(monitor_section.vendorname)
-
- monitor_model.setHorizontalSync(' '.join(monitor_section.getRow('horizsync')))
- monitor_model.setVerticalSync(' '.join(monitor_section.getRow('vertrefresh')))
-
- else:
- # Try detecting the monitor.
- monitor_model = monitor_model_db.detect()
-
- monitor_model.setDpms("dpms" in monitor_section.option)
-
- return monitor_model
-
- def _decodeServerLayoutScreens(self,screens_lines):
- primary_name = None
- secondary_name = None
- layout = XSetup.LAYOUT_SINGLE
- position = XSetup.POSITION_LEFTOF
-
- for line in screens_lines:
- try:
- i = 1
- if line._row[i].isdigit(): # Skip any screen ID number.
- i += 1
-
- screen_name1 = line._row[i]
- if primary_name is None:
- primary_name = screen_name1
- elif secondary_name is None:
- secondary_name = screen_name1
- layout = XSetup.LAYOUT_CLONE
- i += 1
-
- if line._row[i].isdigit():
- # Skip absolute coords.
- i += 2
- else:
- if line._row[i].lower()=='absolute':
- # Skip the absolute keyword and coords
- i += 3
-
- screen_name2 = line._row[i+1]
- secondary_name = screen_name2
-
- position = {
- 'leftof': XSetup.POSITION_LEFTOF,
- 'rightof': XSetup.POSITION_RIGHTOF,
- 'above': XSetup.POSITION_ABOVE,
- 'below': XSetup.POSITION_BELOW
- }[line._row[i].lower()]
-
- layout = XSetup.LAYOUT_DUAL
-
- if screen_name1!=primary_name:
- # Swap the screens around. The primary wasn't given first on this
- # dualhead screen line.
- secondary_name = screen_name1
- position = {
- XSetup.POSITION_LEFTOF: XSetup.POSITION_RIGHTOF,
- XSetup.POSITION_RIGHTOF: XSetup.POSITION_LEFTOF,
- XSetup.POSITION_ABOVE: XSetup.POSITION_BELOW,
- XSetup.POSITION_BELOW: XSetup.POSITION_ABOVE
- }[position]
-
- except IndexError:
- pass
- except KeyError:
- pass
-
- return (primary_name, secondary_name, layout, position)
-
- def _detectGfxCards(self,pci_bus):
- """Scans the PCI bus for graphics cards.
-
- Returns a list of (PCI_ID, PCIDevice, GfxCard) tuples."""
- self.gfx_card_db = GetGfxCardModelDB()
- vesa_model = "VESA driver (generic)"
-
- # Look for a gfxcard.
- found_list = []
- for pci_device in pci_bus.devices:
- if pci_device.isGfxCard():
- pci_id = "PCI:%i:%i:%i" % (pci_device.pci_bus, pci_device.pci_device, pci_device.pci_function)
- model = None
- try:
- cardname = pci_device.getModule()
- if not pci_device.isModuleXorgDriver():
- cardname = vesa_model
- model = self.gfx_card_db.getGfxCardModelByName(cardname)
- except KeyError:
- model = self.gfx_card_db.getGfxCardModelByName(vesa_model)
- found_list.append( (pci_id,pci_device,model) )
-
- return found_list
-
- def _canonicalPCIBusID(self,bus_id):
- try:
- parts = bus_id.split(":")
- if parts[0].lower()!="pci":
- return None
- bus = int(parts[1])
- device = int(parts[2])
- function = int(parts[3])
- return "PCI:%i:%i:%i" % (bus,device,function)
- except IndexError:
- return None
- except ValueError:
- return None
- except AttributeError:
- return None
-
- def _isNVidiaCardDualhead(self,PCIDeviceObject):
- """
- PCIDevice - ScanPCI.PCIDevice
-
- Returns true if the given nVidia PCI device ID supports dualhead.
- """
- # From Xorg source xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c
- # See line "pNv->twoHeads = "
- #
- NV_ARCH_04 = 0x4
- NV_ARCH_10 = 0x10
- NV_ARCH_20 = 0x20
- NV_ARCH_30 = 0x30
- NV_ARCH_40 = 0x40
-
- pci_device = PCIDeviceObject.device
-
- if pci_device & 0xfff0 == 0x00f0:
- return True # FIXME PCIXpress chipsets
-
- # These IDs come from the Xorg source.
- # xc/programs/Xserver/hw/xfree86/drivers/nv/nv_driver.c
- # And should be periodically updated.
- chipset = pci_device & 0x0ff0
- if chipset in [
- 0x0100, # GeForce 256
- 0x0110, # GeForce2 MX
- 0x0150, # GeForce2
- 0x0170, # GeForce4 MX
- 0x0180, # GeForce4 MX (8x AGP)
- 0x01A0, # nForce
- 0x01F0]:# nForce2
- architecture = NV_ARCH_10
- elif chipset in [
- 0x0200, # GeForce3
- 0x0250, # GeForce4 Ti
- 0x0280]:# GeForce4 Ti (8x AGP)
- architecture = NV_ARCH_20
- elif chipset in [
- 0x0300, # GeForceFX 5800
- 0x0310, # GeForceFX 5600
- 0x0320, # GeForceFX 5200
- 0x0330, # GeForceFX 5900
- 0x0340]:# GeForceFX 5700
- architecture = NV_ARCH_30
- elif chipset in [
- 0x0040,
- 0x00C0,
- 0x0120,
- 0x0130,
- 0x0140,
- 0x0160,
- 0x01D0,
- 0x0090,
- 0x0210,
- 0x0220,
- 0x0230,
- 0x0290,
- 0x0390]:
- architecture = NV_ARCH_40
- else:
- architecture = NV_ARCH_04
-
- return (architecture >= NV_ARCH_10) and \
- (chipset != 0x0100) and \
- (chipset != 0x0150) and \
- (chipset != 0x01A0) and \
- (chipset != 0x0200)
-
- def _syncXorgConfig(self):
-
- xinerama_clone = (self.layout==XSetup.LAYOUT_CLONE) and \
- not ((self.secondary_screen._getGfxCard() is self.primary_screen._getGfxCard()) \
- and (self.primary_screen._getGfxCard()._getAvailableLayouts() & XSetup.LAYOUT_CLONE))
-
- if xinerama_clone:
- # For clone mode with xinerama we copy the screen settings from the primary screen
- # to the secondary screen.
- primary_screen = self.getPrimaryScreen()
- secondary_screen = self.getSecondaryScreen()
-
- resolution = primary_screen.getAvailableResolutions()[primary_screen.getResolutionIndex()]
- secondary_resolution_index = secondary_screen.getAvailableResolutions().index(resolution)
- secondary_screen.setResolutionIndex(secondary_resolution_index)
- secondary_rates = secondary_screen.getAvailableRefreshRatesForResolution(secondary_resolution_index)
- primary_rate = primary_screen.getAvailableRefreshRates()[primary_screen.getRefreshRateIndex()]
-
- best_rate_index = 0
- best_score = 1000000
- for i in range(len(secondary_rates)):
- rate = secondary_rates[i]
- score = abs(rate-primary_rate)
- if score < best_score:
- best_score = score
- best_rate_index = i
-
- secondary_screen.setRefreshRateIndex(best_rate_index)
-
- # Sync up the graphics cards.
- for gfxcard in self.gfxcards:
- gfxcard._syncXorgConfig()
-
- server_flags_sections = self.xorg_config.getSections("ServerFlags")
- if len(server_flags_sections)!=0:
- server_flags = server_flags_sections[0]
- server_flags.option.removeOptionByName("Xinerama")
- else:
- server_flags = self.xorg_config.makeSection(None,["Section","ServerFlags"])
- self.xorg_config.append(server_flags)
-
- # Delete any old screen entries in the serverlayout section.
- server_layout = self.xorg_config.getSections("ServerLayout")[0]
- for screen in server_layout.screen[:]:
- server_layout.screen.remove(screen)
-
- # Add the first Screen row
- screen_id_1 = self.primary_screen._getXorgScreenSection().identifier
- server_layout.screen.append(server_layout.screen.makeLine(None,
- ["0",screen_id_1,"0","0"]))
-
- # FIXME server_flags -> Option "DefaultServerLayout" "???"
- if self.layout==XSetup.LAYOUT_DUAL or xinerama_clone:
- server_flags.option.append( server_flags.option.makeLine(None,["Xinerama","true"]) )
-
- # Add the second screen row. This one also has the dual screen
- # orientation info.
- screen_id_2 = self.secondary_screen._getXorgScreenSection().identifier
-
- if not xinerama_clone:
-
- position = {XSetup.POSITION_LEFTOF:"RightOf",
- XSetup.POSITION_RIGHTOF:"LeftOf",
- XSetup.POSITION_ABOVE:"Below",
- XSetup.POSITION_BELOW:"Above"}[self.orientation]
-
- server_layout.screen.append(server_layout.screen.makeLine(None,
- ["1",screen_id_2,position,screen_id_1]))
- else:
- # Xinerama clone mode. Place the second screen directly on top of the
- # primary screen.
- server_layout.screen.append(server_layout.screen.makeLine(None,
- ["1",screen_id_2,"0","0"]))
-
- self.original_layout = self.layout
- self.original_orientation = self.orientation
- self.original_primary_screen = self.primary_screen
- self.original_secondary_screen = self.secondary_screen
-
- def writeXorgConfig(self,filename):
- self._syncXorgConfig()
- self.xorg_config.writeConfig(filename)
-
- def xorgConfigToString(self):
- return self.xorg_config.toString()
-
- def getUsedScreens(self):
- """Returns the list of Screen objects that the current setup is using."""
- if self.layout==XSetup.LAYOUT_SINGLE:
- return [self.primary_screen]
- else:
- return [self.primary_screen, self.secondary_screen]
-
- def getAllScreens(self):
- """Returns a list of all Screen object."""
- screens = []
- for card in self.gfxcards:
- for screen in card.getScreens():
- screens.append(screen)
- return screens
-
- def getScreen(self,screenindex):
- return self.getUsedScreens()[screenindex]
-
- def getGfxCards(self):
- return self.gfxcards[:] # No messin' with the gfx card list.
-
- def getGfxCardByPCIBusID(self,bus_id):
- for gfxcard in self.gfxcards:
- if gfxcard.getPCIBusID()==bus_id:
- return gfxcard
- return None
-
- def getPrimaryScreen(self):
- return self.primary_screen
-
- def getSecondaryScreen(self):
- return self.secondary_screen
-
- def getScreenRole(self,screen):
- if screen is self.primary_screen:
- return XSetup.ROLE_PRIMARY
- if screen is self.secondary_screen:
- return XSetup.ROLE_SECONDARY
- return XSetup.ROLE_UNUSED
-
- def setScreenRole(self,screen,role):
- if role==XSetup.ROLE_PRIMARY:
- if screen is self.secondary_screen:
- # Swap the roles around.
- self.secondary_screen = self.primary_screen
- self.primary_screen = screen
- else:
- self.primary_screen = screen
-
- elif role==XSetup.ROLE_SECONDARY:
- if screen is self.primary_screen:
- # Swap the roles around.
- self.primary_screen = self.secondary_screen
- self.secondary_screen = screen
- else:
- self.secondary_screen = screen
- else:
- # ROLE_UNUSED
- if screen is not self.primary_screen and screen is not self.secondary_screen:
- return
-
- # Find the first screen unused.
- for unused_screen in self.getAllScreens():
- if screen is not self.primary_screen and screen is not self.secondary_screen:
- if screen is self.primary_screen:
- self.primary_screen = unused_screen
- else:
- self.secondary_screen = unused_screen
- return
-
- def mayModifyXorgConfig(self):
- """Check if the current user may modify the xorg.conf file
-
- Returns True or False
- """
- return os.access(self.xorg_config_filename, os.W_OK|os.R_OK)
-
- def mayModifyGamma(self):
- """Check if the current user may modify the gamma settings.
-
- Returns True or False.
- """
- return self.isGammaLive() or self.mayModifyXorgConfig()
-
- def mayModifyResolution(self):
- """Check if the current user may modify the screen resolution.
-
- Returns True or False.
- """
- for screen in self.x_live_info.getScreens():
- if screen.resolutionSupportAvailable():
- return True
-
- return self.mayModifyXorgConfig()
-
- def isGammaLive(self):
- """Check if gamma changes are done immediately.
-
- Returns True or False.
- """
- return True # FIXME depends on the xvid extension and if86misc.
-
- def isLiveResolutionConfigChanged(self):
- """Check if the live server configuration is changed
-
- Checks if the configuration has been modified with changes that can be
- pushed to the running X server.
-
- Returns True or False.
- """
- # XRandR tends to break Xinerama
- if self.primary_screen._getGfxCard().getLayout() in \
- (XSetup.LAYOUT_SINGLE_XINERAMA, XSetup.LAYOUT_DUAL):
- return False
- for screen in self.getAllScreens():
- if screen.isLive() and screen.isResolutionSettingsChanged():
- return True
-
- return False
-
- def applyLiveResolutionChanges(self):
- """Apply any changes that can be done live
-
- Returns True if running server resolution has been changed.
- """
- rc = False
- for s in self.getUsedScreens():
- if s.isResolutionSettingsChanged():
- s.applyResolutionSettings()
- rc = rc or s.isResolutionLive()
- return rc
-
- def acceptLiveResolutionChanges(self):
- """
-
-
- """
- for s in self.getUsedScreens():
- s.acceptResolutionSettings()
-
- def rejectLiveResolutionChanges(self):
- """Rejects and reverts the last live server resolution changes
-
- Rejects the last resolution changes that were made to the live server
- and reverts it back to the previous configuration.
- """
- for s in self.getUsedScreens():
- s.revertResolutionSettings()
-
- def isLiveGammaConfigChanged(self):
- """Check if the live server gamma configuration is changed
-
- Checks if the configuration has been modified with changes that can be
- pushed to the running X server.
-
- Returns True or False.
- """
- for screen in self.getAllScreens():
- if screen.isLive() and screen.isGammaSettingsChanged():
- return True
-
- return False
-
- def applyLiveGammaChanges(self):
- """Apply any changes that can be done live
-
- Returns True if running server gamma has been changed.
- """
- rc = False
- for s in self.getUsedScreens():
- if s.isGammaSettingsChanged():
- s.applyGammaSettings()
- rc = rc or s.isGammaLive()
- return rc
-
- def acceptLiveGammaChanges(self):
- """
-
-
- """
- for s in self.getUsedScreens():
- s.acceptGammaSettings()
-
- def rejectLiveGammaChanges(self):
- """Rejects and reverts the last live server gamma changes
-
- Rejects the last gamma changes that were made to the live server
- and reverts it back to the previous configuration.
- """
- for s in self.getUsedScreens():
- s.revertGammaSettings()
-
- def isXorgConfigChanged(self):
- """Check if the xorg.config needs to updated
-
- Returns True if the xorg.config file needs to updated to reflect new changes.
- """
- changed = self.original_layout!=self.layout or \
- self.original_orientation!=self.orientation or \
- self.original_primary_screen!=self.primary_screen or \
- self.original_secondary_screen!=self.secondary_screen
-
- for gfxcard in self.gfxcards:
- changed = changed or gfxcard.isXorgConfigChanged()
- for screen in self.getAllScreens():
- changed = changed or screen.isXorgConfigChanged()
- return changed
-
- def getRestartHint(self):
- hint = XSetup.RESTART_NONE
- if self.original_layout!= self.layout or self.original_orientation != self.orientation:
- hint = XSetup.RESTART_X
- return max(hint,max( [gfxcard.getRestartHint() for gfxcard in self.gfxcards] ))
-
- def reset(self):
- for card in self.gfxcards:
- card.reset()
-
- self.layout = self.original_layout
- self.orientation = self.original_orientation
- self.primary_screen = self.original_primary_screen
- self.secondary_screen = self.original_secondary_screen
-
- # Dualhead and secondary monitor support ----------
- def getLayout(self):
- return self.layout
-
- def setLayout(self,layout):
- """
-
- Keyword arguments:
- layout - XSetup.LAYOUT_SINGLE, XSetup.LAYOUT_CLONE or XSetup.LAYOUT_DUAL.
- """
- self.layout = layout
-
- if self.layout==XSetup.LAYOUT_SINGLE:
- for gfxcard in self.gfxcards:
- gfxcard.setLayout(XSetup.LAYOUT_SINGLE)
- self.xinerama = False
- elif self.layout==XSetup.LAYOUT_DUAL:
- # 'xinerama' screens can be combined by the ServerLayout xorg.conf
- # sections into a multihead configurations. Gfxcard objects just
- # have to output xinerama friendly xorg.conf device and screen
- # sections.
- self.xinerama = True
- for gfxcard in self.gfxcards:
- gfxcard.setLayout(XSetup.LAYOUT_SINGLE_XINERAMA)
-
- # Check if the primary and secondary screen are on the same gfx card.
- # If so then see if the gfxcard can directly (read: accelarated) support
- # the layout we want.
- if self.primary_screen._getGfxCard() is self.secondary_screen._getGfxCard():
- if self.primary_screen._getGfxCard().getAvailableLayouts() & self.layout:
- self.primary_screen._getGfxCard().setLayout(self.layout)
- self.xinerama = False
-
- elif self.layout==XSetup.LAYOUT_CLONE:
-
- # If the graphics card itself has both heads and it can offer a better clone
- # mode, then we use that instead of faking it with xinerama.
- if (self.secondary_screen._getGfxCard() is self.primary_screen._getGfxCard()) \
- and (self.primary_screen._getGfxCard()._getAvailableLayouts() & XSetup.LAYOUT_CLONE):
- self.xinerama = False
- for gfxcard in self.gfxcards:
- gfxcard.setLayout(XSetup.LAYOUT_CLONE)
- else:
- self.xinerama = True
- for gfxcard in self.gfxcards:
- gfxcard.setLayout(XSetup.LAYOUT_SINGLE_XINERAMA)
-
- def mayModifyLayout(self):
- return self.mayModifyXorgConfig()
-
- def getAvailableLayouts(self):
- if self.secondary_screen is not None:
- return XSetup.LAYOUT_SINGLE | XSetup.LAYOUT_DUAL | XSetup.LAYOUT_CLONE
- else:
- return XSetup.LAYOUT_SINGLE
-
- def setDualheadOrientation(self,orientation):
- """ Sets orientation of monitor to one of
- XSetup.ABOVE, XSetup.UNDER, XSetup.LEFTOF, XSetup.RIGHTOF
- """
- self.orientation = orientation
-
- def getDualheadOrientation(self):
- """ Returns the current orientation, one of
- XSetup.ABOVE, XSetup.UNDER, XSetup.LEFTOF, XSetup.RIGHTOF
- """
- return self.orientation
-
- def isHWAccelerated(self):
- # FIXME:
- # if twinview-alike and screen[0].res = screen[1].res
- # else: if primary screen
- return True
-
- # Internal ----------
- def _addScreen(self,screen):
- self.screens.append(screen)
-
- def _addGfxCard(self,gfxcard):
- self.gfxcards.append(gfxcard)
-
- def _getColorDepth(self):
- return min([s._getColorDepth() for s in self.getUsedScreens()])
-
- def __str__(self):
- string = "XSetup:\n"
- string += " Layout: %s\n" % ({self.LAYOUT_SINGLE: "Single",
- self.LAYOUT_CLONE: "Clone",
- self.LAYOUT_DUAL: "Dual"
- }[self.getLayout()])
-
- i = 1
- for gfxcard in self.gfxcards:
- string += " Gfxcard %i: %s\n" % (i,str(gfxcard))
- i += 1
- return string
-
-############################################################################
-class GfxCard(object):
- """Represents a graphics card that is present in this computer."""
-
- def __init__(self, setup, pci_id=None, x_device=None, detected_model=None, proprietary_driver=False):
- self.setup = setup
- self.x_config = self.setup.xorg_config
- self.layout = XSetup.LAYOUT_SINGLE
- self.pci_id = pci_id
- self.screens = []
-
- self.detected_model = detected_model
- self.proprietary_driver = proprietary_driver
-
- self.video_ram = 1024
-
- # The (optimised) layout that was detected in xorg.conf on device level.
- self.detected_layout = XSetup.LAYOUT_SINGLE
- self.detected_orientation = XSetup.POSITION_LEFTOF
-
- self.x_device = [] # This can be a list of xorg device sections
- if x_device is not None:
- self.x_device.append(x_device)
-
- def _addScreen(self,screen):
- self.screens.append(screen)
-
- def _addXDevice(self,x_device):
- self.x_device.append(x_device)
-
- def _finalizeInit(self):
- # Finish initalisation.
-
- if len(self.x_device)!=0:
-
- # Try to find a gfx card model.
- self.gfxcard_model = None
- if self.x_device[0].boardname is not None:
- # Look up the model by boardname.
- try:
- self.gfxcard_model = GetGfxCardModelDB().getGfxCardModelByName(self.x_device[0].boardname)
- except KeyError:
- pass
-
- if self.gfxcard_model is None:
- # OK, try looking it up by driver.
- try:
- self.gfxcard_model = GetGfxCardModelDB().getGfxCardModelByDriverName(self.x_device[0].driver)
- except KeyError:
- self.gfxcard_model = self.detected_model
-
- # Write the current driver in the model
- if self.x_device[0].driver:
- self.gfxcard_model.setDriver(self.x_device[0].driver)
-
- self.proprietary_driver = self.gfxcard_model.getProprietaryDriver()==self.x_device[0].driver
-
- if self.x_device[0].videoram is not None:
- self.video_ram = int(self.x_device[0].videoram)
-
- # Detect layout
- if len(self.screens)>=2:
- # Xorg ATI driver.
- if self._getCurrentDriver() in ['ati','r128','radeon']:
- merged = self.x_device[0].option.getOptionByName('mergedfb')
- if merged is not None and xorgconfig.toBoolean(merged._row[2]):
- self.detected_layout = XSetup.LAYOUT_CLONE
- # ATI proprietary driver
- elif self._getCurrentDriver()=='fglrx':
- desktopsetup = self.x_device[0].option.getOptionByName('desktopsetup')
- if desktopsetup is not None and desktopsetup._row[2]=='c':
- self.detected_layout = XSetup.LAYOUT_CLONE
- # nVidia proprietary driver
- elif self._getCurrentDriver()=='nvidia':
- twinview = self.x_device[0].option.getOptionByName('twinview')
- if twinview is not None:
- desktopsetup = self.x_device[0].option.getOptionByName('twinvieworientation')
- if desktopsetup is not None and desktopsetup._row[2].lower()=='clone':
- self.detected_layout = XSetup.LAYOUT_CLONE
- # i810 driver
- elif self._getCurrentDriver() in ['i810', 'intel']:
- clone = self.x_device[0].option.getOptionByName('clone')
- if clone is not None:
- if xorgconfig.toBoolean(clone._row[2]):
- self.detected_layout = XSetup.LAYOUT_CLONE
-
- else:
- self.gfxcard_model = self.detected_model
-
- self.original_gfxcard_model = self.gfxcard_model
- self.original_proprietary_driver = self.proprietary_driver
- self.original_layout = self.layout
-
- # Give the screens a chance to finish initialisation.
- for screen in self.screens:
- screen._finalizeInit()
- for screen in self.screens:
- screen._resyncResolution()
-
- def _getDetectedLayout(self):
- return self.detected_layout
-
- def _getDetectedDualheadOrientation(self):
- return self.detected_orientation
-
- def _getDetectedGfxCardModel(self):
- return self.detected_model
-
- def getScreens(self):
- return self.screens[:]
-
- def getGfxCardModel(self):
- return self.gfxcard_model
-
- def setGfxCardModel(self,gfx_card_model):
- self.gfxcard_model = gfx_card_model
-
- for screen in self.screens:
- screen._resyncResolution()
-
- def getXorgDeviceSection(self,index):
- return self.x_device[index]
-
- def isProprietaryDriver(self):
- return self.proprietary_driver
-
- def setProprietaryDriver(self,proprietary_driver):
- self.proprietary_driver = proprietary_driver
-
- def getDetectedGfxCardModel(self):
- return self.detected_model
-
- def getPCIBusID(self):
- return self.pci_id
-
- def isXorgConfigChanged(self):
- return self.original_gfxcard_model is not self.gfxcard_model or \
- self.original_proprietary_driver != self.proprietary_driver or \
- self.original_layout != self.layout
-
- def reset(self):
- for screen in self.screens:
- screen.reset()
-
- self.gfxcard_model = self.original_gfxcard_model
- self.proprietary_driver = self.original_proprietary_driver
-
- def isAGP(self):
- return self.pci_id=='PCI:1:0:0' # FIXME this might not be accurate.
-
- def getLayout(self):
- return self.layout
-
- def setLayout(self,layout):
- self.layout = layout
- for screen in self.screens:
- screen._resyncResolution()
-
- def getAvailableLayouts(self):
- layouts = XSetup.LAYOUT_SINGLE
- if len(self.screens)==2:
- if self._getCurrentDriver() in ['fglrx', 'nvidia', 'i810']:
- layouts |= XSetup.LAYOUT_CLONE | XSetup.LAYOUT_DUAL
- return layouts
-
- def getVideoRam(self):
- """
- Get the amount of video ram that this card has.
-
- The values returned have the following meanings:
- 256 => 256 kB
- 512 => 512 kB
- 1024 => 1 MB
- 2048 => 2 MB
- 4096 => 4 MB
- 8192 => 8 MB
- 16384 => 16 MB
- 32768 => 32 MB
- 65536 => 64 MB or more
-
- The video ram setting is only used if the selected graphics card model requires
- that the amount of video ram be explicitly specified. That is to say that
- gfxcard.getGfxCardModel().getNeedVideoRam() returns true.
-
- Returns an integer from the list above.
- """
- return self.video_ram
-
- def setVideoRam(self,ram):
- self.video_ram = ram
-
- for screen in self.screens:
- screen._resyncResolution()
-
- def _getCurrentDriver(self):
- if self.proprietary_driver:
- return self.gfxcard_model.getProprietaryDriver()
- else:
- return self.gfxcard_model.getDriver()
-
- def getRestartHint(self):
- # The ATI propreitary drivers need a special AGP kernel module to be loaded.
- # The best, and often only way to get this module loaded is to reboot.
- # The same applies for removing the module.
- hint = XSetup.RESTART_NONE
-
- if self.original_proprietary_driver:
- original_gfx_driver = self.original_gfxcard_model.getProprietaryDriver()
- else:
- original_gfx_driver = self.original_gfxcard_model.getDriver()
-
- current_gfx_driver = self._getCurrentDriver()
-
- if current_gfx_driver!=original_gfx_driver:
- # Restart X if the driver is different.
- hint = XSetup.RESTART_X
-
- # Layout changes also require an X server restart.
- if self.original_layout!=self.layout:
- hint = XSetup.RESTART_X
-
- if original_gfx_driver=='fglrx' and current_gfx_driver in ['ati','r128','radeon']:
- hint = XSetup.RESTART_SYSTEM
-
- # If a different kernel module is needed, then restart the system.
- kernel_module_list = self._getLoadedKernelModules()
- if self._needATIFglrx() and 'fglrx' not in kernel_module_list:
- hint = XSetup.RESTART_SYSTEM
- else:
- if 'fglrx' in kernel_module_list:
- hint = XSetup.RESTART_SYSTEM
-
- hintlist = [hint]
- hintlist.extend([screen.getRestartHint() for screen in self.screens])
- return max(hintlist)
-
- def _needATIFglrx(self):
- """Work out if the current configuration require the ATI fglrx kernel module."""
- return self.isAGP() and self.getGfxCardModel() is not None and \
- self.getGfxCardModel().getProprietaryDriver()=='fglrx' and self.isProprietaryDriver()
-
- def _getLoadedKernelModules(self):
- return [line.split()[0] for line in open('/proc/modules')]
-
- def _getAvailableLayouts(self):
- if len(self.screens)>=2:
- drv = self._getCurrentDriver()
- layouts = XSetup.LAYOUT_SINGLE | XSetup.LAYOUT_DUAL
- if drv in ['fglrx', 'nvidia', 'i810']:
- layouts |= XSetup.LAYOUT_CLONE
- elif drv in ['ati', 'radeon', 'r128', 'intel']:
- layouts = XSetup.LAYOUT_SINGLE
- return layouts
- else:
- return XSetup.LAYOUT_SINGLE
-
- def __str__(self):
- screen_string = ",".join([str(s) for s in self.screens])
- driver = self._getCurrentDriver()
- return "GfxCard: {model:"+str(self.gfxcard_model)+", driver:"+driver+", screens:"+screen_string+"}"
-
- def _syncXorgConfig(self):
- if self.proprietary_driver and self.gfxcard_model.getProprietaryDriver() is not None:
- driver = self.gfxcard_model.getProprietaryDriver()
- else:
- driver = self.gfxcard_model.getDriver()
-
- # FIXME maybe this module stuff should migrate into XSetup.
-
- # --- Fix the module section ---
-
- # $raw_X->set_devices($card, @{$card->{cards} || []});
- # $raw_X->get_ServerLayout->{Xinerama} = { commented => !$card->{Xinerama}, Option => 1 }
- #if defined $card->{Xinerama};
- module_sections = self.x_config.getSections("Module")
- if len(module_sections) > 0:
- module = module_sections[0]
- else:
- module = self.x_config.makeSection(None, ["Section", "Module"])
- self.x_config.append(module)
-
- module.removeModule('GLcore')
- module.removeModule('glx')
- module.removeModule('dbe')
-
- # Mandriva
- #module.removeModule("/usr/X11R6/lib/modules/extensions/libglx.so")
-
- if driver=='nvidia':
- module.addModule("glx")
-
- # Mandriva
- # This loads the NVIDIA GLX extension module.
- # IT IS IMPORTANT TO KEEP NAME AS FULL PATH TO libglx.so ELSE
- # IT WILL LOAD XFree86 glx module and the server will crash.
-
- # module.addModule("/usr/X11R6/lib/modules/extensions/libglx.so")
- # FIXME lib64
- elif self.gfxcard_model.getProprietaryDriver()!='fglrx':
- module.addModule('glx')
- module.addModule('GLcore')
-
- #module.removeModule("/usr/X11R6/lib/modules/extensions/libglx.a")
- if driver=='fglrx':
- module.addModule("glx")
- module.addModule("dbe")
- #elif driver!='nvidia':
- # module.addModule("/usr/X11R6/lib/modules/extensions/libglx.a")
-
- # DRI
- module.removeModule('dri')
- if self.gfxcard_model.getDriGlx():
- module.addModule('dri')
-
- module.removeModule('v4l')
- if not (self.gfxcard_model.getDriGlx() and self.gfxcard_model.getDriver()=='r128'):
- module.addModule('v4l')
-
- # --- Fix all of the Device sections ---
- for i in range(len(self.screens)):
-
- if i==len(self.x_device):
- new_device = self.x_config.makeSection('',['section','device'])
- self.x_config.append(new_device)
- self.x_device.append(new_device)
- new_device.identifier = self.x_config.createUniqueIdentifier("device")
-
- identifier = self.x_device[i].identifier
- busid = self.x_device[i].busid
-
- self.x_device[i].clear()
-
- # Create a new Device section in the Xorg config file.
- self.x_device[i].identifier = identifier
- self.x_device[i].boardname = self.gfxcard_model.getName()
- self.x_device[i].busid = self.pci_id
- self.x_device[i].driver = driver
- self.x_device[i].screen = str(i)
-
- if self.gfxcard_model.getVendor() is not None:
- self.x_device[i].vendorname = self.gfxcard_model.getVendor()
-
- if self.gfxcard_model.getNeedVideoRam():
- self.x_device[i].videoram = self.video_ram
-
- # Setup Clone mode for second heads.
- if driver in ["ati","r128","radeon"]: # Xorg ATI driver
- merged_value = {
- XSetup.LAYOUT_CLONE: "on",
- XSetup.LAYOUT_SINGLE: "off",
- XSetup.LAYOUT_DUAL: "on",
- XSetup.LAYOUT_SINGLE_XINERAMA: "off"
- }[self.layout]
-
- merged_option = self.x_device[i].option.makeLine(None,["MergedFB",merged_value])
- self.x_device[i].option.append(merged_option)
-
- if self.layout==XSetup.LAYOUT_CLONE:
- monitor_model = self.setup.getSecondaryScreen().getMonitorModel()
- if monitor_model is not None:
- if monitor_model.getHorizontalSync() is not None:
- hsyncline = self.x_device[i].option.makeLine(None,['CRT2HSync',monitor_model.getHorizontalSync()])
- self.x_device[i].option.append(hsyncline)
-
- if monitor_model.getVerticalSync() is not None:
- vsyncline = self.x_device[i].option.makeLine(None,['CRT2VRefresh',monitor_model.getVerticalSync()])
- self.x_device[i].option.append(vsyncline)
-
- # FIXME option "CloneMode" "off"
-
- if driver=='fglrx': # ATI proprietary driver.
- if self.layout==XSetup.LAYOUT_CLONE:
- new_option = self.x_device[i].option.makeLine(None,["DesktopSetup","c"])
- self.x_device[i].option.append(new_option)
-
- # FIXME this probably won't work on laptops and DVI. The user will probably
- # have to manually select the monitor types.
-
- # We do this to make sure that the driver starts up in clone mode even
- # if it can't detect the second monitor.
- new_option = self.x_device[i].option.makeLine(None,["ForceMonitors","crt1,crt2"])
- self.x_device[i].option.append(new_option)
-
- monitor_model = self.setup.getSecondaryScreen().getMonitorModel()
- if monitor_model is not None:
- if monitor_model.getHorizontalSync() is not None:
- hsyncline = self.x_device[i].option.makeLine(None,['HSync2',monitor_model.getHorizontalSync()])
- self.x_device[i].option.append(hsyncline)
-
- if monitor_model.getVerticalSync() is not None:
- vsyncline = self.x_device[i].option.makeLine(None,['VRefresh2',monitor_model.getVerticalSync()])
- self.x_device[i].option.append(vsyncline)
-
- if driver=='nvidia': # nVidia proprietary driver.
- if self.layout==XSetup.LAYOUT_CLONE:
- new_option = self.x_device[i].option.makeLine(None,["TwinView","on"])
- self.x_device[i].option.append(new_option)
- new_option = self.x_device[i].option.makeLine(None,["TwinViewOrientation","clone"])
- self.x_device[i].option.append(new_option)
-
- monitor_model = self.setup.getSecondaryScreen().getMonitorModel()
- if monitor_model is not None:
- if monitor_model.getHorizontalSync() is not None:
- hsyncline = self.x_device[i].option.makeLine(None,['SecondMonitorHorizSync',monitor_model.getHorizontalSync()])
- self.x_device[i].option.append(hsyncline)
-
- if monitor_model.getVerticalSync() is not None:
- vsyncline = self.x_device[i].option.makeLine(None,['SecondMonitorVertRefresh',monitor_model.getVerticalSync()])
- self.x_device[i].option.append(vsyncline)
-
- if driver in ['i810']: # i810 driver
- if self.layout in (XSetup.LAYOUT_SINGLE_XINERAMA,
- XSetup.LAYOUT_DUAL,
- XSetup.LAYOUT_CLONE):
- new_option = self.x_device[i].option.makeLine(None,["MonitorLayout", "CRT,LFP"])
- self.x_device[i].option.append(new_option)
- if self.layout==XSetup.LAYOUT_CLONE:
- new_option = self.x_device[i].option.makeLine(None,["Clone","on"])
- self.x_device[i].option.append(new_option)
-
- # Find the closest matching refresh rate for the second monitor.
- primary_screen = self.setup.getPrimaryScreen()
- secondary_screen = self.setup.getSecondaryScreen()
- resolution = primary_screen.getAvailableResolutions()[primary_screen.getResolutionIndex()]
- secondary_resolution_index = secondary_screen.getAvailableResolutions().index(resolution)
- secondary_rates = secondary_screen.getAvailableRefreshRatesForResolution(secondary_resolution_index)
- primary_rate = primary_screen.getAvailableRefreshRates()[primary_screen.getRefreshRateIndex()]
-
- best_rate = 50
- best_score = 1000000
- for rate in secondary_rates:
- score = abs(rate-primary_rate)
- if score < best_score:
- best_score = score
- best_rate = rate
-
- # Specify a working refresh rate for the second monitor.
- new_option = self.x_device[i].option.makeLine(None,["CloneRefresh",str(best_rate)])
- self.x_device[i].option.append(new_option)
-
- self._insertRawLinesIntoConfig(self.x_device[i], self.gfxcard_model.getLines())
-
- self.screens[i]._syncXorgConfig(self.x_device[i])
-
- self.original_gfxcard_model = self.gfxcard_model
- self.original_proprietary_driver = self.proprietary_driver
- self.original_layout = self.layout
-
- def _insertRawLinesIntoConfig(self,section,lines):
- reader = csv.reader(lines,delimiter=' ')
- for row in reader:
- if len(row)>=2:
- if row[0].lower()=="option":
- option = section.option.makeLine(None,row[1:])
- section.option.append(option)
-
-############################################################################
-class Screen(object):
- """Represents a single output/screen/monitor on a graphics card.
-
- Changes to the screen resolution, refresh rate, rotation and reflection
- settings are not made active until the method applyResolutionSettings() is
- called. After calling applyResolutionSettings(), changes can be backed out
- of with the revertResolutionSettings() method. If you, should I say the user,
- is satisfied with the new settings then call the acceptResolutionSettings()
- method.
-
- Gamma correction settings take effect immediately, and don't take part in the
- apply, revert and accept mechanism above.
- """
-
- RR_Rotate_0 = xf86misc.XF86Screen.RR_Rotate_0
- RR_Rotate_90 = xf86misc.XF86Screen.RR_Rotate_90
- RR_Rotate_180 = xf86misc.XF86Screen.RR_Rotate_180
- RR_Rotate_270 = xf86misc.XF86Screen.RR_Rotate_270
- RR_Reflect_X = xf86misc.XF86Screen.RR_Reflect_X
- RR_Reflect_Y = xf86misc.XF86Screen.RR_Reflect_Y
-
- def __init__(self, gfx_card=None, x_config_screen=None, x_config_monitor=None, \
- monitor_model=None, x_config=None):
- """Create a Screen object.
-
- This method is private to this module.
- """
- self.gfx_card = gfx_card
- self.x_config_screen = x_config_screen
-
- self.x_config_monitor = x_config_monitor
- self.monitor_model = monitor_model
- self.monitor_aspect = ModeLine.ASPECT_4_3
- self.original_monitor_model = monitor_model
- self.x_config = x_config
-
- # Cookup some sensible screen sizes.
- self.standard_sizes = GetMonitorModeDB().getAllResolutions()
-
- self.x_live_screen = None
-
- # Intialise the gamma settings with defaults.
- self.redgamma = 1.0
- self.greengamma = 1.0
- self.bluegamma = 1.0
- self.allgamma = 1.0
- self.settingall = True
-
- # If there is a monitor xorg.conf section then look there for gamma info.
- if self.x_config_monitor is not None:
- gamma_row = self.x_config_monitor.getRow('gamma')
- if gamma_row is not None:
- # Read the gamma info out of xorg.conf
- try:
- if len(gamma_row)==3:
- self.redgamma = float(gamma_row[0])
- self.greengamma = float(gamma_row[1])
- self.bluegamma = float(gamma_row[2])
- self.allgamma = self.redgamma
- elif len(gamma_row)==1:
- self.allgamma = float(gamma_row[0])
- self.redgamma = self.allgamma
- self.greengamma = self.allgamma
- self.bluegamma = self.allgamma
- except ValueError:
- pass
-
- # Try to work out if this monitor is setup for 4:3 modes or 16:9.
- aspect_43_count = 0
- aspect_169_count = 0
- # Count the number of 4:3 modelines compared to 16:9 modes.
- for mode in self.x_config_monitor.modeline:
- try:
- # Don't count the fallback resolution. It is also present
- # if the monitor is widescreen. Just ignore it.
- if (mode._row[2],mode._row[6])!=FALLBACK_RESOLUTION:
- if MonitorModeDB.aspectRatio(mode._row[2],mode._row[6])==ModeLine.ASPECT_4_3:
- aspect_43_count += 1
- else:
- aspect_169_count += 1
- except IndexError:
- pass
-
- if aspect_43_count >= aspect_169_count:
- self.monitor_aspect = ModeLine.ASPECT_4_3
- else:
- self.monitor_aspect = ModeLine.ASPECT_16_9
-
- # Backup the settings
- (self.originalredgamma, self.originalgreengamma, self.originalbluegamma) = (
- self.redgamma, self.greengamma, self.bluegamma)
- self.originalallgamma = self.allgamma
- self.originalsettingall = self.settingall
- self.original_monitor_aspect = self.monitor_aspect
-
- def _setXLiveScreen(self,x_live_screen):
- self.x_live_screen = x_live_screen
-
- def _finalizeInit(self):
-
- if self.x_live_screen is not None and self.x_live_screen.resolutionSupportAvailable():
- self._computeSizesFromXorg()
-
- (cw,ch,x,x) = self.x_live_screen.getSize()
- i = 0
- self.currentsizeindex = 0
- for size in self.available_sizes:
- if (cw,ch)==size:
- self.currentsizeindex = i
- break
- i += 1
-
- self.currentrefreshrate = self.x_live_screen.getRefreshRate()
- self.currentrotation = self.x_live_screen.getRotation() & (
- Screen.RR_Rotate_0 | Screen.RR_Rotate_90 | Screen.RR_Rotate_180 | Screen.RR_Rotate_270)
- self.currentreflection = self.x_live_screen.getRotation() & (
- Screen.RR_Reflect_X | Screen.RR_Reflect_Y)
-
- else:
- # There is no live info, so try to collect some info out
- # of xorg.conf itself.
-
- # Cookup some reasonable screen resolutions based on what we know about the monitor.
- self._computeSizesFromMonitor()
-
- (cw,ch) = self.available_sizes[0]
- self.currentrefreshrate = None
-
- # Dig through the Display sections in the xorg.conf Screen section
- # and try to find the first resolution/mode.
- if self.x_config_screen is not None:
- default_depth = self.x_config_screen.defaultdepth
-
- current_mode_name = None
-
- for display_section in self.x_config_screen.getSections('display'):
- if default_depth is None or display_section.depth==default_depth:
- modes_row = display_section.getRow('modes')
- if modes_row is not None and len(modes_row)>=1:
- current_mode_name = modes_row[0]
- break
-
- if current_mode_name is not None:
- for mode in self.mode_list:
- if mode.getName()==current_mode_name:
- cw = mode.getWidth()
- ch = mode.getHeight()
- self.currentrefreshrate = mode.getVRefresh()
- break
-
- # Work out the index of the current resolution
- i = 0
- for size in self.available_sizes:
- if (cw,ch)==size:
- self.currentsizeindex = i
- break
- i += 1
-
- if self.currentrefreshrate is None:
- self.currentrefreshrate = self.getAvailableRefreshRates()[0]
-
- self.currentrotation = Screen.RR_Rotate_0 # FIXME
- self.currentreflection = 0 # FIXME
-
- # Gamma settings
- if self.x_live_screen is not None:
- try:
- (self.redgamma, self.greengamma, self.bluegamma, self.allgama,
- self.settingall) = self._getGammaFromLiveScreen()
- except:
- (self.redgamma, self.greengamma, self.bluegamma, self.allgama,
- self.settingall) = self._getGammaFromXorg()
- else:
- (self.redgamma, self.greengamma, self.bluegamma, self.allgama,
- self.settingall) = self._getGammaFromXorg()
-
- self.originalsizeindex = self.currentsizeindex
- self.original_size = self.getAvailableResolutions()[self.currentsizeindex]
- self.originalrefreshrate = self.currentrefreshrate
- self.originalrotation = self.currentrotation
- self.originalreflection = self.currentreflection
-
- self.originalredgamma = self.redgamma
- self.originalgreengamma = self.greengamma
- self.originalbluegamma = self.bluegamma
-
- self.originalallgamma = self.allgamma
- self.originalsettingall = self.settingall
-
- def _getGammaFromLiveScreen(self):
- """Reads the gamma information from the x server"""
- # Read the current gamma settings directly from X.
- (redgamma, greengamma, bluegamma) = self.x_live_screen.getGamma()
-
- # Round the values off to 2 decimal places.
- redgamma = round(self.redgamma,2)
- greengamma = round(self.greengamma,2)
- bluegamma = round(self.bluegamma,2)
-
- allgamma = redgamma
- settingall = redgamma==greengamma==bluegamma
- return (redgamma, greengamma, bluegamma, allgamma, settingall)
-
- def _getGammaFromXorg(self):
- """Extracts the gamma information from the xorg configuration"""
- # Set some gamma defaults
- redgamma = greengamma = bluegamma = allgamma = 1.0
- settingall = True
-
- # Look for gamma information in xorg.conf
- if self.x_config_monitor is not None:
- gamma_row = self.x_config_monitor.getRow('gamma')
- if gamma_row is not None:
- try:
- if len(gamma_row)==1:
- allgamma = float(gamma_row[0])
- redgamma = greengamma = bluegamma = allgamma
- self.settingall = True
- elif len(gamma_row.row)==3:
- redgamma = float(gamma_row[0])
- greengamma = float(gamma_row[1])
- bluegamma = float(gamma_row[2])
- allgamma = self.redgamma
- settingall = False
- except ValueError:
- pass
- return (redgamma, greengamma, bluegamma, allgamma, settingall)
-
- def _computeSizesFromXorg(self):
- all_sizes = self.x_live_screen.getAvailableSizes()
- self.available_sizes = []
-
- # Some dualhead setups repolonger sizelists, those are unlikely
- # to be standard zes, we still want to be able to use them.s
- for i in range(len(all_sizes)):
- if len(all_sizes[i]) > 2:
- self.available_sizes.append(all_sizes[i][:2])
- elif len(alls_sizes[i]) == 2:
- if (size[0],size[1]) in self.standard_sizes:
- self.available_sizes.append(all_sizes[i])
- self.available_sizes.sort()
-
- def _computeSizesFromMonitor(self):
- monitor_model = self.monitor_model
-
- if monitor_model is None:
- # If there is no monitor model selected, then just use a default
- # model so that we at least get some fairly safe resolutions.
- monitor_model = GetMonitorModelDB().getMonitorByName("Monitor 800x600")
-
- self.mode_list = GetMonitorModeDB().getAvailableModes(monitor_model,self.monitor_aspect)
- resolutions = set()
- for mode in self.mode_list:
- pw = mode.getWidth()
- ph = mode.getHeight()
- if (pw,ph) in self.standard_sizes and pw>=640 and ph>=480:
- resolutions.add( (pw,ph) )
-
- # Filter the sizes by the amount of video ram that we have.
- color_bytes = self._getColorDepth()/8
- if self.gfx_card.getGfxCardModel().getNeedVideoRam():
- video_memory = self.gfx_card.getVideoRam()
- else:
- video_memory = 65536 # Big enough.
- video_memory *= 1024 # Convert to bytes.
-
- # Filter the list of modes according to available memory.
- self.available_sizes = [mode for mode in resolutions if mode[0]*mode[1]*color_bytes <= video_memory]
-
- self.available_sizes.sort()
-
- def _getColorDepth(self):
- if self.gfx_card.getGfxCardModel().getNeedVideoRam():
- # If this card has limited memory then we fall back to 16bit colour.
- if self.gfx_card.getVideoRam() <= 4096:
- return 16 # 16bit colour
- else:
- return 24 # 24bit colour
- else:
- return 24
-
- def getName(self):
- try:
- return "Screen %i" % (self.gfx_card.setup.getUsedScreens().index(self)+1)
- except ValueError:
- return "Screen ?"
-
- def isLive(self):
- """Returns True if this screen is currently being used by the X server.
- """
- return self.x_live_screen is not None
-
- def getMonitorModel(self):
- """
-
- Returns a MonitorModel object or None.
- """
- return self.monitor_model
-
- def setMonitorModel(self,monitor_model):
- """
-
- Setting the monitor also changes the resolutions that are available.
-
- """
- self.monitor_model = monitor_model
- self._resyncResolution()
-
- def getMonitorAspect(self):
- """
- Get the aspect ratio for the monitor
-
- Returns one of ModeLine.ASPECT_4_3 or ModeLine.ASPECT_16_9.
- """
- return self.monitor_aspect
-
- def setMonitorAspect(self,aspect):
- """Specify the aspect ratio of the monitor.
-
- Keyword arguments:
- aspect -- Aspect ratio. Either the constant ModeLine.ASPECT_4_3 or ModeLine.ASPECT_16_9.
-
- Setting this also changes the resolutions that are available.
- """
- self.monitor_aspect = aspect
- self._resyncResolution()
-
- def _resyncResolution(self):
- try:
- (preferred_width,preferred_height) = self.getAvailableResolutions()[self.getResolutionIndex()]
- except IndexError:
- print self.getAvailableResolutions()
- (preferred_width,preferred_height) = self.getAvailableResolutions()[-1]
-
- if self.isResolutionLive():
- self._computeSizesFromXorg()
- else:
- # The list of resolutions needs to be updated.
- self._computeSizesFromMonitor()
-
- if self.gfx_card.setup.getLayout()==XSetup.LAYOUT_CLONE:
- if self.gfx_card.setup.getPrimaryScreen() is self:
- # Filter the list of resolutions based on what the secondary screen can show.
- secondary_screen = self.gfx_card.setup.getSecondaryScreen()
- primary_set = set(self.available_sizes)
- secondary_set = set(secondary_screen.available_sizes)
-
- common_set = primary_set.intersection(secondary_set)
-
- suitable_resolutions = []
- # Make sure that each resolution also has a common refresh rate.
- for resolution in common_set:
- primary_rates = self.getAvailableRefreshRatesForResolution(self.available_sizes.index(resolution))
- secondary_rates = secondary_screen.getAvailableRefreshRatesForResolution(secondary_screen.available_sizes.index(resolution))
-
- if len(set(primary_rates).intersection(set(secondary_rates)))!=0:
- suitable_resolutions.append(resolution)
-
- suitable_resolutions.sort()
- self.available_sizes = suitable_resolutions
-
- # Now we select a resolution that closely matches the previous resolution.
- best_score = 2000000 # big number.
- best_index = 0
- resolution_list = self.getAvailableResolutions()
- for i in range(len(resolution_list)):
- (width,height) = resolution_list[i]
- new_score = abs(width-preferred_width) + abs(height-preferred_height)
-
- if new_score < best_score:
- best_index = i
- best_score = new_score
- self.setResolutionIndex(best_index)
-
- if self.gfx_card.setup.getLayout()==XSetup.LAYOUT_CLONE:
- if self.gfx_card.setup.getSecondaryScreen() is self:
- self.gfx_card.setup.getPrimaryScreen()._resyncResolution()
-
- def isXorgConfigChanged(self):
- isroot = os.getuid()==0
- return self.original_monitor_model is not self.monitor_model \
- or self.original_monitor_aspect != self.monitor_aspect \
- or self.isGammaSettingsChanged() \
- or (self.isResolutionSettingsChanged() and (not self.isResolutionLive() or isroot))
-
- def getRedGamma(self):
- """Get the current red gamma value.
- """
- return self.redgamma
-
- def setRedGamma(self,value):
- """Set gamma correction value for red
-
- This method takes effect immediately on the X server if possible.
-
- Keyword arguments:
- value -- gamma correction value (float)
- """
- self.redgamma = value
- if self.x_live_screen is not None:
- self.x_live_screen.setGamma( (self.redgamma,self.greengamma,self.bluegamma) )
- self.settingall = False
-
- def getGreenGamma(self):
- """Get the current green gamma value
- """
- return self.greengamma
-
- def setGreenGamma(self,value):
- """Set gamma correction value for green
-
- This method takes effect immediately on the X server if possible.
-
- Keyword arguments:
- value -- gamma correction value (float)
- """
- self.greengamma = value
- if self.x_live_screen is not None:
- self.x_live_screen.setGamma( (self.redgamma,self.greengamma,self.bluegamma) )
- self.settingall = False
-
- def getBlueGamma(self):
- """Get the current blue gamma value
- """
- return self.bluegamma
-
- def setBlueGamma(self,value):
- """Set gamma correction value for blue
-
- This method takes effect immediately on the X server if possible.
-
- Keyword arguments:
- value -- gamma correction value (float)
- """
- self.bluegamma = value
- if self.x_live_screen is not None:
- self.x_live_screen.setGamma( (self.redgamma,self.greengamma,self.bluegamma) )
- self.settingall = False
-
- def getAllGamma(self):
- """Get the gamma correction value for all colours.
-
- Returns a float.
-
- See isGammaEqual()
- """
- return self.allgamma
-
- def setAllGamma(self,value):
- """Set the gamma correction value for all colours.
-
- Keyword arguments:
- value -- gamma correction value (float)
- """
- self.allgamma = value
- if self.x_live_screen is not None:
- self.x_live_screen.setGamma( (self.allgamma,self.allgamma,self.allgamma) )
- self.settingall = True
-
- def isGammaLive(self):
- """Returns true if modifications to the gamma are immediately visible.
- """
- return self.x_live_screen is not None
-
- def isGammaEqual(self):
- """Test whether each colour is using the same gamma correction value.
-
- Returns True if the gamma value is the same for all colours
- """
- return self.getRedGamma()==self.getGreenGamma()==self.getBlueGamma()
-
- def getScreenIndex(self):
- return self.gfx_card.getScreens().index(self)
-
- # Size and resolution
- def getResolutionIndex(self):
- """Get the current resolution of this screen.
-
- Returns an index into the list of available resolutions. See
- getAvailableResolutions().
- """
- return self.currentsizeindex
-
- def setResolutionIndex(self,index):
- """Set the resolution for this screen.
-
- This method does not take effect immediately, only after applyResolutionSetttings()
- has been called.
-
- Keyword arguments:
- index -- The index of the resolution to use. See getAvailableResolutions().
- """
- self.currentsizeindex = index
-
- def getAvailableResolutions(self):
- """Get the list of available resolutions.
-
- Returns a list of screen (width,height) tuples. width and height are in
- pixels.
- """
- return self.available_sizes[:]
-
- # Rotation
- def getRotation(self):
- """Get the current rotation settings for this screen.
-
- Returns one of Screen.RR_Rotate_0, Screen.RR_Rotate_90,
- Screen.RR_Rotate_180 or Screen.RR_Rotate_270
- """
- return self.currentrotation
-
- def setRotation(self,rotation):
- """Set the rotation for this screen
-
- This method does not take effect immediately, only after
- applyResolutionSetttings() has been called. See getAvailableRotations()
- for how to find out which rotations are supported.
-
- Keyword arguments:
- rotation -- One of Screen.RR_Rotate_0, Screen.RR_Rotate_90,
- Screen.RR_Rotate_180 or Screen.RR_Rotate_270
- """
- self.currentrotation = rotation
-
- def getAvailableRotations(self):
- """Get the supported rotations for this screen.
-
- Returns a bitmask of support rotations for this screen. The returned
- integer is the bitwise OR of one or more of the constants here below.
- * Screen.RR_Rotate_0
- * Screen.RR_Rotate_90
- * Screen.RR_Rotate_180
- * Screen.RR_Rotate_270
- """
- if self.x_live_screen is not None and self.x_live_screen.resolutionSupportAvailable():
- return self.x_live_screen.getAvailableRotations() & \
- (self.RR_Rotate_0 | self.RR_Rotate_90 | self.RR_Rotate_180 | self.RR_Rotate_270)
- else:
- return self.RR_Rotate_0 # FIXME
-
-
- # Reflection
- def getReflection(self):
- """Get the current reflection settings for this screen.
-
- Returns the reflection settings as a bit string. Use Screen.RR_Reflect_X
- and Screen.RR_Reflect_Y as bitmasks to determine which reflections are
- in use.
- """
- return self.currentreflection
-
- def setReflection(self,reflection):
- """Set the reflection settings for this screen.
-
- This method does not take effect immediately, only after
- applyResolutionSetttings() has been called. See getAvailableReflections()
- for how to find out which rotations are supported.
-
- Keyword arguments:
- reflection -- Bit string (Python integer) of desired reflections.
- Bitwise OR Screen.RR_Reflect_X and Screen.RR_Reflect_Y
- to construct the string.
- """
- self.currentreflection = reflection
-
- def getAvailableReflections(self):
- """Get the supported reflections for this screen.
-
- Returns a bit string (Python integer) of supported reflections. Use
- Screen.RR_Reflect_X and Screen.RR_Reflect_Y as bitmasks to determine
- which reflections are available.
- """
- if self.x_live_screen is not None and self.x_live_screen.resolutionSupportAvailable():
- return self.x_live_screen.getAvailableRotations() & (self.RR_Reflect_X | self.RR_Reflect_Y)
- else:
- return 0 # FIXME
-
- # Refresh rates
- def getRefreshRateIndex(self):
- """Get the current refresh rate index for this screen.
-
- Returns an index into the list of refresh rates. See getAvailableRefreshRates().
- """
- rates = self.getAvailableRefreshRates()
- i = 0
- for r in rates:
- if r>=self.currentrefreshrate:
- return i
- i += 1
- return len(rates)-1
-
- def setRefreshRateIndex(self,index):
- """Set the refresh rate for this screen.
-
- Keyword arguments:
- index -- Index into the list of refresh rates. See getAvailableRefreshRates().
- """
- self.currentrefreshrate = self.getAvailableRefreshRates()[index]
-
- def getAvailableRefreshRates(self):
- """Get the list of available refresh rates
-
- Get the list of available refresh rates for the currently selected
- resolution. See setResolutionIndex() and getAvailableRefreshRatesForResolution()
-
- Returns a list of integers in Hz.
- """
- return self.getAvailableRefreshRatesForResolution(self.currentsizeindex)
-
- def getAvailableRefreshRatesForResolution(self,resolution_index):
- """Get the list of available refresh rates for the given resolution
-
- Get the list of available refresh rates for the given resolution.
-
- Keyword arguments:
- resolution_index -- Index into the list of resolutions.
-
- Returns a list of integers in Hz.
- """
- isize = self.available_sizes[resolution_index]
- if self.isResolutionLive():
- j = 0
- for size in self.x_live_screen.getAvailableSizes():
- (sw,sh,wm,hm) = size
- if isize==(sw,sh):
- rates = self.x_live_screen.getAvailableRefreshRates(j)
- rates.sort()
- return rates
- j += 1
- assert False,"Can't find matching screen resolution"
- else:
- #
- rates = []
- for mode in self.mode_list:
- if isize==(mode.getWidth(),mode.getHeight()):
- rates.append(mode.getVRefresh())
-
- rates.sort()
- return rates
-
- # Applying changes.
-
- def isResolutionLive(self):
- return self.x_live_screen is not None and \
- self.x_live_screen.resolutionSupportAvailable() and \
- self.original_monitor_model is self.monitor_model and \
- self.original_monitor_aspect==self.monitor_aspect
-
- def isResolutionSettingsChanged(self):
- try:
- current_size = self.getAvailableResolutions()[self.currentsizeindex]
- except IndexError:
- #FIXME: why does this happen?
- return False
- return current_size != self.original_size or \
- self.currentrefreshrate != self.originalrefreshrate or \
- self.currentrotation != self.originalrotation or \
- self.currentreflection != self.originalreflection
-
- def applyResolutionSettings(self):
- """Apply any tending resolution changes on the X server if possible.
-
-
- """
- if self.isResolutionSettingsChanged() and self.isResolutionLive():
- # Work out what the correct index is for randr.
- (width,height) = self.available_sizes[self.currentsizeindex]
- sizeindex = 0
- for size in self.x_live_screen.getAvailableSizes():
- (pw,ph,wm,hm) = size
- if pw==width and ph==height:
- break
- sizeindex += 1
-
- rc = self.x_live_screen.setScreenConfigAndRate(sizeindex, \
- self.currentrotation | self.currentreflection, self.currentrefreshrate)
-
- # FIXME this can fail if the config on the server has been updated.
-
- def acceptResolutionSettings(self):
- """Accept the last resolution change
- """
- self.originalsizeindex = self.currentsizeindex
- self.original_size = self.getAvailableResolutions()[self.currentsizeindex]
- self.originalrefreshrate = self.currentrefreshrate
- self.originalrotation = self.currentrotation
- self.originalreflection = self.currentreflection
-
- def revertResolutionSettings(self):
- """Revert the last resolution change on the X server
-
- """
- if self.x_live_screen is not None and self.x_live_screen.resolutionSupportAvailable():
- # Work out what the correct index is for randr.
- (width,height) = self.available_sizes[self.originalsizeindex]
- sizeindex = 0
- for size in self.x_live_screen.getAvailableSizes():
- (pw,ph,wm,hm) = size
- if pw==width and ph==height:
- break
- sizeindex += 1
-
- self.x_live_screen.setScreenConfigAndRate(sizeindex, \
- self.originalrotation | self.originalreflection, self.originalrefreshrate)
- # FIXME this can fail if the config on the server has been updated.
-
- def resetResolutionSettings(self):
- """Reset the resolution settings to the last accepted state
-
- """
- # Restore the resolution settings to their original state.
- self.currentsizeindex = self.originalsizeindex
- self.currentrefreshrate = self.originalrefreshrate
- self.currentrotation = self.originalrotation
- self.currentreflection = self.originalreflection
-
- def isGammaSettingsChanged(self):
- return self.redgamma != self.originalredgamma or \
- self.greengamma != self.originalgreengamma or \
- self.bluegamma != self.originalbluegamma or \
- self.allgamma != self.originalallgamma or \
- self.settingall != self.originalsettingall
-
- def acceptGammaSettings(self):
- (self.originalredgamma, self.originalgreengamma, self.originalbluegamma) = (
- self.redgamma, self.greengamma, self.bluegamma)
- self.originalallgamma = self.allgamma
- self.originalsettingall = self.settingall
-
- def revertGammaSettings(self):
- (self.redgamma, self.greengamma, self.bluegamma) = (
- self.originalredgamma, self.originalgreengamma, self.originalbluegamma)
- self.allgamma = self.originalallgamma
- self.settingall = self.originalsettingall
-
- if self.x_live_screen is not None:
- if self.settingall:
- self.x_live_screen.setGamma( (self.allgamma,self.allgamma,self.allgamma) )
- else:
- self.x_live_screen.setGamma( (self.redgamma,self.greengamma,self.bluegamma) )
-
- def isGammaSettingsChanged(self):
- if self.settingall:
- return self.originalallgamma != self.allgamma
- else:
- return self.originalredgamma != self.redgamma or \
- self.originalgreengamma != self.greengamma or \
- self.originalbluegamma != self.bluegamma
-
- def reset(self):
- if self.isLive():
- self.revertGammaSettings()
- self.resetResolutionSettings()
-
- self.monitor_model = self.original_monitor_model
- self.monitor_aspect = self.original_monitor_aspect
-
- def getRestartHint(self):
- if self.original_monitor_model is not self.monitor_model \
- or self.original_monitor_aspect != self.monitor_aspect \
- or (self.isResolutionSettingsChanged() and not self.isResolutionLive()):
- return XSetup.RESTART_X
- return XSetup.RESTART_NONE
-
- def _syncXorgConfig(self,x_device):
- layout = self.gfx_card.getLayout()
-
- if self.x_config_screen is None:
- self.x_config_screen = self.x_config.makeSection('',['section','screen'])
- self.x_config.append(self.x_config_screen)
- self.x_config_screen.identifier = self.x_config.createUniqueIdentifier("screen")
- self.x_config_screen.device = x_device.identifier
-
- bit_depth = self.gfx_card.setup._getColorDepth()
- self.x_config_screen.defaultdepth = bit_depth
-
- # Maybe we don't have a X config monitor section.
- if self.x_config_monitor is None:
- # Make a monitor section.
- self.x_config_monitor = self.x_config.makeSection('',['section','monitor'])
- self.x_config.append(self.x_config_monitor)
- self.x_config_monitor.identifier = self.x_config.createUniqueIdentifier("monitor")
- self.x_config_screen.monitor = self.x_config_monitor.identifier
-
- # Empty the monitor section and fill it in again.
- monitor_identifier = self.x_config_monitor.identifier
- self.x_config_monitor.clear()
- self.x_config_monitor.identifier = monitor_identifier
-
- if self.monitor_model is not None:
- if self.monitor_model.getManufacturer() is not None:
- self.x_config_monitor.vendorname = self.monitor_model.getManufacturer()
-
- self.x_config_monitor.modelname = self.monitor_model.getName()
-
- if self.monitor_model.getType()!=MonitorModel.TYPE_PLUGNPLAY:
- if self.monitor_model.getHorizontalSync() is not None:
- hsyncline = self.x_config_monitor.makeLine(None,['HorizSync',self.monitor_model.getHorizontalSync()])
- self.x_config_monitor.append(hsyncline)
-
- if self.monitor_model.getVerticalSync() is not None:
- vsyncline = self.x_config_monitor.makeLine(None,['VertRefresh',self.monitor_model.getVerticalSync()])
- self.x_config_monitor.append(vsyncline)
-
- # Add a bunch of standard mode lines.
- mode_list = GetMonitorModeDB().getAvailableModes(self.monitor_model,self.monitor_aspect)
-
- if mode_list is not None:
-
- # Filter the mode list by video memory.
- color_bytes = bit_depth/8
- if self.gfx_card.getGfxCardModel().getNeedVideoRam():
- video_memory = self.gfx_card.getVideoRam()
- else:
- video_memory = 65536 # Big enough.
- video_memory *= 1024 # Convert to bytes.
- mode_list = [mode for mode in mode_list if mode.getWidth()*mode.getHeight()*color_bytes <= video_memory]
-
- def mode_cmp(a,b): return cmp(a.getWidth(),b.getWidth())
- mode_list.sort(mode_cmp)
-
- for mode in mode_list:
- modeline = self.x_config_monitor.modeline.makeLine(None,mode.getXorgModeLineList())
- self.x_config_monitor.modeline.append(modeline)
-
- # Specify the preferred resolution.
-
- # Get rid of any old display subsections.
- for display_section in self.x_config_screen.getSections('display'):
- self.x_config_screen.remove(display_section)
-
- try:
- (preferred_width, preferred_height) = self.getAvailableResolutions()[self.currentsizeindex]
- preferred_rate = self.getAvailableRefreshRates()[self.getRefreshRateIndex()]
- except IndexError, errmsg:
- # This is presumed to be better than a crash:
- print "Failed to get preferred width, height, or rate - Assuming none. IndexError: ", errmsg
- preferred_width = 0
- preferred_height = 0
- preferred_rate = 0
-
- # Find the monitor supported mode that best matches what the user has selected.
- best_score = 2000000 # big number.
- best_index = 0
- for i in range(len(mode_list)):
- mode = mode_list[i]
- new_score = abs(mode.getWidth()-preferred_width) + \
- abs(mode.getHeight()-preferred_height) + \
- abs(mode.getVRefresh()-preferred_rate)
- if new_score < best_score:
- best_index = i
- best_score = new_score
-
- # This is all about putting the list of resolutions into a
- # sensible preferred order starting with what the user has chosen
- # and then the rest of the resolutions.
- lower = best_index - 1
- higher = best_index + 1
- len_modes = len(mode_list)
-
- mode_indexes = []
- mode_indexes.append(best_index)
- while lower>=0 or higher<len_modes: # interlace the two sets of indexes.
- if higher<len_modes:
- mode_indexes.append(higher)
- higher += 1
- if lower>=0:
- mode_indexes.append(lower)
- lower -= 1
-
- # Convert the list of resolution indexes into monitor mode names and a modes line for xorg.conf.
- mode_list_line = ['modes']
- mode_list_line.extend([ mode_list[mode_index].getName() for mode_index in mode_indexes ])
-
- # Create the Display subsections in the Screen section.
- display_section = self.x_config_screen.makeSection(None,['SubSection','Display'])
- display_section.depth = bit_depth
-
- # The virtual screen size hack should not be used in combination
- # with Xinerama (RandR doesn't work with Xinerama).
- if layout!=XSetup.LAYOUT_SINGLE_XINERAMA and self.isLive():
- # Find the largest monitor supported mode. We need this info
- # to set the size of the virtual screen. See the big comment
- # in displayconfig-restore.py.
- virtual_width = max([mode_list[mode_index].getWidth() for mode_index in mode_indexes])
- virtual_height = max([mode_list[mode_index].getHeight() for mode_index in mode_indexes])
- display_section.append(display_section.makeLine(None,["virtual",virtual_width,virtual_height]))
-
- display_section.append(display_section.makeLine(None,mode_list_line))
-
- self.x_config_screen.append(display_section)
-
- # Set the gamma info too.
- if self.settingall:
- gamma_row = self.x_config_monitor.makeLine(None,['gamma',str(self.allgamma)])
- else:
- gamma_row = self.x_config_monitor.makeLine(None,['gamma',str(self.redgamma),str(self.greengamma),str(self.bluegamma)])
- self.x_config_monitor.append(gamma_row)
-
- # If resolution changes were not live because the monitor has been changed
- # then we also stop them from being live from now on too.
- if not self.isResolutionLive():
- self.x_live_screen = None
- self.acceptResolutionSettings()
-
- # The orignal monitor model is now the selected one. => no changes need to be applied now.
- self.original_monitor_model = self.monitor_model
- self.original_monitor_aspect = self.monitor_aspect
-
- def _getXorgScreenSection(self):
- return self.x_config_screen
-
- def _getGfxCard(self):
- return self.gfx_card
-
- def __str__(self):
- # FIXME string = str(self.getIdentifier()) + " {"
- string = " {"
- if self.isLive():
- string += "Size: "
- string += str(self.getAvailableResolutions()[self.getResolutionIndex()])
- string += " "
- else:
- string += "Not live, "
- if self.monitor_model is not None:
- string += "Monitor:" + str(self.monitor_model)
- string += "}"
- return string
-
-############################################################################
-class GfxCardModel(object):
- """Describes the properties of a particular model of graphics card.
-
- """
- def __init__(self,name):
- self.name = name
- self.vendor = None
- self.server = None
- self.driver = None
- self.proprietarydriver = None
- self.lines = []
- self.seeobj = None
- self.noclockprobe = None
- self.unsupported = None
- self.driglx = None
- self.utahglx = None
- self.driglxexperimental = None
- self.utahglxexperimental = None
- self.badfbrestore = None
- self.badfbrestoreexf3 = None
- self.multihead = None
- self.fbtvout = None
- self.needvideoram = None
-
- def getName(self): return self.name
-
- def setVendor(self,vendor): self.vendor = vendor
- def getVendor(self): return self._get(self.vendor,"getVendor",None)
- def setServer(self,server): self.server = server
- def getServer(self): return self._get(self.server,"getServer",None)
- def setDriver(self,driver): self.driver = driver
- def getDriver(self): return self._get(self.driver,"getDriver",None)
- def setProprietaryDriver(self,proprietarydriver): self.proprietarydriver = proprietarydriver
- def getProprietaryDriver(self): return self._get(self.proprietarydriver,"getProprietaryDriver",None)
- def addLine(self,line): self.lines.append(line)
- def getLines(self):
- if (len(self.lines)==0) and (self.seeobj is not None):
- return self.seeobj.getLines()
- else:
- return self.lines[:] # Copy
-
- def setNoClockProbe(self,noprobe): self.noclockprobe = noprobe
- def getNoClockProbe(self): return self._get(self.noclockprobe,"getNoClockProbe",False)
- def setUnsupported(self,unsupported): self.unsupported = unsupported
- def getUnsupported(self): return self._get(self.unsupported,"getUnsupported",False)
- def setDriGlx(self,on): self.driglx = on
- def getDriGlx(self): return self._get(self.driglx,"getDriGlx",False)
- def setUtahGlx(self,on): self.utahglx = on
- def getUtahGlx(self): return self._get(self.utahglx,"getUtahGlx",False)
- def setDriGlxExperimental(self,on): self.driglxexperimental = on
- def getDriGlxExperimental(self): return self._get(self.driglxexperimental,"getDriGlxExperimental",False)
- def setUtahGlxExperimental(self,on): self.utahglxexperimental = on
- def getUtahGlxExperimental(self): return self._get(self.utahglxexperimental,"getUtahGlxExperimental",False)
- def setBadFbRestore(self,on): self.badfbrestore = on
- def getBadFbRestore(self,proprietary=False):
- if proprietary:
- driver = self.getProprietaryDriver()
- else:
- driver = self.getDriver()
- if driver in ['i810','intel','fbdev','nvidia','vmware']:
- return True
- if self.badfbrestore is not None:
- return self.badfbrestore
- if self.seeobj is not None:
- return self.seeobj.getBadFbRestore(proprietary)
- return False
- def setBadFbRestoreXF3(self,on): self.badfbrestoreexf3 = on
- def getBadFbRestoreXF3(self): return self._get(self.badfbrestoreexf3,"getBadFbRestoreXF3",False)
- def setMultiHead(self,n): self.multihead = n
- def getMultiHead(self): return self._get(self.multihead,"getMultiHead",1)
- def setFbTvOut(self,on): self.fbtvout = on
- def getFbTvOut(self): return self._get(self.fbtvout,"getFbTvOut",False)
- def setNeedVideoRam(self,on): self.needvideoram = on
- def getNeedVideoRam(self): return self._get(self.needvideoram,"getNeedVideoRam",False)
- def setSee(self,seeobj): self.seeobj = seeobj
-
- # If the seeobj is set, then all attributes that are not filled in for this
- # instance are inheritted from seeobj.
- def _get(self,attr,meth,default):
- if attr is not None:
- return attr
- if self.seeobj is not None:
- return getattr(self.seeobj,meth)()
- else:
- return default
-
- def __str__(self):
- return self.getName()
-
-############################################################################
-gfxcard_model_db_instance = None # Singleton.
-
-def GetGfxCardModelDB():
- """Returns a GfxCardModelDB instance.
- """
- global gfxcard_model_db_instance
- # Lazy instantiation.
- if gfxcard_model_db_instance is None:
- gfxcard_model_db_instance = GfxCardModelDB()
- return gfxcard_model_db_instance
-
-############################################################################
-class GfxCardModelDB(object):
- def __init__(self):
- # List of gfx card databases, if order of preference.
- filename = '/usr/share/ldetect-lst/Cards+'
- if not os.path.exists(filename):
- filename = os.path.join(data_file_dir,"Cards+")
-
- # The card DB. A dict mapping card names to card objects.
- self.db = {}
- # The keys in this dict will be vendor names, values are dicts mapping card names to objects.
- self.vendordb = {}
- self.driverdb = {}
-
- self.drivers = self._getAvailableDrivers()
-
- self.proprietary_drivers = []
-
- self._checkProprietaryDrivers()
- self._loadDrivers(self.drivers, self.proprietary_drivers)
- self._loadDB(filename)
-
- def getGfxCardModelByName(self,name):
- return self.db[name]
-
- def getGfxCardModelByDriverName(self,driver_name):
- return self.driverdb[driver_name]
-
- def getAllGfxCardModelNames(self):
- return self.db.keys()
-
- def _getDriverDirs(self):
- "Returns a list of directories where X driver files may be located"
-
- # Fallback dir:
- defaultDirs = ["/usr/lib/xorg/modules/drivers/"]
-
- # Get display number:
- display_number = 0
- if "DISPLAY" in os.environ:
- display_name = os.environ["DISPLAY"]
- displayRE = re.compile("^.*:(\d+)\.\d+$")
- m = displayRE.match(display_name)
- if m:
- display_number = int(m.group(1))
- else:
- print "failed to parse display number from '%s' - falling back to default (%d)" % (display_name, display_number)
- else:
- print "$DISPLAY not set - falling back to default number (%d)" % display_number
-
- # Get the list of module paths from the Xorg log file:
- XLogfile = "/var/log/Xorg.%d.log" % display_number
- cmd = "awk -F \" ModulePath set to \" '/^\(..\) ModulePath set to (.*)/ {print $2}' %s" % XLogfile
-
- baseList = os.popen(cmd).readline().strip().strip('"')
- if baseList == "":
- print "warning: failed to get module paths from '%s' - falling back to default" % XLogfile
- return defaultDirs
-
- pathList = []
- for basePath in baseList.split(","):
- pathList.append("%s/drivers/" % basePath)
-
- return pathList
-
- def _getAvailableDrivers(self):
- """
- Returns the list of available X graphics drivers.
- Algorithm taken from Xorg source (see GenerateDriverlist() in xf86Config.C).
- """
-
- # These are drivers that cannot actually be used in xorg.conf, hence they are hidden:
- hiddenDrivers = (
- "atimisc", # seems to be just the internal implementation for ati driver
- "dummy", # dummy driver without any output
- "v4l", # not an actual video device driver, but just the v4l module
- "ztv" # seems to be the TV output module for AMD Geode
- )
-
- drivers = []
- driverDirectories = self._getDriverDirs()
-
- driverNameRE = re.compile("^(.+)_drv.(s)?o$")
- for ddir in driverDirectories:
- try:
- driverFiles = os.listdir(ddir)
- except OSError:
- print "error reading directory '%s'" % ddir
- continue
- for f in driverFiles:
- m = driverNameRE.match(f)
- if m:
- driverName = m.group(1)
- if driverName in drivers:
- print "ignoring duplicate driver '%s/%s'" % (ddir, f)
- else:
- if driverName in hiddenDrivers:
- #print "ignoring hidden driver '%s'" % driverName
- pass
- else:
- drivers.append(driverName)
- else:
- #print "ignoring driver file with invalid name '%s'" % f
- pass
- #print "found %d drivers" % len(drivers)
- return drivers
-
- def _checkProprietaryDrivers(self):
- # Check for the NVidia driver.
- # FIXME x86_64 => 'lib64'
-
- if (os.path.exists("/usr/X11R6/lib/modules/drivers/nvidia_drv.o") and \
- os.path.exists("/usr/X11R6/lib/modules/extensions/libglx.so")) \
- or \
- (os.path.exists("/usr/lib/xorg/modules/drivers/nvidia_drv.o") and \
- os.path.exists("/usr/lib/xorg/modules/libglx.so")) \
- or \
- (os.path.exists("/usr/lib/xorg/modules/drivers/nvidia_drv.so") and \
- os.path.exists("/usr/lib/xorg/modules/extensions/libglx.so")):
- self.proprietary_drivers.append("nvidia")
-
- # Check for the ATI driver
- if (os.path.exists("/usr/X11R6/lib/modules/dri/fglrx_dri.so") and \
- os.path.exists("/usr/X11R6/lib/modules/drivers/fglrx_drv.o")) or \
- (os.path.exists("/usr/lib/dri/fglrx_dri.so") and \
- os.path.exists("/usr/lib/xorg/modules/drivers/fglrx_drv.so")):
- self.proprietary_drivers.append("fglrx")
-
- # FIXME MATROX_HAL?
-
- def _loadDrivers(self, drivers, proprietary_drivers):
- # Insert the Driver entries.
- for drivername in drivers:
- cardobj = GfxCardModel(drivername)
- cardobj.setDriver(drivername)
- self.db[drivername] = cardobj
- self.driverdb[drivername] = cardobj
-
- if drivername=="nv" and "nvidia" in proprietary_drivers:
- cardobj.setProprietaryDriver("nvidia")
- self.driverdb["nvidia"] = cardobj
- elif drivername=="ati" and "fglrx" in proprietary_drivers:
- cardobj.setProprietaryDriver("fglrx")
- self.driverdb["fglrx"] = cardobj
-
- def _loadDB(self,filename):
- vendors = ['3Dlabs', 'AOpen', 'ASUS', 'ATI', 'Ark Logic', 'Avance Logic',
- 'Cardex', 'Chaintech', 'Chips & Technologies', 'Cirrus Logic', 'Compaq',
- 'Creative Labs', 'Dell', 'Diamond', 'Digital', 'ET', 'Elsa', 'Genoa',
- 'Guillemot', 'Hercules', 'Intel', 'Leadtek', 'Matrox', 'Miro', 'NVIDIA',
- 'NeoMagic', 'Number Nine', 'Oak', 'Orchid', 'RIVA', 'Rendition Verite',
- 'S3', 'Silicon Motion', 'STB', 'SiS', 'Sun', 'Toshiba', 'Trident',
- 'VideoLogic']
-
- cardobj = None
- # FIXME the file might be compressed.
- fhandle = open(filename,'r')
- for line in fhandle.readlines():
- line = line.strip()
- if len(line)!=0:
- if not line.startswith("#"):
- if line.startswith("NAME"):
- cardobj = GfxCardModel(line[4:].strip())
- cardname = cardobj.getName()
- self.db[cardname] = cardobj
-
- # Try to extract a vendor name from the card's name.
- for vendor in vendors:
- if vendor in cardname:
- cardobj.setVendor(vendor)
- if vendor not in self.vendordb:
- self.vendordb[vendor] = {}
- self.vendordb[vendor][cardname] = cardobj
- break
- else:
- if "Other" not in self.vendordb:
- self.vendordb["Other"] = {}
- self.vendordb["Other"][cardname] = cardobj
-
- elif line.startswith("SERVER"):
- cardobj.setServer(line[6:].strip())
- elif line.startswith("DRIVER2"):
- driver = line[7:].strip()
- if driver in self.proprietary_drivers:
- cardobj.setProprietaryDriver(driver)
- elif line.startswith("DRIVER"):
- cardobj.setDriver(line[6:].strip())
- elif line.startswith("LINE"):
- cardobj.addLine(line[4:].strip())
- elif line.startswith("SEE"):
- try:
- cardobj.setSee(self.db[line[3:].strip()])
- except KeyError:
- pass
- elif line.startswith("NOCLOCKPROBE"):
- cardobj.setNoClockProbe(True)
- elif line.startswith("UNSUPPORTED"):
- cardobj.setUnsupported(True)
- elif line.startswith("DRI_GLX"):
- cardobj.setDriGlx(True)
- elif line.startswith("UTAH_GLX"):
- cardobj.setUtahGlx(True)
- elif line.startswith("DRI_GLX_EXPERIMENTAL"):
- cardobj.setDriGlxExperimental(True)
- elif line.startswith("UTAH_GLX_EXPERIMENTAL"):
- cardobj.setUtahGlxExperimental(True)
- elif line.startswith("BAD_FB_RESTORE"):
- cardobj.setBadFbRestore(True)
- elif line.startswith("BAD_FB_RESTORE_XF3"):
- cardobj.setBadFbRestoreXF3(True)
- elif line.startswith("MULTI_HEAD"):
- cardobj.setMultiHead(int(line[10:].strip()))
- elif line.startswith("FB_TVOUT"):
- cardobj.setFbTvOut(True)
- elif line.startswith("NEEDVIDEORAM"):
- cardobj.setNeedVideoRam(True)
- fhandle.close()
-
-############################################################################
-class MonitorModel(object):
- TYPE_NORMAL = 0
- TYPE_PLUGNPLAY = 1
- TYPE_CUSTOM = 2
-
- def __init__(self):
- self.name = None
- self.manufacturer = None
- self.eisaid = None
- self.horizontalsync = None
- self.verticalsync = None
- self.dpms = False
- self.type = MonitorModel.TYPE_NORMAL
-
- def copy(self):
- newmonitor = MonitorModel()
- newmonitor.name = self.name
- newmonitor.manufacturer = self.manufacturer
- newmonitor.eisaid = self.eisaid
- newmonitor.horizontalsync = self.horizontalsync
- newmonitor.verticalsync = self.verticalsync
- newmonitor.dpms = self.dpms
- return newmonitor
-
- def getName(self): return self.name
- def setName(self,name): self.name = name
- def getManufacturer(self): return self.manufacturer
- def setManufacturer(self,manufacturer): self.manufacturer = manufacturer
- def setEisaId(self,eisaid): self.eisaid = eisaid
- def getEisaId(self): return self.eisaid
- def setDpms(self,on): self.dpms = on
- def getDpms(self): return self.dpms
- def getHorizontalSync(self): return self.horizontalsync
- def setHorizontalSync(self,horizontalsync): self.horizontalsync = horizontalsync
- def getVerticalSync(self): return self.verticalsync
- def setVerticalSync(self,verticalsync): self.verticalsync = verticalsync
- def setType(self,flag): self.type = flag
- def getType(self): return self.type
- def __str__(self):
- return "{Name:"+self.name+"}"
-
-############################################################################
-class PlugNPlayMonitorModel(MonitorModel):
- def __init__(self,monitor_model_db):
- MonitorModel.__init__(self)
- self.monitor_detected = False
- self.monitor_model_db = monitor_model_db
-
- def getEisaId(self):
- self._detectMonitor()
- return self.eisaid
-
- def getHorizontalSync(self):
- self._detectMonitor()
- return self.horizontalsync
-
- def getVerticalSync(self):
- self._detectMonitor()
- return self.verticalsync
-
- def _detectMonitor(self):
- if not self.monitor_detected:
- (eisaid, horizontalsync, verticalsync) = self.monitor_model_db._detectMonitor()
- if eisaid is not None:
- self.eisaid = eisaid
- if horizontalsync is not None:
- self.horizontalsync = horizontalsync
- if verticalsync is not None:
- self.verticalsync = verticalsync
-
- self.monitor_detected = True
-
-############################################################################
-monitor_model_db_instance = None # Singleton
-
-def GetMonitorModelDB(force=False):
- """Returns a GetMonitorModelDB instance.
- """
- global monitor_model_db_instance
- if monitor_model_db_instance is None or force == True:
- monitor_model_db_instance = MonitorModelDB()
- return monitor_model_db_instance
-
-############################################################################
-class MonitorModelDB(object):
- def __init__(self):
- self.db = {}
- self.vendordb = {}
- self.genericdb = {}
- self.customdb = {}
- self.custom_counter = 1
- self.monitor_detect_run = False
-
- # Plug'n Play is a kind of fake entry for monitors that are detected but unknown.
- # It's frequency info is filled in by hardware detection or from the X server config.
- self._plugnplay = PlugNPlayMonitorModel(self)
- self._plugnplay.setName("Plug 'n' Play")
- self._plugnplay.setManufacturer(self._plugnplay.getName())
- self._plugnplay.setType(MonitorModel.TYPE_PLUGNPLAY)
- # This default is what Xorg claims to use when there is no
- # horizontal sync info in the a monitor section.
- self._plugnplay.setHorizontalSync("28.0-33.0")
- # This default is what Xorg claims to use when there is no
- # vertical sync info in the a monitor section.
- self._plugnplay.setVerticalSync("43-72")
- self.customdb[self._plugnplay.getName()] = self._plugnplay
- self.db[self._plugnplay.getName()] = self._plugnplay
-
- # Load monitors from the shipped database
- filename = "/usr/share/ldetect-lst/MonitorsDB"
- if not os.path.exists(filename):
- filename = os.path.join(data_file_dir,"MonitorsDB")
- self.load(filename)
- # Load monitors from the custom database
- filename = os.path.join(var_data_dir, "CustomMonitorsDB")
- if os.path.exists(filename):
- self.load(filename)
-
- def load(self,filename,split=";"):
- fhandle = open(filename,'r')
- for line in fhandle.readlines():
- line = line.strip()
- if len(line)!=0:
- if not line.startswith("#"):
- try:
- parts = line.split(split)
- monitorobj = MonitorModel()
- monitorobj.setManufacturer(parts[0].strip())
- monitorobj.setName(parts[1].strip())
- monitorobj.setEisaId(parts[2].strip().upper())
- monitorobj.setHorizontalSync(parts[3].strip())
- monitorobj.setVerticalSync(parts[4].strip())
- if len(parts)>=6:
- monitorobj.setDpms(parts[5].strip()=='1')
- self.db[monitorobj.getName()] = monitorobj
-
- if monitorobj.getManufacturer() in \
- ["Generic LCD Display", "Generic CRT Display"]:
- self.genericdb[monitorobj.getName()] = monitorobj
- else:
- if monitorobj.getManufacturer() not in self.vendordb:
- self.vendordb[monitorobj.getManufacturer()] = {}
- self.vendordb[monitorobj.getManufacturer()]\
- [monitorobj.getName()] = monitorobj
-
- except IndexError:
- print "Bad monitor line:",line
- fhandle.close()
-
- def getMonitorByName(self,name):
- return self.db.get(name,None)
-
- def newCustomMonitor(self,name=None):
- custom_model = MonitorModel()
- if name is None:
- name = "Custom %i" % self.custom_counter
- custom_model.setName(name)
- self.db[custom_model.getName()] = custom_model
- self.customdb[name] = custom_model
- self.custom_counter += 1
- return custom_model
-
- def getCustomMonitors(self):
- return self.customdb
-
- def detect(self):
- """Detect the attached monitor.
-
- Returns a 'monitor' object on success, else None.
- """
- (eisaid,hrange,vrange) = self._detectMonitor()
-
- # Look up the EISAID in our database.
- if eisaid is not None:
- for monitor in self.db:
- if eisaid==self.db[monitor].getEisaId():
- return self.db[monitor]
-
- return self._plugnplay
-
- def _detectMonitor(self):
- if not self.monitor_detect_run:
- eisaid = None
- hrange = None
- vrange = None
-
- if os.path.isfile("/usr/sbin/monitor-edid"):
- # This utility appeared in Mandriva 2005 LE
- output = ExecWithCapture("/usr/sbin/monitor-edid",["monitor-edid","-v"])
- for line in output.split("\n"):
- if "HorizSync" in line:
- hrange = line.split()[1]
- elif "VertRefresh" in line:
- vrange = line.split()[1]
- elif line.startswith("EISA ID:"):
- eisaid = line[9:].upper()
-
- elif os.path.isfile("/usr/sbin/ddcxinfos"):
- # This utility _was_ standard on Mandrake 10.1 and earlier.
- output = ExecWithCapture("/usr/sbin/ddcxinfos",["ddcxinfos"])
- for line in output.split("\n"):
- if "HorizSync" in line:
- hrange = line.split()[0]
- elif "VertRefresh" in line:
- vrange = line.split()[0]
- elif "EISA ID=" in line:
- eisaid = line[line.find("EISA ID=")+8:].upper()
-
- elif os.path.isfile("/usr/sbin/ddcprobe"):
- # on Debian
- """
- ddcprobe's output looks like this:
-
- ...
- eisa: SAM00b1
- ...
- monitorrange: 30-81, 56-75
- ...
- """
- output = ExecWithCapture("/usr/sbin/ddcprobe",["ddcprobe"])
- for line in output.split("\n"):
- if line.startswith("eisa:"):
- parts = line.split(":")
- if len(parts)>=2:
- eisaid = parts[1].strip().upper()
- elif line.startswith("monitorrange:"):
- parts = line.replace(',','').split()
- if len(parts)==3:
- hrange = parts[1].strip()
- vrange = parts[2].strip()
-
- self.detected_eisa_id = eisaid
- self.detected_h_range = hrange
- self.detected_v_range = vrange
- self.monitor_detect_run = True
-
- return (self.detected_eisa_id, self.detected_h_range, self.detected_v_range)
-
-############################################################################
-
-SYNC_TOLERANCE = 0.01 # 1 percent
-class ModeLine(object):
- ASPECT_4_3 = 0
- ASPECT_16_9 = 1
-
- XF86CONF_PHSYNC = 0x0001
- XF86CONF_NHSYNC = 0x0002
- XF86CONF_PVSYNC = 0x0004
- XF86CONF_NVSYNC = 0x0008
- XF86CONF_INTERLACE = 0x0010
- XF86CONF_DBLSCAN = 0x0020
- XF86CONF_CSYNC = 0x0040
- XF86CONF_PCSYNC = 0x0080
- XF86CONF_NCSYNC = 0x0100
- XF86CONF_HSKEW = 0x0200 # hskew provided
- XF86CONF_BCAST = 0x0400
- XF86CONF_CUSTOM = 0x0800 # timing numbers customized by editor
- XF86CONF_VSCAN = 0x1000
- flags = {"interlace": XF86CONF_INTERLACE,
- "doublescan": XF86CONF_DBLSCAN,
- "+hsync": XF86CONF_PHSYNC,
- "-hsync": XF86CONF_NHSYNC,
- "+vsync": XF86CONF_PVSYNC,
- "-vsync": XF86CONF_NVSYNC,
- "composite": XF86CONF_CSYNC,
- "+csync": XF86CONF_PCSYNC,
- "-csync": XF86CONF_NCSYNC }
-
- # Thanks go out to Redhat for this code donation. =)
- def __init__(self, elements):
- self.name = elements[1].strip('"')
- self.clock = float(elements[2])
- self.hdisp = int(elements[3])
- self.hsyncstart = int(elements[4])
- self.hsyncend = int(elements[5])
- self.htotal = int(elements[6])
- self.vdisp = int(elements[7])
- self.vsyncstart = int(elements[8])
- self.vsyncend = int(elements[9])
- self.vtotal = int(elements[10])
-
- self.flags = 0
- for i in range(11, len(elements)):
- try:
- self.flags |= ModeLine.flags[string.lower(elements[i])]
- except KeyError:
- pass
-
- def getWidth(self):
- return self.hdisp
-
- def getHeight(self):
- return self.vdisp
-
- def getName(self):
- return self.name
-
- def getVRefresh(self):
- vrefresh = self.clock * 1000000.0 / float(self.htotal * self.vtotal)
- if self.flags & ModeLine.XF86CONF_INTERLACE:
- vrefresh = vrefresh * 2.0
- if self.flags & ModeLine.XF86CONF_DBLSCAN:
- vrefresh = vrefresh / 2.0
- return int(round(vrefresh))
-
- # Basically copied from xf86CheckModeForMonitor
- def supports(self, monitor_hsync, monitor_vsync):
- hsync = self.clock * 1000 / self.htotal
- for freq in monitor_hsync:
- if hsync > freq[0] * (1.0 - SYNC_TOLERANCE) and hsync < freq[1] * (1.0 + SYNC_TOLERANCE):
- break
- else:
- return False
-
- vrefresh = self.getVRefresh()
- for freq in monitor_vsync:
- if vrefresh > freq[0] * (1.0 - SYNC_TOLERANCE) and vrefresh < freq[1] * (1.0 + SYNC_TOLERANCE):
- return True
- return False
-
- def getXorgModeLineList(self):
- row = [self.name, str(self.clock), str(self.hdisp), str(self.hsyncstart), str(self.hsyncend),
- str(self.htotal), str(self.vdisp), str(self.vsyncstart), str(self.vsyncend), str(self.vtotal)]
-
- for (flag_name,flag_bit) in ModeLine.flags.iteritems():
- if self.flags & flag_bit:
- row.append(flag_name)
- return row
-
- def __str__(self):
- return "ModeLine:"+self.name
-
-############################################################################
-monitor_mode_db_instance = None # Singleton
-
-
-def GetMonitorModeDB():
- """Returns a GetMonitorModeDB instance.
- """
- global monitor_mode_db_instance
- if monitor_mode_db_instance is None:
- monitor_mode_db_instance = MonitorModeDB()
- return monitor_mode_db_instance
-
-############################################################################
-class MonitorModeDB(object):
- def __init__(self):
- self.db = {}
- self.db169 = {}
-
- module_dir = os.path.dirname(os.path.join(os.getcwd(),__file__))
- self.load(os.path.join(data_file_dir,"vesamodes"))
- self.load(os.path.join(data_file_dir,"extramodes"))
- self.load(os.path.join(data_file_dir,"widescreenmodes"))
-
- # Make a list of screen sizes for the getAllResolutions() method.
- self.all_resolutions = []
- for mode in self.db.values()+self.db169.values():
- size = (mode.getWidth(),mode.getHeight())
- if size not in self.all_resolutions:
- self.all_resolutions.append(size)
-
- self.all_resolutions.sort()
-
- def load(self,filename):
- fd = open(filename, 'r')
- lines = fd.readlines()
- fd.close()
-
- for line in lines:
- if line[0] != "#" and line[0] != '/':
- line = line.strip()
- elements = line.split()
- if line!="":
- if len(elements) < 11 or string.lower(elements[0]) != "modeline":
- print "Bad modeline found:",line
- continue
- name = elements[1][1:-1]
- new_mode = ModeLine(elements)
-
- width = new_mode.getWidth()
- height = new_mode.getHeight()
- if self.aspectRatio(width, height)==ModeLine.ASPECT_4_3:
- self.db[name] = new_mode
- else:
- self.db169[name] = new_mode
-
- if (width,height)==FALLBACK_RESOLUTION:
- # We grab these modes and use them a fallbacks in the widescreen list.
- self.db169[name] = new_mode
-
- @staticmethod
- def aspectRatio(width,height):
- ratio = float(width)/float(height)
- # 4/3 is 1.333333
- # 16/9 is 1.777777
- # We will just consider anything below 1.45 to be standard.
- if ratio < 1.45:
- return ModeLine.ASPECT_4_3
- else:
- return ModeLine.ASPECT_16_9
-
- def getAvailableModes(self,monitor,aspect):
- """
- Get the list of video modes that this monitor supports.
-
- Returns a list of modeline objects or None if the available modes for this monitor are unknown.
- """
- if monitor.horizontalsync is None or monitor.verticalsync is None:
- return None
-
- result = []
-
- hsync_list = self._list_from_string(monitor.getHorizontalSync())
- vsync_list = self._list_from_string(monitor.getVerticalSync())
-
- if aspect==ModeLine.ASPECT_4_3:
- db = self.db
- else:
- db = self.db169
-
- for modeline in db.values():
- if modeline.supports(hsync_list, vsync_list):
- result.append(modeline)
- return result
-
- def getAllResolutions(self):
- return self.all_resolutions
-
- def _list_from_string(self,src):
- l = []
- pieces = src.split(",")
- for piece in pieces:
- tmp = string.split(piece, "-")
- if len(tmp) == 1:
- l.append( (float(tmp[0].strip()), float(tmp[0].strip())) )
- else:
- l.append( (float(tmp[0].strip()), float(tmp[1].strip())) )
- return l
-
-############################################################################
-
-def ranges_to_string(array, length):
- stringobj = ""
- for i in range(length):
- r = array[i]
- if stringobj != "":
- stringobj = stringobj + ","
- if r[0] == r[1]:
- stringobj = stringobj + repr(r[0])
- else:
- stringobj = stringobj + repr(r[0]) + "-" + repr(r[1])
- return stringobj
-
-
-def main():
- # FIXME: turns this into a real set of unit tests.
- SetDataFileDir("ldetect-lst")
-
- #xs = XSetup()
- #xs = XSetup('xorg.conf.test')
- xs = XSetup(xorg_config_filename='bug_data/tonio_intel/xorg.conf',
- debug_scan_pci_filename="bug_data/tonio_intel/PCIbus.txt")
- print str(xs)
- return
-
- #screen1 = xs.getGfxCards()[0].getScreens()[0]
- #monitor_db = GetMonitorModelDB()
- #new_model = monitor_db.getMonitorByName('Samsung SyncMaster 15GL')
- #print new_model
- #screen1.setMonitorModel(new_model)
-
- #screen2 = xs.getGfxCards()[0].getScreens()[1]
- #screen2.setMonitorModel(new_model)
-
- print "getAvailableLayouts(): ",xs.getAvailableLayouts()
- xs.getGfxCards()[0].setProprietaryDriver(True)
- print str(xs)
- xs.setLayout(XSetup.LAYOUT_CLONE) # XSetup.LAYOUT_DUAL.
- print "getAvailableLayouts(): ",xs.getAvailableLayouts()
- print str(xs)
-
- #gfxcard_db = GetGfxCardModelDB()
- #new_gfxcard_model = gfxcard_db.getGfxCardModelByName('NVIDIA GeForce FX (generic)')
- ##'ATI Radeon 8500'
- ##'NVIDIA GeForce FX (generic)'
- #print new_gfxcard_model
- #gfx_card = xs.getGfxCards()[0]
- #gfx_card.setProprietaryDriver(False)
- #gfx_card.setGfxCardModel(new_gfxcard_model)
- xs.writeXorgConfig('xorg.conf.test')
-
-if __name__=='__main__':
- main()