3 from binascii import hexlify, unhexlify
4 from screen import ScreenSetup, Resolution, RelativeScreenPosition
6 class InvalidDBFile(Exception):
10 def __init__(self, dbfilename):
12 assert(os.path.isdir(os.path.dirname(dbfilename)))
13 if not os.path.isfile(dbfilename):
14 if os.path.lexists(dbfilename):
15 raise Exception("Database must be a file: '%s'" % dbfilename)
16 # database will be created on __enter__ because we need a dbconnection for it
18 self._dbfilename = dbfilename
19 self._connection = None
21 self._connection = sqlite3.connect(self._dbfilename)
24 c.execute("""CREATE TABLE meta (key text, value text, PRIMARY KEY(key))""")
25 c.execute("""INSERT INTO meta VALUES ('version', '1')""")
26 c.execute("""CREATE TABLE known_configs (edid blob, resinternal text, resexternal text, mode text, ext_is_primary integer, PRIMARY KEY(edid))""")
27 # edid in binary format
28 # resindernal, resexternal = "1024x768" or NULL if display is off
29 # mode: the enum text of screen.RelativeScreenPosition or NULL if one display is off
30 else: # check compatibility
31 dbversion = int(self._getMeta("version"))
33 raise InvalidDBFile("Database is too new: Version %d. Please update lilass." % dbversion)
35 def _getMeta(self, key):
37 c.execute("""SELECT value FROM meta WHERE key=?""", (key,))
39 if got is None: # to differentiate between the value being NULL and the row being not there
40 raise KeyError("""Key "%s" is not in the meta table.""" % key)
41 assert c.fetchone() is None # uniqueness
44 def putConfig(self, extconn_edid, conf):
46 b_edid = unhexlify(extconn_edid)
47 intres = conf.intResolution.forDatabase() if conf.intResolution else None
48 extres = conf.extResolution.forDatabase() if conf.extResolution else None
49 mode = conf.relPosition.text if conf.relPosition else None
50 extprim = int(conf.extIsPrimary) # False => 0, True => 1
51 c.execute("""INSERT OR REPLACE INTO known_configs VALUES (?,?,?,?,?)""", (b_edid, intres, extres, mode, extprim))
52 def getConfig(self, extconn_edid):
54 b_edid = unhexlify(extconn_edid)
55 c.execute("""SELECT * FROM known_configs WHERE edid=?""", (b_edid,))
59 assert c.fetchone() is None # uniqueness
60 _, intres, extres, mode, extprim = result
61 intres = Resolution.fromDatabase(intres) # this method is safe for NULLs
62 extres = Resolution.fromDatabase(extres)
63 mode = RelativeScreenPosition(mode) if mode else None
64 extprim = bool(extprim) # 0 => False, 1 => True
65 return ScreenSetup(intres, extres, mode, extprim)
66 def __exit__(self, type, value, tb):
68 self._connection.commit()
69 self._connection.close()
71 assert(self._connection)
72 return self._connection.cursor()