File: redshift.py

package info (click to toggle)
bumblebee-status 2.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,844 kB
  • sloc: python: 13,430; sh: 68; makefile: 29
file content (120 lines) | stat: -rw-r--r-- 3,866 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# pylint: disable=C0111,R0903

"""Displays the current color temperature of redshift

Requires the following executable:
    * redshift

Parameters:
    * redshift.location : location provider, either of 'auto' (default), 'geoclue2',
      'ipinfo' or 'manual'
      'auto' uses whatever redshift is configured to do
    * redshift.lat : latitude if location is set to 'manual'
    * redshift.lon : longitude if location is set to 'manual'
    * redshift.show_transition: information about the transitions (x% day) defaults to True
    * redshift.adjust: set this to 'true' (defaults to false) to let bumblebee-status adjust color temperature, instead of just showing the current settings
"""

import re
import threading

import core.module
import core.widget
import core.input
import core.decorators

import util.cli
import util.format
import util.location


def get_redshift_value(module):
    widget = module.widget()
    location = module.parameter("location", "auto")
    lat = module.parameter("lat", None)
    lon = module.parameter("lon", None)

    # Even if location method is set to manual, if we have no lat or lon,
    # fall back to the geoclue2 method.
    if location == "manual" and (lat is None or lon is None):
        location = "geoclue2"

    command = ["redshift"]

    if util.format.asbool(module.parameter("adjust", "false")) == True:
        command.extend(["-o", "-v"])
    else:
        command.append("-p")

    if location == "manual":
        command.extend(["-l", "{}:{}".format(lat, lon)])
    if location == "geoclue2":
        command.extend(["-l", "geoclue2"])

    try:
        res = util.cli.execute(" ".join(command))
    except Exception:
        res = ""
    widget.set("temp", "n/a")
    widget.set("transition", "")
    widget.set("state", "day")
    for line in res.split("\n"):
        line = line.lower()
        if "temperature" in line:
            widget.set("temp", line.split(" ")[2].upper())
        if "period" in line:
            state = line.split(" ")[1]
            if "day" in state:
                widget.set("state", "day")
            elif "night" in state:
                widget.set("state", "night")
            else:
                widget.set("state", "transition")
                match = re.search(r"(\d+)\.\d+% ([a-z]+)", line)
                widget.set(
                    "transition", "({}% {})".format(match.group(1), match.group(2))
                )
    core.event.trigger("update", [widget.module.id], redraw_only=True)


class Module(core.module.Module):
    @core.decorators.every(seconds=10)
    def __init__(self, config, theme):
        super().__init__(config, theme, core.widget.Widget(self.text))

        self.__thread = None
        self.show_transition = util.format.asbool(
            self.parameter("show_transition", True)
        )

        if self.parameter("location", "") == "ipinfo":
            # override lon/lat with ipinfo
            try:
                location = util.location.coordinates()
                self.set("lat", location[0])
                self.set("lon", location[1])
                self.set("location", "manual")
            except Exception:
                # Fall back to geoclue2.
                self.set("location", "geoclue2")

        self._text = ""

    def text(self, widget):
        val = widget.get("temp", "n/a")
        transition = widget.get("transition", "")
        if transition and self.show_transition:
            val = "{} {}".format(val, transition)
        return val

    def update(self):
        if self.__thread is not None and self.__thread.is_alive():
            return
        self.__thread = threading.Thread(target=get_redshift_value, args=(self,))
        self.__thread.start()

    def state(self, widget):
        return widget.get("state", None)


# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4