You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.8 KiB
207 lines
5.8 KiB
import functions
|
|
import subprocess
|
|
import abc
|
|
import sys
|
|
import os.path
|
|
|
|
class AbstractControl(metaclass=abc.ABCMeta):
|
|
def __init__(self):
|
|
self.args = None
|
|
|
|
@property
|
|
def visible(self):
|
|
return self.enabled
|
|
|
|
@property
|
|
def enabled(self):
|
|
return True
|
|
|
|
def configure(self, argument_parser):
|
|
pass
|
|
|
|
def bind_arguments(self, args):
|
|
self.args = args
|
|
|
|
def periodic(self):
|
|
pass
|
|
|
|
def cleanup(self):
|
|
pass
|
|
|
|
def respond_to(self, command):
|
|
return False
|
|
|
|
def load_state(self, state):
|
|
pass
|
|
|
|
def dump_state(self):
|
|
return None
|
|
|
|
def create_pipe_command(self, command):
|
|
return 'echo {} | {}/command.sh {}'.format(command, os.path.abspath(sys.path[0]), os.path.abspath(self.args.command_pipe.name))
|
|
|
|
|
|
|
|
class VolumeControl(AbstractControl):
|
|
|
|
@property
|
|
def muted(self):
|
|
return self._muted
|
|
|
|
@muted.setter
|
|
def muted(self, muted):
|
|
if self._muted != muted:
|
|
try:
|
|
self._muted = muted
|
|
self._pactl('set-sink-mute', str(int(muted)))
|
|
except subprocess.CalledProcessError as e:
|
|
pass
|
|
|
|
@property
|
|
def volume(self):
|
|
return self._volume
|
|
|
|
@volume.setter
|
|
def volume(self, volume):
|
|
if self.muted:
|
|
self.muted = False
|
|
if self._volume != volume:
|
|
try:
|
|
self._volume = volume
|
|
self._pactl('set-sink-volume', str(volume))
|
|
except subprocess.CalledProcessError as e:
|
|
pass
|
|
|
|
def _pactl(self, command, arg):
|
|
for i in range(6):
|
|
subprocess.check_call(["pactl", command, str(i), arg])
|
|
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._muted = False
|
|
self._volume = 0
|
|
|
|
def respond_to(self, command):
|
|
if command[0] == '=':
|
|
self.volume = int(command[1:])*9000
|
|
elif command == 'm1':
|
|
self.muted = True
|
|
elif command == 'm0':
|
|
self.muted = False
|
|
elif command == 'mt':
|
|
self.muted = not self.muted
|
|
elif command == '+':
|
|
self.volume+=3000
|
|
elif command == '-':
|
|
self.volume-=3000
|
|
elif command == 'r':
|
|
self.volume=30000
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
def __str__(self):
|
|
return self.action_bars(functions.create_bars(self.volume) if not self.muted else ' (mute) ')
|
|
|
|
def action_bars(self, bars):
|
|
return ''.join([functions.action(self.create_pipe_command('=%d'%(i+1)), c, button=1) for i,c in zip(range(len(bars)), bars)])
|
|
|
|
def load_state(self, state):
|
|
self.volume = state['volume']
|
|
self.muted = state['muted']
|
|
|
|
def dump_state(self):
|
|
return dict(volume=self.volume, muted=self.muted)
|
|
|
|
class QuitControl(AbstractControl):
|
|
@property
|
|
def visible(self):
|
|
return False
|
|
|
|
def respond_to(self, command):
|
|
if command == 'q':
|
|
sys.exit(0)
|
|
elif command == 'refresh':
|
|
return True
|
|
|
|
class RedshiftControl(AbstractControl):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._redshift_proc = None
|
|
|
|
def configure(self, argument_parser):
|
|
argument_parser.add_argument('--redshift-enabled', help='Use the redshift module', action='store_true')
|
|
argument_parser.add_argument('--redshift-location', help='LAT:LON Your current location', type=str)
|
|
argument_parser.add_argument('--redshift-temperature', help='DAY:NIGHT Color temperature to set at daytime/night', type=str)
|
|
|
|
def bind_arguments(self, args):
|
|
super().bind_arguments(args)
|
|
if self.enabled and not self.redshift_error_message:
|
|
self.redshift_enabled = True
|
|
|
|
@property
|
|
def enabled(self):
|
|
return self.args.redshift_enabled
|
|
|
|
@property
|
|
def redshift_enabled(self):
|
|
return bool(self._redshift_proc)
|
|
|
|
@property
|
|
def redshift_error_message(self):
|
|
if self.enabled and not (self.args.redshift_location or self.args.redshift_temperature):
|
|
return "Missing parameter(s) --redshift-location and/or --redshift-temperature"
|
|
if self._redshift_proc is not None and self._redshift_proc.returncode is not None and self._redshift_proc.returncode != 0:
|
|
return self._redshift_proc.communicate()[1].replace("\n", ' ')
|
|
return None
|
|
|
|
|
|
@redshift_enabled.setter
|
|
def redshift_enabled(self, value):
|
|
if value == self.redshift_enabled:
|
|
return
|
|
if value:
|
|
self._redshift_proc = subprocess.Popen(['redshift', '-l', self.args.redshift_location, '-t', self.args.redshift_temperature], )
|
|
else:
|
|
self._redshift_proc.terminate()
|
|
|
|
def periodic(self):
|
|
if self._redshift_proc:
|
|
self._redshift_proc.poll()
|
|
if self._redshift_proc.returncode is not None:
|
|
self._redshift_proc = None
|
|
return True
|
|
|
|
def respond_to(self, command):
|
|
if command == 'redshift':
|
|
self.redshift_enabled = not self.redshift_enabled
|
|
return True
|
|
return False
|
|
|
|
def cleanup(self):
|
|
self.redshift_enabled = False
|
|
if self._redshift_proc:
|
|
self._redshift_proc.wait()
|
|
|
|
def __str__(self):
|
|
if not self.redshift_error_message:
|
|
return functions.action(self.create_pipe_command('redshift'), 'R' if self.redshift_enabled else 'r')
|
|
return 'E: '+self.redshift_error_message
|
|
|
|
def load_state(self, state):
|
|
self.redshift_enabled = state['redshift_enabled']
|
|
|
|
def dump_state(self):
|
|
return {'redshift_enabled': self.redshift_enabled}
|
|
|
|
class ChildReaperControl(AbstractControl):
|
|
@property
|
|
def visible(self):
|
|
return False
|
|
|
|
def periodic(self):
|
|
try:
|
|
os.wait3(os.WNOHANG)
|
|
except:
|
|
pass
|
|
|