My Qtile window manager configuration
git clone https://github.com/m-col/qtile-config
Files | Refs | Readme

-rw-r--r-- mindfulness.py


      1 # Copyright (c) 2022 Matt Colligan
      2 #
      3 # Permission is hereby granted, free of charge, to any person obtaining a copy
      4 # of this software and associated documentation files (the "Software"), to deal
      5 # in the Software without restriction, including without limitation the rights
      6 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      7 # copies of the Software, and to permit persons to whom the Software is
      8 # furnished to do so, subject to the following conditions:
      9 #
     10 # The above copyright notice and this permission notice shall be included in
     11 # all copies or substantial portions of the Software.
     12 #
     13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     18 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     19 # SOFTWARE.
     20 
     21 import os
     22 from random import randint
     23 from urllib import request
     24 
     25 import gi
     26 
     27 gi.require_version("Gst", "1.0")
     28 from gi.repository import Gst
     29 from libqtile.log_utils import logger
     30 from libqtile.utils import get_cache_dir
     31 from libqtile.widget import base
     32 
     33 Gst.init(None)
     34 
     35 
     36 class ReMindfulness(base.ThreadPoolText):
     37     """
     38     Mindfulness reminder widget (Proof of concept / work in progress)
     39 
     40     Inspired by Kyle MacLeod's mindfulnotifier Android app
     41     (https://github.com/kmac/mindfulnotifier). The widget will periodically play a
     42     calming tone at semi-random intervals.
     43 
     44     Note, if the specified audio_file does not exist (i.e. the first time the widget is
     45     configured, leaving the default value for ``audio_file``), one will be downloaded.
     46     It is fetched via the mindfulnotifier app's github repository.
     47     """
     48 
     49     default_path = os.path.join(get_cache_dir(), "tibetan_bell_ding_b.mp3")
     50     default_url = "https://github.com/kmac/mindfulnotifier/raw/master/media/tibetan_bell_ding_b.mp3"
     51 
     52     defaults = [
     53         ("audio_file", default_path, "Lower bound for the interval between reminders"),
     54         ("interval_minimum", 60 * 60, "Lower bound for the interval between reminders"),
     55         ("interval_maximum", 90 * 60, "Upper bound for the interval between reminders"),
     56         ("reminder_background", "ff0000", "Background colour when reminding"),
     57         ("reminder_foreground", "ff0000", "Foreground colour when reminding"),
     58         ("reminder_duration", 5, "Duration of reminders (i.e. for appearance change)"),
     59         ("reminder_text", None, "Text"),
     60     ]
     61 
     62     def __init__(self, text="", **config):
     63         base.ThreadPoolText.__init__(self, text, **config)
     64         self.add_defaults(ReMindfulness.defaults)
     65         self._just_started = True
     66         self._original_foreground = self.foreground
     67         self._original_background = self.background
     68 
     69         self.add_callbacks(
     70             {
     71                 "Button1": self._reset_colours,
     72             }
     73         )
     74 
     75     def _configure(self, qtile, bar):
     76         self._just_started = not self.configured
     77         base.ThreadPoolText._configure(self, qtile, bar)
     78 
     79     def poll(self):
     80         self.update_interval = randint(self.interval_minimum, self.interval_maximum)
     81 
     82         if self._just_started:
     83             return self.text
     84 
     85         if not os.path.exists(self.audio_file):
     86             logger.info("Downloading default tone for ReMindfulness widget")
     87             request.urlretrieve(self.default_url, self.audio_file)
     88 
     89         playbin = Gst.ElementFactory.make("playbin", "playbin")
     90         playbin.props.uri = "file://" + self.audio_file
     91         playbin.set_state(Gst.State.PLAYING)
     92 
     93         self.foreground = self.reminder_foreground
     94         self.background = self.reminder_background
     95         self.timeout_add(self.reminder_duration, self._reset_colours)
     96 
     97         return self.text
     98 
     99     def _reset_colours(self):
    100         self.foreground = self._original_foreground
    101         self.background = self._original_background
    102