<commit_before>import sys
import time
import traceback
import subprocess

import psutil

import ooxcb
from ooxcb.protocol import xproto
from ooxcb.contrib.ewmh import ewmh_get_window_name

# Requires ooxcb and psutil

# TODO nice commandline options


# Disable the screensaver for any video which is currently fullscreen and in foreground
FULLSCREEN_ENOUGH = False
# If above is false, disable for these programs which are in fullscreen (all lower case!)
FULLSCREEN_NAMES = ['chromium', 'mplayer', 'firefox', 'vlc']


_NET_WM_STATE_FULLSCREEN = 352


def enable_screensaver():
    subprocess.check_call(['xset', '+dpms'])
    subprocess.check_call(['xset', 's', 'on'])

def disable_screensaver():
    subprocess.check_call(['xset', '-dpms'])
    subprocess.check_call(['xset', 's', 'off'])


def is_fullscreen(window):
    states = window.get_property('_NET_WM_STATE', 'ATOM').reply().value.to_atoms()
    for atom in states:
        if 'fullscreen' in atom.name.lower():
            return True

def get_pid(window):
    return int(window.get_property('_NET_WM_PID', 'CARDINAL').reply().value[0])


def check(screen):
    window = screen.get_active_window()

    if is_fullscreen(window):
        if FULLSCREEN_ENOUGH:
            return True

        name = ewmh_get_window_name(window).strip()

        if name in ['plugin-container', 'Microsoft Silverlight']:
            return True

        try:
            pid = get_pid(window)
        except ValueError:
            return False

        process = psutil.Process(pid)
        return process.name.lower() in FULLSCREEN_NAMES

    return False


def main():
    def log():
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback.print_exception(exc_type, exc_value, exc_traceback,
                                    limit=None, file=sys.stderr)

    conn = ooxcb.connect()
    screen = conn.setup.roots[conn.pref_screen]
    activated = False

    while True:
        try:
            if check(screen):
                if not activated:
                    disable_screensaver()
                activated = True
            elif activated:
                    enable_screensaver()
                    activated = False
        except KeyboardInterrupt:
            break
        except:
            log()

        time.sleep(180)


if __name__ == '__main__':
    main()<commit_msg>improve code quality, add commandline options<commit_after>import time
import fnmatch
import traceback
import subprocess

try:
    import psutil
except ImportError:
    _HAS_PSUTIL = False
else:
    _HAS_PSUTIL = True

import ooxcb
from ooxcb.util import Mixin
from ooxcb.protocol import xproto
#from ooxcb.protocol import screensaver
from ooxcb.exception import ProtocolException
from ooxcb.contrib.ewmh import ewmh_get_window_name


class ETMVException(Exception):
    pass


def process_name_from_pid(pid):
    if _HAS_PSUTIL:
        try:
            return psutil.Process(pid).name
        except psutil.NoSuchProcess, e:
            raise ETMVException(e.message)

    try:
        return subprocess.check_output(['ps', '-p', str(pid), 'comm=']).strip()
    except subprocess.CalledProcessError, e:
        raise ETMVException(e.message)


_NET_WM_STATE_FULLSCREEN = 352

class WindowMixin(Mixin):
    target_class = xproto.Window

    def is_fullscreen(self):
        ''' Returns True if the Window is in fullscreen mode '''
        repl = self.get_property('_NET_WM_STATE', 'ATOM').reply()
        states = repl.value.to_atoms()
        for atom in states:
            if 'fullscreen' in atom.name.lower():
                return True

    def is_flash(self):
        name = ewmh_get_window_name(self).strip()
        return name in ['plugin-container', 'Microsoft Silverlight']

    def get_pid(self):
        ''' Returns _NET_WM_PID if exists, otherwise 0 '''
        repl = self.get_property('_NET_WM_PID', 'CARDINAL').reply()
        return int(repl.value[0]) if len(repl.value) > 0 else 0

    def get_process_name(self):
        pid = self.get_pid()
        return process_name_from_pid(pid)

WindowMixin.mixin()


class ScreenSaverControl(object):
    DISABLED = 0
    ENABLED = 1

    def __init__(self, connection, fnames=None):
        self.fnames = ['chromium', 'opera', 'firefox', 'mplayer', 'mpv', 'vlc']
        if not fnames is None:
            self.fnames = fnames

        self.connection = connection
        self.screen = connection.setup.roots[connection.pref_screen]
        self.state = ScreenSaverControl.ENABLED

    def run(self, interval=-1):
        if interval <= 0:
            ss = self.connection.core.get_screen_saver().reply()
            interval = (ss.interval-1)/2

        while True:
            self.change_state_if_needed()
            time.sleep(interval)

    def change_state_if_needed(self):
        if self.should_disable():
            if self.state == ScreenSaverControl.ENABLED:
                self.disable_screensaver()
        elif self.state == ScreenSaverControl.DISABLED:
            self.enable_screensaver()

    def should_disable(self):
        current = self.screen.get_active_window()

        if current.is_fullscreen():
            if current.is_flash():
                return True

            try:
                name = current.get_process_name()
            except (ETMVException, ProtocolException):
                return False

            for fn in self.fnames:
                if fnmatch.fnmatch(name, fn):
                    return True
        return False


    # TODO use ooxcb for that, unfortunatly it doesn't support the dpms ext
    def enable_screensaver(self):
        subprocess.check_call(['xset', '+dpms'])
        subprocess.check_call(['xset', 's', 'on'])
        self.state = ScreenSaverControl.ENABLED

    def disable_screensaver(self):
        subprocess.check_call(['xset', '-dpms'])
        subprocess.check_call(['xset', 's', 'off'])
        self.state = ScreenSaverControl.DISABLED


def main():
    import sys
    import argparse

    def log(logfile):
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback.print_exception(exc_type, exc_value, exc_traceback,
                                    limit=None, file=logfile)

    parser = argparse.ArgumentParser(
        description=
            'Disable dpms and screensaver, if the currently active '
            'window is a fullscreen flash window or matches a few criterias.'
    )

    parser.add_argument(
        '--interval', dest='interval',
        type=int, default=-1,
        help='The interval to check if there is a matching window to either '
             'enable or disable the screensaver.'
    )

    parser.add_argument(
        '--name', dest='name',
        action='append', default=None,
        help='Disable the screensaver, if the currently active fullscreen '
             'window belongs to this process (fnmatching supported). '
             'This option can be used multiple times. '
             'Defaults to: chromium, opera, firefox, mplayer, mpv and vlc.'
    )

    parser.add_argument(
        '--display', dest='display',
        default='',
        help='The X display to connect to, if not specified the DISPLAY '
             'environment variable will be used.'
    )

    parser.add_argument(
        '--auth', dest='auth',
        default=None,
        help='Custom authentication cookie used to connect to the display.'
    )

    ns = parser.parse_args()

    connection = ooxcb.connect(ns.display, auth_string=ns.auth)
    ssc = ScreenSaverControl(connection, ns.names)

    try:
        ssc.run(ns.interval)
    except KeyboardInterrupt:
        pass
    except Exception:
        log(sys.stderr)


if __name__ == '__main__':
    main()
{'fraction_non_alphanumeric': 0.09775993784798653, 'fraction_numerical': 0.0027191505891492945, 'mean_word_length': 2.4390026714158504, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3443856', 'n_tokens_mistral': 2321, 'n_tokens_neox': 2236, 'n_words': 581}