#!/usr/bin/env python import curses import sys import gevent import monitor import process import hotkey import splash import footer def check_window_size(interface_queue, state, window, min_y, min_x): # TODO: use SIGWINCH interrupt if (state['y'], state['x']) != window.getmaxyx(): new_y, new_x = window.getmaxyx() if (new_y < min_y) or (new_x < min_x): interface_queue.put({ 'stop': "Window is too small - must be at least " + str(min_x) + "x" + str(min_y)}) if (state['y'], state['x']) != (-1, -1): # initialized interface_queue.put({'resize': 1}) state['x'] = new_x state['y'] = new_y def init_curses(): window = curses.initscr() curses.noecho() # prevents user input from being echoed curses.curs_set(0) # make cursor invisible curses.start_color() curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(4, curses.COLOR_MAGENTA, curses.COLOR_BLACK) curses.init_pair(5, curses.COLOR_YELLOW, curses.COLOR_BLACK) window.timeout(50) window.keypad(1) # interpret arrow keys, etc return window def init_state(): state = { 'mode': "splash", 'blocks': { 'cursor': 0, 'offset': 0 }, 'networkhashps': {}, 'estimatefee': {}, 'console': { 'cbuffer': [], 'rbuffer': [], 'offset': 0 }, 'x': -1, 'y': -1, 'history': { 'getnettotals': [] } } return state def loop(block_viewer, state, window, interface_queue, rpcc, poller): iterations = 0 while 1: check_window_size(interface_queue, state, window, 12, 75) # min_y, min_x error_message = process.queue(state, window, interface_queue) if error_message: return error_message # ends if stop command sent by rpc gevent.sleep(0.0001) # TODO: Can we kill this? if state['mode'] == "monitor": if not iterations % 20: monitor.draw_window(state, window) footer.draw_window(state) if hotkey.check(block_viewer, state, window, rpcc, poller): # poll for user input break # returns 1 when quit key is pressed iterations += 1 return False def main(block_viewer, window, interface_queue, rpcc, poller, initial_mode=None): error_message = False rpcc.request("getnetworkinfo") rpcc.request("getblockchaininfo") try: state = init_state() splash.draw_window(state, window) check_window_size(interface_queue, state, window, 12, 75) # min_y, min_x if initial_mode: hotkey.change_mode(state, window, initial_mode, poller) error_message = loop(block_viewer, state, window, interface_queue, rpcc, poller) finally: # restore sane terminal state, end RPC thread curses.nocbreak() curses.endwin() if error_message: sys.stderr.write("bitcoind-ncurses encountered an error\n") sys.stderr.write("Message: " + error_message + "\n")