Merge branch 'master' of git://ralfj.de/dsl
authorRalf Jung <post@ralfj.de>
Sat, 6 Oct 2012 10:39:15 +0000 (12:39 +0200)
committerRalf Jung <post@ralfj.de>
Sat, 6 Oct 2012 10:39:15 +0000 (12:39 +0200)
1  2 
dsl.py

diff --combined dsl.py
index dad969abdaebe9cce52044fa99d4703d1af4906b,396468d5bfca273ac8058b3cd980ea307c92e944..c7ea0f9ad333dc0d249edc4eacd4f66ca6f1afd2
--- 1/dsl.py
--- 2/dsl.py
+++ b/dsl.py
  # along with this program (gpl.txt); if not, write to the Free Software
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  
 -import os, sys, re, subprocess
 -from PyQt4 import QtGui
 +import os, re, subprocess
  from selector_window import PositionSelection
 -app = QtGui.QApplication(sys.argv)
 +import gui
  
  # for auto-config: common names of internal connectors
- commonInternalConnectorNames = ['LVDS', 'LVDS1']
+ commonInternalConnectorNames = ['LVDS', 'LVDS0', 'LVDS1', 'LVDS-0', 'LVDS-1']
  
  # Load a section-less config file: maps parameter names to space-separated lists of strings (with shell quotation)
  def loadConfigFile(file):
@@@ -42,7 -43,7 +42,7 @@@
                                curKey = line[:pos].strip()
                                result[curKey] = shlex.split(line[pos+1:]) # shlex.split also strips
                        except Exception:
 -                              raise Exception("Invalid config, line %d: Error parsing line (quoting issue?)" % linenr)
 +                              raise Exception("Invalid config, line %d: Error parsing line (quoting issue?)." % linenr)
        # add some convencience get functions
        return result
  
@@@ -51,8 -52,11 +51,11 @@@ def getXrandrInformation()
        connectors = {} # map of connector names to a list of resolutions
        connector = None # current connector
        for line in p.stdout:
+               # ignore screens
+               if line.startswith("Screen"):
+                       continue
                # new connector?
-               m = re.search(r'^([\w]+) (dis)?connected ', line)
+               m = re.search(r'^([\w\-]+) (dis)?connected ', line)
                if m is not None:
                        connector = m.groups()[0]
                        assert connector not in connectors
@@@ -64,7 -68,7 +67,7 @@@
                        assert connector is not None
                        connectors[connector].append((int(m.groups()[0]), int(m.groups()[1])))
        p.communicate()
 -      if p.returncode != 0: raise Exception("Querying xrandr for data failed")
 +      if p.returncode != 0: raise Exception("Querying xrandr for data failed.")
        return connectors
  
  def res2xrandr(res):
@@@ -89,81 -93,71 +92,81 @@@ def findAvailableConnector(tryConnector
                        return connector
        return None
  
 -# load connectors and options
 -connectors = getXrandrInformation()
 -config = loadConfigFile(os.getenv('HOME') + '/.dsl.conf')
 -# find internal connector
 -if 'internalConnector' in config:
 -      if len(config['internalConnector']) != 1:
 -              raise Exception("You must specify exactly one internal connector")
 -      internalConnector = config['internalConnector'][0]
 -      if not internalConnector in connectors:
 -              raise Exception("Connector %s does not exist, there is an error in your config file" % internalConnector)
 -else:
 -      # auto-config
 -      internalConnector = findAvailableConnector(commonInternalConnectorNames)
 -      if internalConnector is None:
 -              raise Exception("Could not automatically find internal connector, please use ~/.dsl.conf to specify it manually")
 -# all the rest is external then, obviously - unless the user wants to do that manually
 -if 'externalConnectors' in config:
 -      externalConnectors = config['externalConnectors']
 -      for connector in externalConnectors:
 -              if not connector in connectors:
 -                      raise Exception("Connector %s does not exist, there is an error in your config file" % internalConnector)
 -else:
 -      externalConnectors = connectors.keys()
 -      externalConnectors.remove(internalConnector)
 -if not externalConnectors:
 -      raise Exception("No external connector found - either your config is wrong, or your machine has only one connector")
 +# the main function
 +def main():
 +      # load connectors and options
 +      connectors = getXrandrInformation()
 +      config = loadConfigFile(os.getenv('HOME') + '/.dsl.conf')
 +      # find internal connector
 +      if 'internalConnector' in config:
 +              if len(config['internalConnector']) != 1:
 +                      raise Exception("You must specify exactly one internal connector.")
 +              internalConnector = config['internalConnector'][0]
 +              if not internalConnector in connectors:
 +                      raise Exception("Connector %s does not exist, there is an error in your config file." % internalConnector)
 +      else:
 +              # auto-config
 +              internalConnector = findAvailableConnector(commonInternalConnectorNames)
 +              if internalConnector is None:
 +                      raise Exception("Could not automatically find internal connector, please use ~/.dsl.conf to specify it manually.")
 +      # all the rest is external then, obviously - unless the user wants to do that manually
 +      if 'externalConnectors' in config:
 +              externalConnectors = config['externalConnectors']
 +              for connector in externalConnectors:
 +                      if not connector in connectors:
 +                              raise Exception("Connector %s does not exist, there is an error in your config file." % internalConnector)
 +      else:
 +              externalConnectors = connectors.keys()
 +              externalConnectors.remove(internalConnector)
 +      if not externalConnectors:
 +              raise Exception("No external connector found - either your config is wrong, or your machine has only one connector.")
  
 -# default: screen off
 -args = {} # maps connector names to xrand arguments
 -for c in externalConnectors+[internalConnector]:
 -      args[c] = ["--off"]
 +      # default: screen off
 +      args = {} # maps connector names to xrand arguments
 +      for c in externalConnectors+[internalConnector]:
 +              args[c] = ["--off"]
  
 -# Check what to do
 -usedExternalConnector = findAvailableConnector(externalConnectors) # *the* external connector which is actually used
 -if usedExternalConnector is not None: # there's an external screen connected, we need to ask what to do
 -      internalResolutions = connectors[internalConnector]
 -      externalResolutions = connectors[usedExternalConnector]
 -      extPosition = PositionSelection(usedExternalConnector, map(res2user, internalResolutions), map(res2user, externalResolutions))
 -      extPosition.exec_()
 -      if not extPosition.result(): sys.exit(1) # the user canceled
 -      extResolution = res2xrandr(externalResolutions[extPosition.extResolutions.currentIndex()])
 -      intResolution = res2xrandr(internalResolutions[extPosition.intResolutions.currentIndex()])
 -      # build command-line
 -      args[usedExternalConnector] = ["--mode", extResolution] # set external screen to desired resolution
 -      if extPosition.extOnly.isChecked():
 -              args[usedExternalConnector] += ["--primary"]
 -      else:
 -              # there are two screens
 -              args[internalConnector] = ["--mode", intResolution] # set internal screen to desired resolution
 -              # set position
 -              if extPosition.posLeft.isChecked():
 -                      args[usedExternalConnector] += ["--left-of", internalConnector]
 -              else:
 -                      args[usedExternalConnector] += ["--right-of", internalConnector]
 -              # set primary screen
 -              if extPosition.primExt.isChecked():
 +      # Check what to do
 +      usedExternalConnector = findAvailableConnector(externalConnectors) # *the* external connector which is actually used
 +      if usedExternalConnector is not None: # there's an external screen connected, we need to ask what to do
 +              internalResolutions = connectors[internalConnector]
 +              externalResolutions = connectors[usedExternalConnector]
 +              extPosition = PositionSelection(usedExternalConnector, map(res2user, internalResolutions), map(res2user, externalResolutions))
 +              extPosition.exec_()
 +              if not extPosition.result(): sys.exit(1) # the user canceled
 +              extResolution = res2xrandr(externalResolutions[extPosition.extResolutions.currentIndex()])
 +              intResolution = res2xrandr(internalResolutions[extPosition.intResolutions.currentIndex()])
 +              # build command-line
 +              args[usedExternalConnector] = ["--mode", extResolution] # set external screen to desired resolution
 +              if extPosition.extOnly.isChecked():
                        args[usedExternalConnector] += ["--primary"]
                else:
 -                      args[internalConnector] += ["--primary"]
 -else:
 -      # use first resolution
 -      args[internalConnector] = ["--mode", res2xrandr(connectors[internalConnector][0]), "--primary"]
 -# and do it
 -call = ["xrandr"]
 -for name in args:
 -      call += ["--output", name] + args[name]
 -print "Call that will be made:",call
 -subprocess.check_call(call)
 +                      # there are two screens
 +                      args[internalConnector] = ["--mode", intResolution] # set internal screen to desired resolution
 +                      # set position
 +                      if extPosition.posLeft.isChecked():
 +                              args[usedExternalConnector] += ["--left-of", internalConnector]
 +                      else:
 +                              args[usedExternalConnector] += ["--right-of", internalConnector]
 +                      # set primary screen
 +                      if extPosition.primExt.isChecked():
 +                              args[usedExternalConnector] += ["--primary"]
 +                      else:
 +                              args[internalConnector] += ["--primary"]
 +      else:
 +              # use first resolution
 +              args[internalConnector] = ["--mode", res2xrandr(connectors[internalConnector][0]), "--primary"]
 +      # and do it
 +      call = ["xrandr"]
 +      for name in args:
 +              call += ["--output", name] + args[name]
 +      print "Call that will be made:",call
 +      subprocess.check_call(call)
 +
 +# if we run top-level
 +if __name__ == "__main__":
 +      try:
 +              main()
 +      except Exception as e:
 +              gui.error(str(e))
 +              raise