~jocave/checkbox/hybrid-amd-gpu-mods

« back to all changes in this revision

Viewing changes to providers/plainbox-provider-checkbox/bin/xrandr_cycle

  • Committer: Zygmunt Krynicki
  • Date: 2013-05-17 13:54:25 UTC
  • mto: This revision was merged to the branch mainline in revision 2130.
  • Revision ID: zygmunt.krynicki@canonical.com-20130517135425-cxcenxx5t0qrtbxd
checkbox-ng: add CheckBoxNG sub-project

CheckBoxNG (or lowercase as checkbox-ng, pypi:checkbox-ng) is a clean
implementation of CheckBox on top of PlainBox. It provides a new
executable, 'checkbox' that has some of the same commands that were
previously implemented in the plainbox package.

In particular CheckBoxNG comes with the 'checkbox sru' command
(the same one as in plainbox). Later on this sub-command will be removed
from plainbox.

CheckBoxNG depends on plainbox >= 0.3

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python3
2
 
 
3
 
import argparse
4
 
import errno
5
 
import os
6
 
import re
7
 
import shutil
8
 
import subprocess
9
 
import sys
10
 
import tarfile
11
 
import time
12
 
 
13
 
parser = argparse.ArgumentParser()
14
 
parser.add_argument('--keyword', default='',
15
 
                    help=('A keyword to distinguish the screenshots '
16
 
                          'taken in this run of the script'))
17
 
parser.add_argument('--screenshot-dir',
18
 
                    default=os.environ['HOME'],
19
 
                    help=('Specify a directory to store screenshots in. '
20
 
                          'Default is %(default)s'))
21
 
args = parser.parse_args()
22
 
 
23
 
 
24
 
device_context = ''    # track what device's modes we are looking at
25
 
modes = []             # keep track of all the devices and modes discovered
26
 
current_modes = []     # remember the user's current settings for cleanup later
27
 
failures = 0           # count the number of failed modesets
28
 
failure_messages = []  # remember which modes failed
29
 
success_messages = []  # remember which modes succeeded
30
 
 
31
 
# Run xrandr and ask it what devices and modes are supported
32
 
xrandrinfo = subprocess.Popen('xrandr -q', shell=True, stdout=subprocess.PIPE)
33
 
output = xrandrinfo.communicate()[0].decode().split('\n')
34
 
 
35
 
 
36
 
# The results from xrandr are given in terms of the available display devices.
37
 
# One device can have zero or more associated modes.  Unfortunately xrandr
38
 
# indicates this through indentation and is kinda wordy, so we have to keep
39
 
# track of the context we see mode names in as we parse the results.
40
 
 
41
 
for line in output:
42
 
    # I haven't seen any blank lines in xrandr's output in my tests, but meh
43
 
    if line == '':
44
 
        break
45
 
 
46
 
    # luckily the various data from xrandr are separated by whitespace...
47
 
    foo = line.split()
48
 
 
49
 
    # Check to see if the second word in the line indicates a new context
50
 
    #  -- if so, keep track of the context of the device we're seeing
51
 
    if len(foo) >= 2:  # throw out any weirdly formatted lines
52
 
        if foo[1] == 'disconnected':
53
 
            # we have a new context, but it should be ignored
54
 
            device_context = ''
55
 
        if foo[1] == 'connected':
56
 
            # we have a new context that we want to test
57
 
            device_context = foo[0]
58
 
        elif device_context != '':  # we've previously seen a 'connected' dev
59
 
            # mode names seem to always be of the format [horiz]x[vert]
60
 
            # (there can be non-mode information inside of a device context!)
61
 
            if foo[0].find('x') != -1:
62
 
                modes.append((device_context, foo[0]))
63
 
            # we also want to remember what the current mode is, which xrandr
64
 
            # marks with a '*' character, so we can set things back the way
65
 
            # we found them at the end:
66
 
            if foo[1].find('*') != -1:
67
 
                current_modes.append((device_context, foo[0]))
68
 
 
69
 
# Now we have a list of the modes we need to test.  So let's do just that.
70
 
profile_path = os.environ['HOME'] + '/.shutter/profiles/'
71
 
screenshot_path = os.path.join(args.screenshot_dir, 'xrandr_screens')
72
 
 
73
 
# Where to find the shutter.xml template? Two possible locations.
74
 
shutter_xml_template = None
75
 
 
76
 
if 'PLAINBOX_PROVIDER_DATA' in os.environ:
77
 
    shutter_xml_template = os.path.join(os.environ['PLAINBOX_PROVIDER_DATA'],
78
 
                                        "settings", "shutter.xml")
79
 
else:
80
 
    shutter_xml_template = os.path.join(os.path.split(os.path.dirname(
81
 
                                        os.path.realpath(__file__)))[0],
82
 
                                       "data",
83
 
                                        "settings",
84
 
                                        "shutter.xml")
85
 
 
86
 
if args.keyword:
87
 
    screenshot_path = screenshot_path + '_' + args.keyword
88
 
 
89
 
regex = re.compile(r'filename="[^"\r\n]*"')
90
 
 
91
 
# Keep the shutter profile in place before starting
92
 
 
93
 
# Any errors creating the directories or copying the template is fatal,
94
 
# since things won't work if we fail.
95
 
try:
96
 
    os.makedirs(profile_path, exist_ok=True)
97
 
    os.makedirs(screenshot_path, exist_ok=True)
98
 
except OSError as excp:
99
 
    raise SystemExit("ERROR: Unable to create "
100
 
                     "required directories: {}".format(excp))
101
 
 
102
 
try:
103
 
    shutil.copy(shutter_xml_template, profile_path)
104
 
except (IOError, OSError) as excp:
105
 
    print("ERROR: Unable to copy {} to {}: {}".format(shutter_xml_template,
106
 
                                                      profile_path,
107
 
                                                      excp))
108
 
    if excp.errno == errno.ENOENT:
109
 
        print("Try setting PLAINBOX_PROVIDER_DATA to the the data path of a")
110
 
        print("provider shipping the 'shutter.xml' template file, usually ")
111
 
        print("found under /usr/share.")
112
 
    raise SystemExit()
113
 
 
114
 
try:
115
 
    old_profile = open(profile_path + 'shutter.xml', 'r')
116
 
    content = old_profile.read()
117
 
    new_profile = open(profile_path + 'shutter.xml', 'w')
118
 
    # Replace the folder name with the desired one
119
 
    new_profile.write(re.sub(r'folder="[^"\r\n]*"',
120
 
                             'folder="%s"' % screenshot_path, content))
121
 
    new_profile.close()
122
 
    old_profile.close()
123
 
except:
124
 
    raise SystemExit("ERROR: While updating folder name "
125
 
                     "in shutter profile: {}".format(sys.exc_info()))
126
 
 
127
 
for mode in modes:
128
 
    cmd = 'xrandr --output ' + mode[0] + ' --mode ' + mode[1]
129
 
    retval = subprocess.call(cmd, shell=True)
130
 
    if retval != 0:
131
 
        failures = failures + 1
132
 
        message = 'Failed to set mode ' + mode[1] + ' for output ' + mode[0]
133
 
        failure_messages.append(message)
134
 
    else:
135
 
        # Update shutter profile to save the image as the right name
136
 
        mode_string = mode[0] + '_' + mode[1]
137
 
 
138
 
        try:
139
 
            old_profile = open(profile_path + 'shutter.xml', 'r')
140
 
            content = old_profile.read()
141
 
            new_profile = open(profile_path + 'shutter.xml', 'w')
142
 
            new_profile.write(regex.sub('filename="%s"' % mode_string,
143
 
                              content))
144
 
            new_profile.close()
145
 
            old_profile.close()
146
 
 
147
 
            shuttercmd = ['shutter', '--profile=shutter', '--full', '-e']
148
 
            retval = subprocess.call(shuttercmd, shell=False)
149
 
 
150
 
            if retval != 0:
151
 
                print("""Could not capture screenshot -
152
 
                         you may need to install the package 'shutter'.""")
153
 
 
154
 
        except:
155
 
            print("""Could not configure screenshot tool -
156
 
                     you may need to install the package 'shutter',
157
 
                     or check that {}/{} exists and is writable.""".format(
158
 
                profile_path,
159
 
                'shutter.xml'))
160
 
 
161
 
        message = 'Set mode ' + mode[1] + ' for output ' + mode[0]
162
 
        success_messages.append(message)
163
 
    time.sleep(3)  # let the hardware recover a bit
164
 
 
165
 
# Put things back the way we found them
166
 
 
167
 
for mode in current_modes:
168
 
    cmd = 'xrandr --output ' + mode[0] + ' --mode ' + mode[1]
169
 
    subprocess.call(cmd, shell=True)
170
 
 
171
 
# Tar up the screenshots for uploading
172
 
try:
173
 
    with tarfile.open(screenshot_path + '.tgz', 'w:gz') as screen_tar:
174
 
        for screen in os.listdir(screenshot_path):
175
 
            screen_tar.add(screenshot_path + '/' + screen, screen)
176
 
except:
177
 
    pass
178
 
 
179
 
# Output some fun facts and knock off for the day
180
 
 
181
 
for message in failure_messages:
182
 
    print(message, file=sys.stderr)
183
 
 
184
 
for message in success_messages:
185
 
    print(message)
186
 
 
187
 
if failures != 0:
188
 
    exit(1)
189
 
else:
190
 
    exit(0)