diff options
author | Mattias Andrée <maandree@operamail.com> | 2014-05-16 18:43:26 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2014-05-16 18:48:31 +0200 |
commit | 7680d6d24de9b049dfe8f322bf97fec820734fb9 (patch) | |
tree | 9c3841509480af9374e93920903438e93b1d9068 | |
parent | do not toggle when dying (diff) | |
download | nightshift-7680d6d24de9b049dfe8f322bf97fec820734fb9.tar.gz nightshift-7680d6d24de9b049dfe8f322bf97fec820734fb9.tar.bz2 nightshift-7680d6d24de9b049dfe8f322bf97fec820734fb9.tar.xz |
m misc + add freeze/thaw
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r-- | examples/x-window-focus | 5 | ||||
-rwxr-xr-x | src/__main__.py | 130 | ||||
-rw-r--r-- | src/completion | 4 | ||||
-rw-r--r-- | src/interface.py | 61 |
4 files changed, 154 insertions, 46 deletions
diff --git a/examples/x-window-focus b/examples/x-window-focus index e08442e..9d341ff 100644 --- a/examples/x-window-focus +++ b/examples/x-window-focus @@ -29,6 +29,9 @@ import threading import Xlib.display +# TODO: cannot re-exec when this script is used +# TODO: does not wait with toggling of redshift is froozen + def x_window_focus_thread_function(proc): ''' @@ -95,7 +98,7 @@ def x_window_focus_thread_function(proc): should_be_disabled = True # Perhaps toggle - if red_running and (should_be_disabled == red_status) and not red_dying: + if red_running and (should_be_disabled == red_status) and (not red_dying) and (not red_froozen): if red_status or we_disabled: we_disabled = should_be_disabled proc.send_signal(signal.SIGUSR1) diff --git a/src/__main__.py b/src/__main__.py index 0cd3aef..e965bce 100755 --- a/src/__main__.py +++ b/src/__main__.py @@ -99,6 +99,16 @@ toggle = False :bool Whether or not to toggle redshift ''' +set_status = None +''' +:bool? `True` if redshift should be enabled, `False` for disble, otherwise `None` +''' + +set_freeze = None +''' +:bool? `True` if redshift should be froozen, `False` for thawed, otherwise `None` +''' + status = False ''' :bool Whether or not to get the current status @@ -163,6 +173,10 @@ for arg in sys.argv[1:]: -d --daemon Start as daemon -x --reset --kill Remove adjustment from screen +x --toggle Temporarily disable or enable adjustments + +d --disable Temporarily disable adjustments + +e --enable Re-enable adjustments + +f --freeze Temporarily freeze the redshift process + +t --thaw Thaw the redshift process -s --status Print status information +c --script FILE Load nightshift configuration script from specified file @@ -190,6 +204,7 @@ for arg in sys.argv[1:]: subargs = [arg] if arg.startswith('-') and not arg.startswith('--'): subargs = ['-' + letter for letter in arg[1:]] elif arg.startswith('+') and not arg.startswith('++'): subargs = ['+' + letter for letter in arg[1:]] + elif arg.startswith('=') and not arg.startswith('=='): subargs = ['=' + letter for letter in arg[1:]] red_arg = '' for arg in subargs: if (add_to_red_opts is None) or add_to_red_opts: @@ -198,9 +213,13 @@ for arg in sys.argv[1:]: elif isinstance(config_file, list): config_file.append(arg) elif arg in ('-d', '--daemon'): daemon = 1 - elif arg in ('+d', '++daemon'): daemon = 2 + elif arg in ('=d', '==daemon'): daemon = 2 elif arg in ('-x', '--reset', '--kill'): kill += 1 elif arg in ('+x', '--toggle'): toggle = True + elif arg in ('+d', '--disable'): set_status = False + elif arg in ('+e', '--enable'): set_status = True + elif arg in ('+f', '--freeze'): set_freeze = True + elif arg in ('+t', '--thaw'): set_freeze = False elif arg in ('-s', '--status'): status = True elif arg in ('+c', '--script'): config_file = [] else: @@ -258,7 +277,7 @@ The pathname of the interprocess communication socket for nightshift red_brightness, red_temperature = 1, 6500 red_brightnesses, red_temperatures = (1, 1), (5500, 3500) red_period, red_location = 1, (0, 0) -red_status, red_running, red_dying = True, True, False +red_status, red_running, red_dying, red_froozen = True, True, False, False red_condition = None @@ -338,18 +357,19 @@ def generate_status_message(): @return :str Status message ''' - 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 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') - message += 'Dying: %s\n' % ('yes' if red_dying else 'no') + 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') + message += 'Dying: %s\n' % ('yes' if red_dying else 'no') + message += 'Froozen: %s\n' % ('yes' if red_froozen else 'no') return message @@ -360,7 +380,7 @@ def use_client(sock, proc): @param sock:socket The socket connected to the client @param proc:Popen The redshift process ''' - global red_dying + global red_dying, red_froozen buf = '' closed = False while not closed: @@ -380,8 +400,28 @@ def use_client(sock, proc): sock.sendall((message + '\n').encode('utf-8')) red_condition.release() elif message == 'toggle': - proc.send_signal(signal.SIGUSR1) - elif message == 'kill': + if (not red_dying) and (not red_froozen): + proc.send_signal(signal.SIGUSR1) + elif message == 'disable': + if (not red_dying) and (not red_froozen): + if red_status: + proc.send_signal(signal.SIGUSR1) + elif message == 'enable': + if (not red_dying) and (not red_froozen): + if not red_status: + proc.send_signal(signal.SIGUSR1) + elif message == 'freeze': + if not red_froozen: + red_froozen = True + proc.send_signal(signal.SIGTSTP) + elif message == 'thaw': # TODO broadcast update + if red_froozen: + red_froozen = False + proc.send_signal(signal.SIGCONT) + elif message == 'kill': # TODO broadcast update + if red_froozen: + red_froozen = False + proc.send_signal(signal.SIGCONT) red_dying = True proc.terminate() import time @@ -461,13 +501,14 @@ def run_as_daemon(sock): def do_daemon(reexec): ''' - Run actions for --daemon or ++daemon + Run actions for --daemon or ==daemon - @param reexec:bool Wether to perform actions for ++daemon + @param reexec:bool Wether to perform actions for ==daemon ''' if not reexec: - if (kill > 0) or toggle or status: - print('%s: error: -x, +x and -s can be used when running as the daemon' % sys.argv[0]) + if (kill > 0) or toggle or (set_status is not None) or (set_freeze is not None) or status: + disallowed = '-x, +x, +e, +d, +f, +t and -s' + print('%s: error: %s can be used when running as the daemon' % (disallowed, sys.argv[0])) sys.exit(1) # Create server socket @@ -523,6 +564,34 @@ def do_toggle(): sock.sendall('toggle\n'.encode('utf-8')) +def do_disable(): + ''' + Run actions for --disable + ''' + sock.sendall('disable\n'.encode('utf-8')) + + +def do_enable(): + ''' + Run actions for --enable + ''' + sock.sendall('enable\n'.encode('utf-8')) + + +def do_freeze(): + ''' + Run actions for --freeze + ''' + sock.sendall('freeze\n'.encode('utf-8')) + + +def do_thaw(): + ''' + Run actions for --thaw + ''' + sock.sendall('thaw\n'.encode('utf-8')) + + def do_kill(): ''' Run actions for --kill @@ -621,10 +690,22 @@ def run_as_client(): Perform client actions ''' # Temporarily disable or enable redshift - if toggle: + if set_status is not None: + if set_status: + do_enable() + else: + do_disable() + elif toggle: do_toggle() - # Kill redshift and the night daemon + # Freeze or thaw redshift + if set_freeze is not None: + if set_freeze: + do_freeze() + else: + do_thaw() + + # Kill redshift and the nightshift daemon if kill > 0: do_kill() @@ -634,7 +715,7 @@ def run_as_client(): sock.close() # Start user interface - if (kill == 0) and not (status or toggle): + if (kill == 0) and not (status or toggle or (set_status is not None) or (set_freeze is not None)): sock.sendall('listen\n'.encode('utf-8')) user_interface() @@ -685,7 +766,8 @@ def respawn_daemon(): os.close(w_end) # Reexecute image - os.execl('/proc/self/exe', '/proc/self/exe', *(sys.argv + ['+d'])) + exe = os.readlink('/proc/self/exe') + os.execl(exe, exe, *(sys.argv + ['==daemon'])) else: ## Front-end (parent) # Wait for a signal @@ -703,7 +785,7 @@ def respawn_daemon(): def run(): ''' - Run as either the daemon (if --daemon or ++daemon) or as a client (otherwise) + Run as either the daemon (if --daemon or ==daemon) or as a client (otherwise) ''' if daemon > 0: do_daemon(daemon == 2) diff --git a/src/completion b/src/completion index f0fb7a6..b2caa90 100644 --- a/src/completion +++ b/src/completion @@ -24,6 +24,10 @@ (unargumented (options -d --daemon) (complete --daemon) (desc 'Start as daemon')) (unargumented (options -x --reset --kill) (complete --kill) (desc 'Remove adjustment from screen')) (unargumented (options +x --toggle) (complete --toggle) (desc 'Temporarily disable or enable adjustments')) + (unargumented (options +d --disable) (complete --disable) (desc 'Temporarily disable adjustments')) + (unargumented (options +e --enable) (complete --enable) (desc 'Re-enable adjustments')) + (unargumented (options +f --freeze) (complete --freeze) (desc 'Freeze the redshift process')) + (unargumented (options +t --thaw) (complete --thaw) (desc 'Thaw the redshift process')) (unargumented (options -s --status) (complete --status) (desc 'Print status information')) (argumented (options +c --script) (complete --script) (arg FILE) (files -f) (desc 'Load nightshift configuration script from specified file')) diff --git a/src/interface.py b/src/interface.py index 9188326..b041d6b 100644 --- a/src/interface.py +++ b/src/interface.py @@ -69,21 +69,28 @@ def ui_print(): print('\033[2K' + ('Dying' if red_dying else ('Enabled' if red_status else 'Disabled'))) print('\033[2K\n\033[2K', end = '') if not red_dying: - print(_button(0) % ('Disable' if red_status else 'Enable'), end = ' ') - print(_button(1) % 'Kill', end = ' ') + if red_froozen: + print(_button(0, 1) % 'Thaw', end = ' ') + print(_button(2) % 'Kill', end = ' ') + print(_button(3) % 'Close') + else: + print(_button(0) % ('Disable' if red_status else 'Enable'), end = ' ') + print(_button(1) % 'Freeze', end = ' ') + print(_button(2) % 'Kill', end = ' ') + print(_button(3) % 'Close') else: - print(_button(0, 1) % 'Kill immediately', end = ' ') - print(_button(2) % 'Close') + print(_button(0, 1, 2) % 'Kill immediately', end = ' ') + print(_button(3) % 'Close') else: print('\033[2KNot running') print('\033[2K\n\033[2K', end = '') - print(_button(0, 1) % 'Revive', end = ' ') - print(_button(2) % 'Close') + print(_button(0, 1, 2) % 'Revive', end = ' ') + print(_button(3) % 'Close') print('\033[J') def ui_read(): - global red_dying + global red_dying, red_froozen inbuf = sys.stdin.buffer while True: c = inbuf.read(1) @@ -93,25 +100,36 @@ def ui_read(): red_condition.acquire() try: if red_running and not red_dying: - ui_state['focus'] = (ui_state['focus'] + 1) % 3 - elif ui_state['focus'] == 2: + if red_froozen and (ui_state['focus'] == 0): + ui_state['focus'] = 1 + ui_state['focus'] = (ui_state['focus'] + 1) % 4 + if red_froozen and (ui_state['focus'] == 0): + ui_state['focus'] = 1 + elif ui_state['focus'] == 3: ui_state['focus'] = 0 else: - ui_state['focus'] = 2 + ui_state['focus'] = 3 red_condition.notify() finally: red_condition.release() elif c in b' \n': red_condition.acquire() try: - if ui_state['focus'] == 2: + if ui_state['focus'] == 3: break elif red_running: - if (not red_dying) and (ui_state['focus'] == 0): - sock.sendall('toggle\n'.encode('utf-8')) - else: + if red_dying or (ui_state['focus'] == 2): sock.sendall('kill\n'.encode('utf-8')) red_dying = True + elif red_froozen: + sock.sendall('thaw\n'.encode('utf-8')) + red_froozen = False + else: + if ui_state['focus'] == 0: + sock.sendall('toggle\n'.encode('utf-8')) + elif ui_state['focus'] == 1: + sock.sendall('freeze\n'.encode('utf-8')) + red_froozen = True red_condition.notify() else: respawn_daemon() @@ -166,19 +184,20 @@ def ui_status(): def ui_status_callback(status): global red_brightness, red_temperature, red_brightnesses, red_temperatures - global red_period, red_location, red_status, red_running, red_dying + global red_period, red_location, red_status, red_running, red_dying, red_froozen if status is not None: - brightness = [float(status['%s brightness' % k]) for k in ('Current', 'Daytime', 'Night')] + brightness = [float(status['%s brightness' % k]) for k in ('Current', 'Daytime', 'Night')] temperature = [float(status['%s temperature' % k]) for k in ('Current', 'Daytime', 'Night')] red_condition.acquire() try: - red_brightness, red_brightnesses = brightness[0], tuple(brightness[1:]) + red_brightness, red_brightnesses = brightness[0], tuple(brightness[1:]) red_temperature, red_temperatures = temperature[0], tuple(temperature[1:]) - red_period = float(status['Dayness']) + red_period = float(status['Dayness']) red_location = (float(status['Latitude']), float(status['Longitude'])) - red_status = status['Enabled'] == 'yes' - red_running = status['Running'] == 'yes' - red_dying = status['Dying'] == 'yes' + red_status = status['Enabled'] == 'yes' + red_running = status['Running'] == 'yes' + red_dying = status['Dying'] == 'yes' + red_froozen = status['Froozen'] == 'yes' red_condition.notify() finally: red_condition.release() |