import sys import typing as t import time import whispercpp as w
class StreamTranscriber: def init(self, model_name: str): self.transcriber = w.Whisper.from_pretrained(model_name) self.paused = False
def store_transcript_handler(self, ctx, n_new, data):
segment = ctx.full_n_segments() - n_new
cur_segment = ""
while segment < ctx.full_n_segments():
cur_segment = ctx.full_get_segment_text(segment)
data.append(cur_segment)
segment += 1
if "hey toaster" in cur_segment.lower() and not self.paused:
self.transcriber.pause_audio()
self.paused = True
print("Stopping")
time.sleep(5)
self.transcriber.resume_audio()
self.paused = False
print("Resumed")
def main(self, **kwargs: t.Any):
transcription: t.Iterator[str] | None = None
try:
transcription = self.transcriber.stream_transcribe(callback=self.store_transcript_handler, **kwargs)
finally:
assert transcription is not None, "Something went wrong!"
sys.stderr.writelines(
["\\nTranscription (line by line):\\n"] + [f"{it}\\n" for it in transcription]
)
sys.stderr.flush()
if name == "main": import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"--model_name", default="tiny.en", choices=list(w.utils.MODELS_URL)
)
parser.add_argument(
"--device_id", type=int, help="Choose the audio device", default=0
)
parser.add_argument(
"--length_ms",
type=int,
help="Length of the audio buffer in milliseconds",
default=5000,
)
parser.add_argument(
"--sample_rate",
type=int,
help="Sample rate of the audio device",
default=w.api.SAMPLE_RATE,
)
parser.add_argument(
"--n_threads",
type=int,
help="Number of threads to use for decoding",
default=3,
)
parser.add_argument(
"--step_ms",
type=int,
help="Step size of the audio buffer in milliseconds",
default=0,
)
parser.add_argument(
"--keep_ms",
type=int,
help="Length of the audio buffer to keep in milliseconds",
default=200,
)
parser.add_argument(
"--max_tokens",
type=int,
help="Maximum number of tokens to decode",
default=32,
)
parser.add_argument("--audio_ctx", type=int, help="Audio context", default=512)
parser.add_argument(
"--list_audio_devices",
action="store_true",
default=False,
help="Show available audio devices",
)
args = parser.parse_args()
if args.list_audio_devices:
w.utils.available_audio_devices()
sys.exit(0)
transcriber = StreamTranscriber(args.model_name)
transcriber.main(**vars(args))
specch recongisation code
import prestart
import os import re import sys import json import random import legacy import threading import traceback import tkinter as tk import tkinter.ttk as ttk import tkinter.font as tkf import tkinter.filedialog as tkfd import tkinter.messagebox as tkmb
path_exe = os.path.dirname(os.path.realpath(sys.executable if getattr(sys, "frozen", False) else file)) path_lib = os.path.join(path_exe, "lib") sys.path.append(path_lib) # for clean build reasons we dont include lib.handwriting import tkwidgets as tkw
versionSettingsCurrent = "0.4.0" style = { "bg_window": "#303030", "bg_button": "#505050", "bg_button_hover": "#404040", "bg_button_start": "#409040", "bg_scroll": "#202020", "bg_inner": "#101010", "bg_separator": "#606060", "fg_button": "#D0D0D0", "fg_button_hover": "#D0D0D0", "fg_button_start": "#004000", "fg_scroll": "#808080", "fg_label": "#D0D0D0", "fg_text": "#F0F0F0", "fg_hint": "#A0A0A0", "fg_progress": "#409040", "relief": "flat", "borderwidth": 0 }
def main(): window = tk.Tk() window.resizable(False, False) wsize = (660, 650) window.geometry(f"{wsize[0]}x{wsize[1]}") window.title("HandCode") window.configure(bg=style["bg_window"]) window.iconbitmap(os.path.join(path_lib, "icon.ico"))
fontTooltip = tkf.Font(size=7)
fontText = tkf.Font(size=9)
fontLabel = tkf.Font(size=10, weight="bold")
fontStart = tkf.Font(size=24, weight="bold")
styleLabelSection = {
"font": fontLabel,
"bg": style["bg_window"],
"fg": style["fg_label"],
}
styleLabelInput = {
"font": fontText,
"bg": style["bg_window"],
"fg": style["fg_label"],
}
styleLabelTooltip = {
"font": fontTooltip,
"bg": style["bg_window"],
"fg": style["fg_label"]
}
styleEntryDefault = {
"bg": style["bg_inner"],
"fg": style["fg_text"],
"insertbackground": style["fg_hint"],
"relief": tk.FLAT
}
_styleEntryCustom = {
"bgentry": style["bg_inner"],
"fgentry": style["fg_text"],
"bgcursor": style["fg_hint"],
"font": fontText
}
styleEntryScrolled = {
**_styleEntryCustom,
"stylescrollx": "Maddin.HC.Horizontal.TScrollbar",
"stylescrolly": "Maddin.HC.Vertical.TScrollbar",
}
styleEntryUnit = {
**_styleEntryCustom,
"fgunit": style["fg_hint"]
}
styleEntryLabeled = {
**styleEntryUnit,
"bglabel": style["bg_window"],
"fglabel": style["fg_label"]
}
styleButtonDefault = {
"bg": style["bg_button"],
"fg": style["fg_button"],
"relief": tk.FLAT
}
styleButtonStart = {
"font": fontStart,
"bg": style["bg_button_start"],
"fg": style["fg_button_start"],
"relief": tk.FLAT
}
styleScaleLabeled = {
"bglabel": style["bg_window"],
"fglabel": style["fg_label"],
"fgtooltip": style["fg_hint"],
"bgscale": style["bg_inner"],
"fgscale": style["bg_button"],
"fgscale:hover": style["bg_button_hover"],
"font": fontText,
"fonttooltip": fontTooltip
}
styleSelectLabeled = {
"bglabel": style["bg_window"],
"fglabel": style["fg_label"],
"bgselect": style["bg_button"],
"bgselect:hover": style["bg_button_hover"],
"fgselect": style["fg_button"],
"fgselect:hover": style["fg_button_hover"]
}
styleCheckboxDefault = {
"bglabel": style["bg_window"],
"bgcheck": style["bg_inner"],
"fg": style["fg_label"],
"font": fontText,
}
styleCheckboxSmall = {
**styleCheckboxDefault,
"font": fontTooltip
}
ttkStyle = ttk.Style()
ttkStyle.theme_use("default")
ttkStyle.configure("Maddin.HC.Horizontal.TProgressbar", borderwidth=style["borderwidth"], troughcolor=style["bg_inner"], background=style["fg_progress"], troughrelief=style["relief"])
ttkStyle.configure('Maddin.HC.Horizontal.TScrollbar', troughcolor=style["bg_window"], background=style["bg_button"], arrowcolor=style["fg_hint"], relief=style["relief"], troughrelief=style["relief"])
ttkStyle.map('Maddin.HC.Horizontal.TScrollbar', background=[('pressed', '!disabled', 'active', style["bg_button_hover"])])
ttkStyle.configure('Maddin.HC.Vertical.TScrollbar', troughcolor=style["bg_window"], background=style["bg_button"], arrowcolor=style["fg_hint"], relief=style["relief"], troughrelief=style["relief"])
ttkStyle.map('Maddin.HC.Vertical.TScrollbar', background=[('pressed', '!disabled', 'active', style["bg_button_hover"])])
lblFileIn = tk.Label(window, text="Input File (opt):", **styleLabelSection)
btnFileIn = tk.Button(window, text="Open File...", **styleButtonDefault)
lblFileProcess = tk.Label(window, text="↴ ↱", *{*styleLabelSection, "font": fontStart})
lblFileOut = tk.Label(window, text="Output File:", **styleLabelSection)
edtFileOut = tk.Entry(window, **styleEntryDefault)
sltFileType = tkw.LabeledSelect(window, label="Format", options=["GCode"], **styleSelectLabeled)
lblInput = tk.Label(window, text="Input Text:", **styleLabelSection)
edtInput = tkw.ScrolledEntry(window, **styleEntryScrolled)
lblLog = tk.Label(window, text="Event Log:", **styleLabelSection)
edtLog = tkw.ScrolledEntry(window, **styleEntryScrolled)
prgLoading = ttk.Progressbar(window, orient="horizontal", mode="indeterminate", style="Maddin.HC.Horizontal.TProgressbar")
btnShow = tk.Button(window, text="Open input/output folder", **styleButtonDefault)
btnStart = tk.Button(window, text="Start", **styleButtonStart, state=tk.DISABLED)
segLeftRight = tk.Frame(window, bd=0, bg=style["bg_separator"])
lblFont = tk.Label(window, text="Font Settings:", **styleLabelSection)
edtFontSize = tkw.LabeledEntry(window, label="Size", unit="mm", **styleEntryLabeled)
sltFontStyle = tkw.LabeledSelect(window, label="Style", options=[f"Style {i+1}" for i in range(12)], **styleSelectLabeled)
edtFontBias = tkw.LabeledEntry(window, label="Legibility", unit="%", **styleEntryLabeled)
edtFontLineHeight = tkw.LabeledEntry(window, label="Line Height", unit="mm", **styleEntryLabeled)
lblFontWordSpacing = tk.Label(window, text="Word Spacing", **styleLabelInput)
edtFontWordSpacing = tkw.UnitEntry(window, unit="mm", **styleEntryUnit)
lblFontWordSpacingVar = tk.Label(window, text="±", **styleLabelInput)
edtFontWordSpacingVar = tkw.UnitEntry(window, unit="mm", **styleEntryUnit)
chkFontLineHeightRecalc = tkw.Checkbox(window, label="Recalc on f...", **styleCheckboxSmall)
chkFontWordSpacingRecalc = tkw.Checkbox(window, label="Recalc on font size cha...", **styleCheckboxSmall)
sclFontAlignHorizontal = tkw.LabeledScale(window, label="Horzontal Align", description="Left Center Right", start=0, end=1, step=0.1, **styleScaleLabeled, state=tk.DISABLED)
sclFontAlignVertical = tkw.LabeledScale(window, label="Vertical Align", description="Top Center Bottom", start=0, end=1, step=0.1, **styleScaleLabeled)
lblPen = tk.Label(window, text="Pen Settings:", **styleLabelSection)
edtPenZDraw = tkw.LabeledEntry(window, label="Z Draw", unit="mm", **styleEntryLabeled)
edtPenZTravel = tkw.LabeledEntry(window, label="Z Travel", unit="mm", **styleEntryLabeled)
edtPenZPause = tkw.LabeledEntry(window, label="Z Pause", unit="mm", **styleEntryLabeled)
edtPenFDraw = tkw.LabeledEntry(window, label="Feedrate Draw", unit="mm/min", **styleEntryLabeled)
edtPenFTravel = tkw.LabeledEntry(window, label="Feedrate Travel", unit="mm/min", **styleEntryLabeled)
lblPage = tk.Label(window, text="Page Settings:", **styleLabelSection)
edtPageWidth = tkw.LabeledEntry(window, label="Width (o≃∞)", unit="mm", **styleEntryLabeled)
edtPageHeight = tkw.LabeledEntry(window, label="Height (o≃∞)", unit="mm", **styleEntryLabeled)
edtPageRotation = tkw.LabeledEntry(window, label="Rotation", unit="°", **styleEntryLabeled)
lblOther = tk.Label(window, text="Other Features:", **styleLabelSection)
chkFeatureReplace = tkw.Checkbox(window, label="Replace unknown characters", **styleCheckboxDefault)
lblFeatureReplace = tk.Label(window, text="(e.g. ä -> a, Q -> O)", **styleLabelTooltip)
chkFeatureImitate = tkw.Checkbox(window, label="Imitate some unknown characters", **styleCheckboxDefault)
chkFeatureImitateDAM = tkw.Checkbox(window, label="Imitate diaresis as macron (ä -> ā)", **styleCheckboxSmall)
chkFeatureSplitPages = tkw.Checkbox(window, label="One output file for each page", **styleCheckboxDefault)
def reloadUI():
# set listeners
_fontfactors = dict()
def recalculateFontSize(base, entry, name, digits=-1):
if name not in _fontfactors:
return
template = "{size}"
if digits > 0:
template = f"{{size:.0{digits}f}}"
size = base * _fontfactors[name]
entry.set(template.format(size=size).rstrip("0").rstrip("."))
def getFontSize(entry):
size = -1
try:
size = float(entry.get().strip())
except:
pass # bad, i know...
return size
def recalculateFontSizes():
_fontSize = getFontSize(edtFontSize)
if _fontSize < 0:
return
if chkFontLineHeightRecalc.get():
recalculateFontSize(_fontSize, edtFontLineHeight, "lineheight", digits=4)
if chkFontWordSpacingRecalc.get():
recalculateFontSize(_fontSize, edtFontWordSpacing, "wordspacing", digits=2)
recalculateFontSize(_fontSize, edtFontWordSpacingVar, "wordspacingvar", digits=1)
def recalculateFontFactor(base, entry, name):
size = getFontSize(entry)
_fontfactors[name] = size/base
def recalculateFontFactors():
_fontSize = getFontSize(edtFontSize)
if _fontSize <= 0:
return
if chkFontLineHeightRecalc.get():
recalculateFontFactor(_fontSize, edtFontLineHeight, "lineheight")
else:
_fontfactors.pop("lineheight", None)
if chkFontWordSpacingRecalc.get():
recalculateFontFactor(_fontSize, edtFontWordSpacing, "wordspacing")
recalculateFontFactor(_fontSize, edtFontWordSpacingVar, "wordspacingvar")
else:
_fontfactors.pop("wordspacing", None)
_fontfactors.pop("wordspacingvar", None)
edtFontSize.addListener("change", recalculateFontSizes)
edtFontLineHeight.addListener("change", recalculateFontFactors)
edtFontWordSpacing.addListener("change", recalculateFontFactors)
edtFontWordSpacingVar.addListener("change", recalculateFontFactors)
chkFontLineHeightRecalc.addListener("change", recalculateFontFactors)
chkFontWordSpacingRecalc.addListener("change", recalculateFontFactors)
def updateFeatureImitate():
state = tk.NORMAL if chkFeatureImitate.get() else tk.DISABLED
chkFeatureImitateDAM.configure(state=state)
chkFeatureImitate.addListener("change", updateFeatureImitate)
btnStart.configure(command=startConvert)
# actually display all the ui stuff
xstart = 10; ystart = 5
xmargin = 10; ymargin = 5
height = 20
x = xstart; y = ystart
lblFileIn.place(x=x, y=y, height=height)
btnFileIn.place(x=x, y=y+height, width=120, height=height)
btnFileIn.configure(command=selectInputFile)
lblFileProcess.place(x=x+120, y=y+height-2)
lblFileOut.place(x=x+120+70, y=y, height=height)
edtFileOut.place(x=x+120+70, y=y+height, width=120, height=height)
sltFileType.place(x=x+120+70+120+xmargin, y=y, width=80)
y += height + height + ymargin
lblInput.place(x=x, y=y, height=height)
y += height
edtInput.place(x=x, y=y, width=400, height=430)
y += 430 + ymargin
lblLog.place(x=x, y=y, height=height)
y += height
edtLog.place(x=x, y=y, width=400, height=114)
x += 400 + xmargin; y = ystart
segLeftRight.place(x=x-1, y=y+ymargin, width=2, height=wsize[1]-2*(ystart+ymargin))
x += xmargin
lblFont.place(x=x, y=y, height=20)
y += height
edtFontSize.place(x=x, y=y, width=60)
sltFontStyle.place(x=x+60+xmargin, y=y, width=80)
edtFontBias.place(x=x+60+xmargin+80+xmargin, y=y, width=60)
y += 2 * height + ymargin
edtFontLineHeight.place(x=x, y=y, width=80)
lblFontWordSpacing.place(x=x+80+xmargin, y=y, width=100, height=height)
edtFontWordSpacing.place(x=x+80+xmargin, y=y+height, width=65)
lblFontWordSpacingVar.place(x=x+80+xmargin+65, y=y+height, width=15, height=height)
edtFontWordSpacingVar.place(x=x+80+xmargin+65+15, y=y+height, width=50)
y += 2 * height
chkFontLineHeightRecalc.place(x=x-3, y=y, height=height)
chkFontWordSpacingRecalc.place(x=x+80+xmargin-3, y=y, height=height)
y += height + ymargin
sclFontAlignHorizontal.place(x=x, y=y, width=105)
sclFontAlignVertical.place(x=x+105+xmargin, y=y, width=105)
y += 2 * height + 10 + 3 * ymargin # + 10 since the LabeledScale is 10px larger than 2 * height
lblPen.place(x=x, y=y, height=height)
y += height
edtPenZDraw.place(x=x, y=y, width=67)
edtPenZTravel.place(x=x+67+xmargin, y=y, width=66)
edtPenZPause.place(x=x+67+xmargin+66+xmargin, y=y, width=67)
y += 2 * height + ymargin
edtPenFDraw.place(x=x, y=y, width=105)
edtPenFTravel.place(x=x+105+xmargin, y=y, width=105)
y += 2 * height + 3 * ymargin
lblPage.place(x=x, y=y, height=height)
y += height
edtPageWidth.place(x=x, y=y, width=75)
edtPageHeight.place(x=x+75+xmargin, y=y, width=75)
edtPageRotation.place(x=x+75+xmargin+75+xmargin, y=y, width=50)
y += 2 * height + 3 * ymargin
lblOther.place(x=x, y=y, height=height)
y += height
chkFeatureReplace.place(x=x, y=y, height=height)
y += height
lblFeatureReplace.place(x=x+height, y=y, height=height//2)
y += height//2 + ymargin
chkFeatureImitate.place(x=x, y=y, height=height)
y += height
chkFeatureImitateDAM.place(x=x+height, y=y, height=height-5)
y += height + ymargin
chkFeatureSplitPages.place(x=x, y=y, height=height)
y += height + 3 * ymargin - 2
prgLoading.place(x=x, y=y, width=220, height=height)
y += height + ymargin + 2
btnShow.place(x=x, y=y, width=220, height=height+ymargin)
y += height + ymargin + 2 * ymargin
btnStart.place(x=x, y=y, width=220, height=2*height+2*ymargin)
def startConvert():
if convertEvent.is_set():
return
btnStart.configure(state=tk.DISABLED)
edtLog.set("")
prgLoading.start()
readSettingsFromUI()
saveSettingsToFile()
errors = convertSettingsToData()
if errors:
report("log", f"\\n{errors} errors were encountered while parsing your current settings. Please see above for more information.\\n")
prgLoading.stop()
return
convertEvent.set()
def threadConvert():
try:
report("log", "Loading tensorflow... ")
import handwriting
report("log", "Done\\nLoading neural network... ")
gcode = handwriting.gcode.HandGCode(logger=lambda s: report("log", s))
report("log", "Done\\nLoading helper functions... ")
_pensettingsgen["gcode"] = handwriting.commands.gcode
report("log", "Done\\n")
report("success")
while True:
convertEvent.wait()
try:
gcode.generate(convertData)
report("success")
except Exception as e:
report("error", e)
convertEvent.clear()
except Exception as e:
tkmb.showerror("Error in the neural network thread", f"The following unhandled exception occured: {e}\\n\\n{traceback.format_exc()}\\n\\n{sys.exc_info()}")
def report(event, data=None):
if (event == "log") and data:
edtLog.append(data)
if (event == "success"):
btnStart.configure(state=tk.NORMAL)
prgLoading.stop()
if (event == "error"):
btnStart.configure(state=tk.NORMAL)
prgLoading.stop()
report("log", f"\\nUnhandled error: {data}\\n")
print(f"An error occurred:\\n{traceback.format_exc()}\\n\\n{sys.exc_info()}")
def selectInputFile():
filename = tkfd.askopenfilename(title="Open text file...", initialdir="data")
if not filename:
report("log", "No file selected!\\n")
return
readInputFile(filename)
def readInputFile(filename):
if not filename:
return
file = None
try:
file = open(filename, "r")
edtInput.set(file.read())
except Exception as e:
report("log", f"Unknown error reading file: {e}")
finally:
if file:
file.close()
def _savePathInDict(d, path, value):
plen = len(path)
for i, p in enumerate(path, 1):
if i < plen:
if p not in d:
d[p] = dict()
d = d[p]
continue
d[p] = value
def saveSetting(path, value):
_savePathInDict(convertSettings, path, value)
def readSettingsFromUI():
convertSettings.clear()
convertSettings["version"] = versionSettingsCurrent
saveSetting(["input", "text"], edtInput.get())
saveSetting(["output", "file"], edtFileOut.get())
saveSetting(["output", "format"], sltFileType.get())
saveSetting(["font", "size"], edtFontSize.get())
saveSetting(["font", "style"], sltFontStyle.get())
saveSetting(["font", "bias"], edtFontBias.get())
saveSetting(["font", "lineheight"], edtFontLineHeight.get())
saveSetting(["font", "wordspacing"], edtFontWordSpacing.get())
saveSetting(["font", "wordspacingvariance"], edtFontWordSpacingVar.get())
#saveSetting(["font", "align", "horizontal"], sclFontAlignHorizontal.get())
saveSetting(["font", "align", "vertical"], sclFontAlignVertical.get())
saveSetting(["pen", "heights", "draw"], edtPenZDraw.get())
saveSetting(["pen", "heights", "travel"], edtPenZTravel.get())
saveSetting(["pen", "heights", "pause"], edtPenZPause.get())
saveSetting(["pen", "speeds", "draw"], edtPenFDraw.get())
saveSetting(["pen", "speeds", "travel"], edtPenFTravel.get())
saveSetting(["page", "width"], edtPageWidth.get())
saveSetting(["page", "height"], edtPageHeight.get())
saveSetting(["page", "rotate"], edtPageRotation.get())
saveSetting(["features", "replace", "enabled"], chkFeatureReplace.get())
saveSetting(["features", "imitate", "enabled"], chkFeatureImitate.get())
saveSetting(["features", "imitate", "diaresisasmacron"], chkFeatureImitateDAM.get())
saveSetting(["features", "splitpages", "enabled"], chkFeatureSplitPages.get())
formatFloat = legacy.formatFloat
formatFontStyleName = legacy.formatFontStyleName
def writeSettingsToUI():
edtInput.set(convertSettings.get("input", {}).get("text", ""))
edtFileOut.delete(0, tk.END)
edtFileOut.insert(0, convertSettings.get("output", {}).get("file", "demo.nc"))
sltFileType.set(convertSettings.get("output", {}).get("format", "GCode"))
settingsFont = convertSettings.get("font", {})
fontSize = settingsFont.get("size", formatFloat(10))
_fontSize = 10
try: _fontSize = float(fontSize)
except: pass
edtFontSize.set(fontSize)
sltFontStyle.set(settingsFont.get("style", formatFontStyleName(1)))
edtFontBias.set(settingsFont.get("bias", formatFloat(75)))
edtFontLineHeight.set(settingsFont.get("lineheight", fontSize))
edtFontWordSpacing.set(settingsFont.get("wordspacing", formatFloat(round(_fontSize * 0.4, 2))))
edtFontWordSpacingVar.set(settingsFont.get("wordspacingvariance", formatFloat(round(_fontSize * 0.2, 1))))
chkFontLineHeightRecalc.set(settingsFont.get("lineheight_recalc", True))
chkFontWordSpacingRecalc.set(settingsFont.get("wordspacing_recalc", True))
chkFontWordSpacingRecalc.callListeners("change")
settingsFontAlign = settingsFont.get("align", {})
sclFontAlignHorizontal.set(settingsFontAlign.get("horizontal", 0))
sclFontAlignVertical.set(settingsFontAlign.get("vertical", 0.8))
settingsPen = convertSettings.get("pen", {})
settingsPenHeights = settingsPen.get("heights", {})
edtPenZDraw.set(settingsPenHeights.get("draw", formatFloat(0)))
edtPenZTravel.set(settingsPenHeights.get("travel", formatFloat(5)))
edtPenZPause.set(settingsPenHeights.get("pause", formatFloat(30)))
settingsPenSpeeds = settingsPen.get("speeds", {})
edtPenFDraw.set(settingsPenSpeeds.get("draw", formatFloat(1000)))
edtPenFTravel.set(settingsPenSpeeds.get("draw", formatFloat(1000)))
settingsPage = convertSettings.get("page", {})
edtPageWidth.set(settingsPage.get("width", formatFloat(0)))
edtPageHeight.set(settingsPage.get("height", formatFloat(0)))
edtPageRotation.set(settingsPage.get("rotate", formatFloat(0)))
settingsFeatures = convertSettings.get("features", {})
chkFeatureReplace.set(settingsFeatures.get("replace", {}).get("enabled", True))
chkFeatureImitate.set(settingsFeatures.get("imitate", {}).get("enabled", True))
chkFeatureImitate.callListeners("change")
chkFeatureImitateDAM.set(settingsFeatures.get("imitate", {}).get("diaresisasmacron", False))
chkFeatureSplitPages.set(settingsFeatures.get("splitpages", {}).get("enabled", False))
def formatPath(path):
return "->".join(path)
_fontstylere = re.compile("^\\s*Style (\\d+)\\s*$")
def parseFontStyle(style):
style = _fontstylere.findall(style)
try:
style = int(style[0])
if (style < 1) or (style > 12):
raise ValueError()
return style
except (KeyError, ValueError):
report("log", f"Invalid font style selected: \\"{style}\\"\\n")
raise
except Exception as e:
report("log", f"Unknown error while parsing font style \\"{style}\\": {e}\\n")
raise
_pensettingsgen = dict()
def parsePenSettings(mode, **kwargs):
if not _pensettingsgen:
raise NotImplemented("The handwriting library does not seem to have been fully loaded yet!")
if mode not in _pensettingsgen:
raise NotImplemented("The mode you requested does not seem to be implemented (yet?).")
return _pensettingsgen[mode](**kwargs)
def getConvertSetting(path, default=None):
value = convertSettings
for p in path:
if p not in value:
report("log", f"Field {formatPath(path)} ({p}) not set!")
if default is not None:
report("log", f" Using default value instead: {default}\\n")
return default
report("log", "\\n")
raise
try:
value = value[p]
except Exception as e:
report("log", f"Error while accessing part \\"{p}\\" of field {formatPath(path)}:\\n{traceback.format_exc()}")
if default is not None:
report("log", f"Using default value instead: {default}\\n")
return default
raise
return value
def getConvertSettingTyped(path, dtype, default=None):
value = getConvertSetting(path, default=default)
try:
value = dtype(value)
except Exception as e:
report("log", f"Unable to parse value \\"{value}\\" from field {formatPath(path)} to {dtype}:\\n{traceback.format_exc()}")
try:
value = dtype(default)
report("log", f"Using default value instead: {default} -> {value}\\n")
return value
except:
pass
raise
return value
def convertSettingToData(path, dtype, to=None, default=None):
if to is None:
to = path
try:
value = getConvertSettingTyped(path, dtype, default=default)
except:
return 1
_savePathInDict(convertData, to, value)
return 0
def convertSettingsToData():
errors = 0
errors += convertSettingToData(["input", "text"], str, default="Lorem ipsum (there was an error parsing the input field)")
errors += convertSettingToData(["output", "file"], lambda p: os.path.join("data", p), default="demo.gcode")
errors += convertSettingToData(["font", "size"], float, default=formatFloat(10))
errors += convertSettingToData(["font", "style"], parseFontStyle, default=formatFontStyleName(1))
errors += convertSettingToData(["font", "bias"], lambda x: float(x)/100, default=formatFloat(75))
errors += convertSettingToData(["font", "lineheight"], float, default=formatFloat(10))
try:
_fontSize = convertData.get("font", {}).get("size", 10)
wordspacing = getConvertSettingTyped(["font", "wordspacing"], float, default=formatFloat(_fontSize * 0.4))
wordspacingvar = getConvertSettingTyped(["font", "wordspacingvariance"], float, default=formatFloat(_fontSize * 0.2))
def wordspacingfun():
return wordspacing + (random.random()-0.5) * wordspacingvar
_savePathInDict(convertData, ["font", "wordspacing"], wordspacingfun)
except:
errors += 1
# errors += convertSettingToData(["font", "align", "horizontal"], float, default=formatFloat(0))
errors += convertSettingToData(["font", "align", "vertical"], float, default=formatFloat(0.8))
try:
pensettings = dict()
mode = getConvertSettingTyped(["output", "format"], str, default="GCode").lower()
# see lib/handwriting/commands.py for more information about these arguments
pensettings["pendraw"] = getConvertSettingTyped(["pen", "heights", "draw"], float, default=formatFloat(0))
pensettings["pentravel"] = getConvertSettingTyped(["pen", "heights", "travel"], float, default=formatFloat(5))
pensettings["penpause"] = getConvertSettingTyped(["pen", "heights", "pause"], float, default=formatFloat(30))
pensettings["feeddraw"] = getConvertSettingTyped(["pen", "speeds", "draw"], float, default=formatFloat(1000))
pensettings["feedtravel"] = getConvertSettingTyped(["pen", "speeds", "travel"], float, default=formatFloat(1000))
_savePathInDict(convertData, ["commands"], parsePenSettings(mode, **pensettings))
except:
print(traceback.format_exc())
errors += 1
errors += convertSettingToData(["page", "width"], float, default=formatFloat(0))
errors += convertSettingToData(["page", "height"], float, default=formatFloat(0))
errors += convertSettingToData(["page", "rotate"], float, default=formatFloat(0))
errors += convertSettingToData(["features", "replace", "enabled"], bool, default=True)
errors += convertSettingToData(["features", "imitate", "enabled"], bool, default=True)
errors += convertSettingToData(["features", "imitate", "diaresisasmacron"], bool, default=False)
errors += convertSettingToData(["features", "splitpages", "enabled"], bool, default=False)
return errors
_pathSettings = os.path.join("data", "settings.json")
def loadSettingsFromFile():
if not os.path.isfile(_pathSettings):
return
file = None
try:
file = open(_pathSettings, "r")
settings = json.load(file)
settings = legacy.convertSettingsLegacy(settings, versionSettingsCurrent)
convertSettings.update(settings)
except Exception as e:
print("Could not load settings: ")
print(traceback.format_exc())
finally:
if file: file.close()
def saveSettingsToFile():
report("log", "Saving settings... ")
file = open(_pathSettings, "w")
json.dump(convertSettings, file)
file.close()
report("log", "Done\\n")
prgLoading.start(20)
convertEvent = threading.Event()
convertData = dict()
convertSettings = dict()
convertThread = threading.Thread(target=threadConvert, daemon=True)
convertThread.start()
reloadUI()
window.update()
loadSettingsFromFile()
writeSettingsToUI()
window.mainloop()
if name == "main": main()