parent
74e632e57a
commit
491b51fcb3
@ -1,207 +0,0 @@ |
||||
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 |
@ -1,5 +0,0 @@ |
||||
#!/bin/bash |
||||
cat /dev/stdin | $(cat /dev/stdin > "$1")& |
||||
quit_proc="$!" |
||||
sleep 1 |
||||
kill "$quit_proc" |
@ -1,73 +0,0 @@ |
||||
#!/usr/bin/env python3 |
||||
import argparse |
||||
import time |
||||
import actions |
||||
import pickle |
||||
|
||||
class CreateFileType(argparse.FileType): |
||||
def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None): |
||||
super().__init__(mode, bufsize, encoding, errors) |
||||
self.__mode = mode |
||||
self.__bufsize = bufsize |
||||
self.__encoding = encoding |
||||
self.__errors = errors |
||||
|
||||
def __call__(self, string): |
||||
try: |
||||
return super().__call__(string) |
||||
except argparse.ArgumentTypeError as e: |
||||
return open(string, 'wb' if 'b' in self.__mode else 'w', self.__bufsize, self.__encoding, self.__errors) |
||||
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='Pulseaudio volume manager for xmobar') |
||||
parser.add_argument('output_pipe', type=argparse.FileType('w',bufsize=1)) |
||||
parser.add_argument('command_pipe', type=argparse.FileType('r',bufsize=1)) |
||||
parser.add_argument('--state-file', type=CreateFileType('r+b')) |
||||
|
||||
modules = [ |
||||
actions.QuitControl(), |
||||
actions.ChildReaperControl(), |
||||
actions.RedshiftControl(), |
||||
actions.VolumeControl(), |
||||
] |
||||
|
||||
[m.configure(parser.add_argument_group(m.__class__.__name__)) for m in modules] |
||||
args = parser.parse_args() |
||||
[m.bind_arguments(args) for m in modules] |
||||
|
||||
if args.state_file is not None and args.state_file.readable(): |
||||
try: |
||||
state = pickle.load(args.state_file) |
||||
print(state) |
||||
[m.load_state(state[m.__class__.__name__]) for m in modules if m.enabled and m.__class__.__name__ in state] |
||||
except Exception as e: |
||||
print(e) |
||||
|
||||
|
||||
def output_pipe(fd): |
||||
bars=' | '.join([str(m) for m in modules if m.visible]) |
||||
fd.writelines(bars+"\n") |
||||
|
||||
def command_pipe(fd): |
||||
command = str.rstrip(fd.readline()) |
||||
if len(command) == 0: |
||||
return False |
||||
return any([m.respond_to(command) for m in modules if m.enabled]) |
||||
|
||||
|
||||
try: |
||||
while True: |
||||
if command_pipe(args.command_pipe) or any([m.periodic() for m in modules if m.enabled]): |
||||
output_pipe(args.output_pipe) |
||||
else: |
||||
time.sleep(1) |
||||
finally: |
||||
if args.state_file is not None: |
||||
args.state_file.seek(0) |
||||
args.state_file.truncate() |
||||
state = {m.__class__.__name__: m.dump_state() for m in modules if m.enabled} |
||||
pickle.dump(state, args.state_file) |
||||
args.state_file.close() |
||||
|
||||
[m.cleanup() for m in modules if m.enabled] |
@ -1,21 +0,0 @@ |
||||
import itertools |
||||
import math |
||||
|
||||
def action(command, text, **kwargs): |
||||
return '<action=`{}`{}>{}</action>'.format(command,' '+(' '.join(['{}={}'.format(k, v) for k,v in kwargs.items()])) if len(kwargs) else '', text) |
||||
|
||||
def create_bars(volume): |
||||
num_bars=float(volume)/9000.0 |
||||
return ('/'*math.floor(num_bars))+partial_bar(num_bars-math.floor(num_bars))+(' '*(10-math.ceil(num_bars))) |
||||
|
||||
def partial_bar(bar_size): |
||||
if bar_size == 0.0: |
||||
return '' |
||||
elif bar_size < 0.3: |
||||
return ' ' |
||||
elif bar_size < 0.6: |
||||
return '.' |
||||
elif bar_size < 0.9: |
||||
return '-' |
||||
return '/' |
||||
|
@ -1,36 +0,0 @@ |
||||
#!/bin/bash |
||||
ARGS="$@" |
||||
while [[ -n "$@" ]]; do |
||||
if [[ "${1:0:1}" != "-" ]]; then |
||||
if [[ -z "$volumepipe" ]]; then |
||||
volumepipe="$1" |
||||
elif [[ -z "$commandpipe" ]]; then |
||||
commandpipe="$1" |
||||
fi |
||||
fi |
||||
shift; |
||||
done |
||||
|
||||
|
||||
|
||||
# volumepipe |
||||
if ! [[ -p "$volumepipe" ]]; then |
||||
rm -rf "$volumepipe" |
||||
mkfifo "$volumepipe" |
||||
fi |
||||
|
||||
# volumecontrol |
||||
if [[ -p "$commandpipe" ]]; then |
||||
$(echo "q" > $commandpipe)& |
||||
quit_proc=$! |
||||
sleep 1 |
||||
kill $quit_proc |
||||
rm "$commandpipe" |
||||
else |
||||
rm -f "$commandpipe" |
||||
fi |
||||
|
||||
mkfifo "$commandpipe" |
||||
$(sleep 1; echo "refresh" > $commandpipe)& |
||||
eval set -- "$ARGS" |
||||
exec "$(dirname "${BASH_SOURCE[0]}")/daemon.py" "$@" |
Loading…
Reference in new issue