mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
host: add verbose output toggle
Provided as a checkbox in the GUI and a command line argument in the CLI. Exception information is now also printed to the GUI textbox if the verbose output checkbox is enabled.
This commit is contained in:
parent
961459fe01
commit
158d7c1e92
1 changed files with 41 additions and 12 deletions
|
@ -32,6 +32,8 @@
|
||||||
# Under MacOS, use `brew install libusb` to install libusb via Homebrew.
|
# Under MacOS, use `brew install libusb` to install libusb via Homebrew.
|
||||||
# Under Linux, you should be good to go from the start. If not, just use the package manager from your distro to install libusb.
|
# Under Linux, you should be good to go from the start. If not, just use the package manager from your distro to install libusb.
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
@ -298,6 +300,7 @@ TASKBAR_LIB = b'TVNGVAIAAQAAAAAACQQAAAAAAABBAAAAAQAAAAAAAAAOAAAA/////wAAAAAAAAAA
|
||||||
# Global variables used throughout the code.
|
# Global variables used throughout the code.
|
||||||
g_cliMode: bool = False
|
g_cliMode: bool = False
|
||||||
g_outputDir: str = ''
|
g_outputDir: str = ''
|
||||||
|
g_logLevelIntVar: Optional[tk.IntVar] = None
|
||||||
|
|
||||||
g_osType: str = ''
|
g_osType: str = ''
|
||||||
g_osVersion: str = ''
|
g_osVersion: str = ''
|
||||||
|
@ -313,6 +316,7 @@ g_tkChooseDirButton: Optional[tk.Button] = None
|
||||||
g_tkServerButton: Optional[tk.Button] = None
|
g_tkServerButton: Optional[tk.Button] = None
|
||||||
g_tkTipMessage: Any = None
|
g_tkTipMessage: Any = None
|
||||||
g_tkScrolledTextLog: Optional[scrolledtext.ScrolledText] = None
|
g_tkScrolledTextLog: Optional[scrolledtext.ScrolledText] = None
|
||||||
|
g_tkVerboseCheckbox: Optional[tk.Checkbutton] = None
|
||||||
|
|
||||||
g_logger: Optional[logging.Logger] = None
|
g_logger: Optional[logging.Logger] = None
|
||||||
|
|
||||||
|
@ -363,9 +367,11 @@ class LogConsole:
|
||||||
# Create a logging handler using a queue.
|
# Create a logging handler using a queue.
|
||||||
self.log_queue: queue.Queue = queue.Queue()
|
self.log_queue: queue.Queue = queue.Queue()
|
||||||
self.queue_handler = LogQueueHandler(self.log_queue)
|
self.queue_handler = LogQueueHandler(self.log_queue)
|
||||||
|
|
||||||
#formatter = logging.Formatter('[%(asctime)s] -> %(message)s')
|
#formatter = logging.Formatter('[%(asctime)s] -> %(message)s')
|
||||||
formatter = logging.Formatter('%(message)s')
|
formatter = logging.Formatter('%(message)s')
|
||||||
self.queue_handler.setFormatter(formatter)
|
self.queue_handler.setFormatter(formatter)
|
||||||
|
|
||||||
g_logger.addHandler(self.queue_handler)
|
g_logger.addHandler(self.queue_handler)
|
||||||
|
|
||||||
# Start polling messages from the queue.
|
# Start polling messages from the queue.
|
||||||
|
@ -536,6 +542,14 @@ class ProgressBarWindow:
|
||||||
|
|
||||||
g_progressBarWindow: Optional[ProgressBarWindow] = None
|
g_progressBarWindow: Optional[ProgressBarWindow] = None
|
||||||
|
|
||||||
|
def eprint(*args, **kwargs) -> None:
|
||||||
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
|
def utilsLogException(exception_str: str) -> None:
|
||||||
|
eprint(exception_str)
|
||||||
|
if g_logger is not None:
|
||||||
|
g_logger.debug(exception_str)
|
||||||
|
|
||||||
def utilsGetPath(path_arg: str, fallback_path: str, is_file: bool, create: bool = False) -> str:
|
def utilsGetPath(path_arg: str, fallback_path: str, is_file: bool, create: bool = False) -> str:
|
||||||
path = os.path.abspath(os.path.expanduser(os.path.expandvars(path_arg if path_arg else fallback_path)))
|
path = os.path.abspath(os.path.expanduser(os.path.expandvars(path_arg if path_arg else fallback_path)))
|
||||||
|
|
||||||
|
@ -656,7 +670,7 @@ def usbRead(size: int, timeout: int = -1) -> bytes:
|
||||||
rd = bytes(g_usbEpIn.read(size, timeout))
|
rd = bytes(g_usbEpIn.read(size, timeout))
|
||||||
except usb.core.USBError:
|
except usb.core.USBError:
|
||||||
if not g_cliMode:
|
if not g_cliMode:
|
||||||
traceback.print_exc(file=sys.stderr)
|
utilsLogException(traceback.format_exc())
|
||||||
g_logger.error('\nUSB timeout triggered or console disconnected.')
|
g_logger.error('\nUSB timeout triggered or console disconnected.')
|
||||||
|
|
||||||
return rd
|
return rd
|
||||||
|
@ -670,7 +684,7 @@ def usbWrite(data: bytes, timeout: int = -1) -> int:
|
||||||
wr = g_usbEpOut.write(data, timeout)
|
wr = g_usbEpOut.write(data, timeout)
|
||||||
except usb.core.USBError:
|
except usb.core.USBError:
|
||||||
if not g_cliMode:
|
if not g_cliMode:
|
||||||
traceback.print_exc(file=sys.stderr)
|
utilsLogException(traceback.format_exc())
|
||||||
g_logger.error('\nUSB timeout triggered or console disconnected.')
|
g_logger.error('\nUSB timeout triggered or console disconnected.')
|
||||||
|
|
||||||
return wr
|
return wr
|
||||||
|
@ -1070,7 +1084,7 @@ def uiStartServer() -> None:
|
||||||
try:
|
try:
|
||||||
os.makedirs(g_outputDir, exist_ok=True)
|
os.makedirs(g_outputDir, exist_ok=True)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc(file=sys.stderr)
|
utilsLogException(traceback.format_exc())
|
||||||
messagebox.showerror('Error', 'Unable to create full output directory tree!', parent=g_tkRoot)
|
messagebox.showerror('Error', 'Unable to create full output directory tree!', parent=g_tkRoot)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -1086,6 +1100,7 @@ def uiToggleElements(flag: bool) -> None:
|
||||||
#assert g_tkChooseDirButton is not None
|
#assert g_tkChooseDirButton is not None
|
||||||
#assert g_tkServerButton is not None
|
#assert g_tkServerButton is not None
|
||||||
#assert g_tkCanvas is not None
|
#assert g_tkCanvas is not None
|
||||||
|
#assert g_tkVerboseCheckbox is not None
|
||||||
|
|
||||||
if flag:
|
if flag:
|
||||||
g_tkRoot.protocol('WM_DELETE_WINDOW', uiHandleExitProtocol)
|
g_tkRoot.protocol('WM_DELETE_WINDOW', uiHandleExitProtocol)
|
||||||
|
@ -1093,6 +1108,8 @@ def uiToggleElements(flag: bool) -> None:
|
||||||
g_tkChooseDirButton.configure(state='normal')
|
g_tkChooseDirButton.configure(state='normal')
|
||||||
g_tkServerButton.configure(text='Start server', command=uiStartServer, state='normal')
|
g_tkServerButton.configure(text='Start server', command=uiStartServer, state='normal')
|
||||||
g_tkCanvas.itemconfigure(g_tkTipMessage, state='hidden', text='')
|
g_tkCanvas.itemconfigure(g_tkTipMessage, state='hidden', text='')
|
||||||
|
|
||||||
|
g_tkVerboseCheckbox.configure(state='normal')
|
||||||
else:
|
else:
|
||||||
#assert g_tkScrolledTextLog is not None
|
#assert g_tkScrolledTextLog is not None
|
||||||
|
|
||||||
|
@ -1106,6 +1123,8 @@ def uiToggleElements(flag: bool) -> None:
|
||||||
g_tkScrolledTextLog.delete('1.0', tk.END)
|
g_tkScrolledTextLog.delete('1.0', tk.END)
|
||||||
g_tkScrolledTextLog.configure(state='disabled')
|
g_tkScrolledTextLog.configure(state='disabled')
|
||||||
|
|
||||||
|
g_tkVerboseCheckbox.configure(state='disabled')
|
||||||
|
|
||||||
def uiChooseDirectory() -> None:
|
def uiChooseDirectory() -> None:
|
||||||
dir = filedialog.askdirectory(parent=g_tkRoot, title='Select an output directory', initialdir=INITIAL_DIR, mustexist=True)
|
dir = filedialog.askdirectory(parent=g_tkRoot, title='Select an output directory', initialdir=INITIAL_DIR, mustexist=True)
|
||||||
if dir:
|
if dir:
|
||||||
|
@ -1128,9 +1147,14 @@ def uiHandleExitProtocolStub() -> None:
|
||||||
def uiScaleMeasure(measure: int) -> int:
|
def uiScaleMeasure(measure: int) -> int:
|
||||||
return round(float(measure) * SCALE)
|
return round(float(measure) * SCALE)
|
||||||
|
|
||||||
|
def uiHandleVerboseCheckbox() -> None:
|
||||||
|
#assert g_logger is not None
|
||||||
|
#assert g_logLevelIntVar is not None
|
||||||
|
g_logger.setLevel(g_logLevelIntVar.get())
|
||||||
|
|
||||||
def uiInitialize() -> None:
|
def uiInitialize() -> None:
|
||||||
global SCALE
|
global SCALE, g_logLevelIntVar
|
||||||
global g_tkRoot, g_tkCanvas, g_tkDirText, g_tkChooseDirButton, g_tkServerButton, g_tkTipMessage, g_tkScrolledTextLog
|
global g_tkRoot, g_tkCanvas, g_tkDirText, g_tkChooseDirButton, g_tkServerButton, g_tkTipMessage, g_tkScrolledTextLog, g_tkVerboseCheckbox
|
||||||
global g_stopEvent, g_tlb, g_taskbar, g_progressBarWindow
|
global g_stopEvent, g_tlb, g_taskbar, g_progressBarWindow
|
||||||
|
|
||||||
# Setup thread event.
|
# Setup thread event.
|
||||||
|
@ -1146,7 +1170,7 @@ def uiInitialize() -> None:
|
||||||
if not dpi_aware:
|
if not dpi_aware:
|
||||||
dpi_aware = (ctypes.windll.shcore.SetProcessDpiAwareness(1) == 0)
|
dpi_aware = (ctypes.windll.shcore.SetProcessDpiAwareness(1) == 0)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc(file=sys.stderr)
|
utilsLogException(traceback.format_exc())
|
||||||
|
|
||||||
# Enable taskbar features under Windows (if possible).
|
# Enable taskbar features under Windows (if possible).
|
||||||
del_tlb = False
|
del_tlb = False
|
||||||
|
@ -1165,7 +1189,7 @@ def uiInitialize() -> None:
|
||||||
g_taskbar = cc.CreateObject('{56FDF344-FD6D-11D0-958A-006097C9A090}', interface=g_tlb.ITaskbarList3)
|
g_taskbar = cc.CreateObject('{56FDF344-FD6D-11D0-958A-006097C9A090}', interface=g_tlb.ITaskbarList3)
|
||||||
g_taskbar.HrInit()
|
g_taskbar.HrInit()
|
||||||
except:
|
except:
|
||||||
traceback.print_exc(file=sys.stderr)
|
utilsLogException(traceback.format_exc())
|
||||||
|
|
||||||
if del_tlb:
|
if del_tlb:
|
||||||
os.remove(TASKBAR_LIB_PATH)
|
os.remove(TASKBAR_LIB_PATH)
|
||||||
|
@ -1181,7 +1205,7 @@ def uiInitialize() -> None:
|
||||||
icon_image = tk.PhotoImage(data=base64.b64decode(APP_ICON))
|
icon_image = tk.PhotoImage(data=base64.b64decode(APP_ICON))
|
||||||
g_tkRoot.wm_iconphoto(True, icon_image)
|
g_tkRoot.wm_iconphoto(True, icon_image)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc(file=sys.stderr)
|
utilsLogException(traceback.format_exc())
|
||||||
|
|
||||||
# Get screen resolution.
|
# Get screen resolution.
|
||||||
screen_width_px = g_tkRoot.winfo_screenwidth()
|
screen_width_px = g_tkRoot.winfo_screenwidth()
|
||||||
|
@ -1243,6 +1267,10 @@ def uiInitialize() -> None:
|
||||||
|
|
||||||
g_tkCanvas.create_text(uiScaleMeasure(5), uiScaleMeasure(WINDOW_HEIGHT - 10), text=COPYRIGHT_TEXT, anchor=tk.W)
|
g_tkCanvas.create_text(uiScaleMeasure(5), uiScaleMeasure(WINDOW_HEIGHT - 10), text=COPYRIGHT_TEXT, anchor=tk.W)
|
||||||
|
|
||||||
|
g_logLevelIntVar = tk.IntVar()
|
||||||
|
g_tkVerboseCheckbox = tk.Checkbutton(g_tkRoot, text='Verbose output', variable=g_logLevelIntVar, onvalue=logging.DEBUG, offvalue=logging.INFO, command=uiHandleVerboseCheckbox)
|
||||||
|
g_tkCanvas.create_window(uiScaleMeasure(WINDOW_WIDTH - 55), uiScaleMeasure(WINDOW_HEIGHT - 10), window=g_tkVerboseCheckbox, anchor=tk.CENTER)
|
||||||
|
|
||||||
# Initialize console logger.
|
# Initialize console logger.
|
||||||
console = LogConsole(g_tkScrolledTextLog)
|
console = LogConsole(g_tkScrolledTextLog)
|
||||||
|
|
||||||
|
@ -1281,8 +1309,9 @@ def main() -> int:
|
||||||
|
|
||||||
# Parse command line arguments.
|
# Parse command line arguments.
|
||||||
parser = ArgumentParser(description=SCRIPT_TITLE + '. ' + COPYRIGHT_TEXT + '.')
|
parser = ArgumentParser(description=SCRIPT_TITLE + '. ' + COPYRIGHT_TEXT + '.')
|
||||||
parser.add_argument('-c', '--cli', required=False, action='store_true', help='Start the script in CLI mode.')
|
parser.add_argument('-c', '--cli', required=False, action='store_true', default=False, help='Start the script in CLI mode.')
|
||||||
parser.add_argument('-o', '--outdir', required=False, type=str, metavar='DIR', help='Path to output directory. Defaults to "' + DEFAULT_DIR + '".')
|
parser.add_argument('-o', '--outdir', required=False, type=str, metavar='DIR', help='Path to output directory. Defaults to "' + DEFAULT_DIR + '".')
|
||||||
|
parser.add_argument('-v', '--verbose', required=False, action='store_true', default=False, help='Enable verbose output.')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Update global flags.
|
# Update global flags.
|
||||||
|
@ -1305,10 +1334,10 @@ def main() -> int:
|
||||||
g_isWindows7 = (True if (win_ver_major > 6) else (win_ver_major == 6 and win_ver_minor > 0))
|
g_isWindows7 = (True if (win_ver_major > 6) else (win_ver_major == 6 and win_ver_minor > 0))
|
||||||
|
|
||||||
# Setup logging mechanism.
|
# Setup logging mechanism.
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=(logging.DEBUG if args.verbose else logging.INFO))
|
||||||
g_logger = logging.getLogger()
|
g_logger = logging.getLogger()
|
||||||
if len(g_logger.handlers):
|
if len(g_logger.handlers):
|
||||||
# Remove stderr output handler from logger.
|
# Remove stderr output handler from logger. We'll control standard output on our own.
|
||||||
log_stderr = g_logger.handlers[0]
|
log_stderr = g_logger.handlers[0]
|
||||||
g_logger.removeHandler(log_stderr)
|
g_logger.removeHandler(log_stderr)
|
||||||
|
|
||||||
|
@ -1330,7 +1359,7 @@ if __name__ == "__main__":
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
print('\nScript interrupted.')
|
print('\nScript interrupted.')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc(file=sys.stderr)
|
utilsLogException(traceback.format_exc())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sys.exit(ret)
|
sys.exit(ret)
|
||||||
|
|
Loading…
Reference in a new issue