diff options
author | Mattias Andrée <maandree@operamail.com> | 2014-04-10 21:13:05 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2014-04-10 21:13:05 +0200 |
commit | 50127fe432dbec47e8c468eebb5748e1a6018413 (patch) | |
tree | 84f62750a02e80d5083a924e4719d2749b3f1f32 | |
parent | update status atomically (diff) | |
download | nightshift-50127fe432dbec47e8c468eebb5748e1a6018413.tar.gz nightshift-50127fe432dbec47e8c468eebb5748e1a6018413.tar.bz2 nightshift-50127fe432dbec47e8c468eebb5748e1a6018413.tar.xz |
we can tell the daemon to kill or toggle redshift or print its status
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rwxr-xr-x | src/nightshift.py | 104 |
1 files changed, 88 insertions, 16 deletions
diff --git a/src/nightshift.py b/src/nightshift.py index 6cc4473..b5e019a 100755 --- a/src/nightshift.py +++ b/src/nightshift.py @@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import os import sys import socket +import signal import threading from subprocess import Popen, PIPE @@ -201,11 +202,12 @@ red_status, red_running = True, True red_condition = None -def read_status(proc): +def read_status(proc, sock): ''' Read status from redshift - @param proc:Popen The redshift process + @param proc:Popen The redshift process + @param sock:socket The server socket ''' global red_brightness, red_temperature global red_brightnesses, red_temperatures @@ -219,7 +221,7 @@ def read_status(proc): got = got.decode('utf-8', 'replace')[:-1] (key, value) = got.split(': ') if released: - red_condition.aquire() + red_condition.acquire() try: if key == 'Location': red_location = [float(v) for v in value.split(', ')] @@ -255,10 +257,57 @@ def read_status(proc): except: pass if released: - red_condition.aquire() + red_condition.acquire() red_running = False red_condition.notify_all() red_condition.release() + sock.shutdown(socket.SHUT_RDWR) + + +def use_client(sock, proc): + ''' + Communication with client + + @param sock:socket The socket connected to the client + @param proc:Popen The redshift process + ''' + buf = '' + closed = False + while not closed: + got = sock.recv(128).decode('utf-8', 'error') + if (got is None) or (len(got) == 0): + break + buf += got + while '\n' in buf: + buf = buf.split('\n') + message, buf = buf[0], '\n'.join(buf[1:]) + if message == 'status': + red_condition.acquire() + message = 'Current brightness: %f\n' % red_brightness + message += 'Daytime brightness: %f\n' % red_brightnesses[0] + message += 'Night brightness: %f\n' % red_brightnesses[1] + message += 'Current temperature: %f\n' % red_temperature + message += 'Daytime temperature: %f\n' % red_temperatures[0] + message += 'Night temperature: %f\n' % red_temperatures[1] + message += 'Dayness: %f\n' % red_period + message += 'Latitude: %f\n' % red_location[0] + message += 'Longitude: %f\n' % red_location[1] + message += 'Enabled: %s\n' % ('yes' if red_status else 'no') + message += 'Running: %s\n' % ('yes' if red_running else 'no') + sock.sendall(message.encode('utf-8')) + red_condition.release() + pass + elif message == 'toggle': + proc.send_signal(signal.SIGUSR1) + elif message == 'kill': + proc.terminate() + import time + time.sleep(0.1) ## XXX this required for redshift to catch both signals properly + elif message == 'close': + closed = True + elif message == 'listen': + pass ## TODO + sock.close() def run_as_daemon(sock): @@ -267,10 +316,10 @@ def run_as_daemon(sock): @param sock:socket The server socket ''' - global red_condition + global red_condition, red_pid # Create status condition - red_condition = thread.Condition() + red_condition = threading.Condition() # Start redshift command = ['redshift'] + red_opts @@ -279,11 +328,24 @@ def run_as_daemon(sock): proc = Popen(command, stdout = PIPE, stderr = open(os.devnull)) # Read status from redshift - thread = threading.Thread(target = read_status) + thread = threading.Thread(target = read_status, args = (proc, sock)) thread.setDaemon(True) thread.start() - # TODO + red_condition.acquire() + while red_running: + red_condition.release() + try: + (client_sock, _client_address) = sock.accept() + except: + pass # We have shut down the socket so that accept halts + client_thread = threading.Thread(target = use_client, args = (client_sock, proc)) + client_thread.setDaemon(True) + client_thread.start() + red_condition.acquire() + + red_condition.release() + thread.join() if daemon: @@ -292,7 +354,10 @@ if daemon: sys.exit(1) # Create server socket - os.unlink(socket_path) + try: + os.unlink(socket_path) + except: + pass # The fill does (probably) not exist sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.bind(socket_path) sock.listen(5) @@ -336,7 +401,10 @@ if sock is None: os.close(sys.stdout.fileno()) # Create server socket - os.unlink(socket_path) + try: + os.unlink(socket_path) + except: + pass # The fill does (probably) not exist sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.bind(socket_path) sock.listen(5) @@ -373,30 +441,34 @@ if sock is None: # Get redshift status if status: - sock.sendall('status\n') + sock.sendall('status\n'.encode('utf-8')) + sock.sendall('close\n'.encode('utf-8')) while True: got = sock.recv(1024) if (got is None) or (len(got) == 0): break sys.stdout.buffer.write(got) - sys.stdout.buffer.flush() + sys.stdout.buffer.flush() # Temporarily disable or enable redshift if toggle: - sock.sendall('toggle\n') + sock.sendall('toggle\n'.encode('utf-8')) # Kill redshift and the night daemon if kill >= 1: - sock.sendall('kill\n') + sock.sendall('kill\n'.encode('utf-8')) # Kill redshift and the night daemon immediately if kill >= 2: - sock.sendall('kill\n') + sock.sendall('kill\n'.encode('utf-8')) + +if toggle or (kill > 0): + sock.sendall('close\n'.encode('utf-8')) # Start user interface if (kill == 0) and not (status or toggle): - sock.sendall('listen\n') + sock.sendall('listen\n'.encode('utf-8')) pass # TODO |