117 lines
4.2 KiB
Python
117 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
"""Make the UP / page number / DOWN keys on every page follow the status page's ALL button.
|
||
|
|
|
||
|
|
The status page (page 19) carries coloured copies of Companion's own nav keys
|
||
|
|
(see make_page.py and nav_templates.json). This copies them over the built-in
|
||
|
|
nav keys on every other page, wherever those sit, using the same "copy button"
|
||
|
|
call as the Companion UI. Each key keeps its normal press action.
|
||
|
|
|
||
|
|
python3 nav_keys.py --dry-run list what would change
|
||
|
|
python3 nav_keys.py apply (also refreshes keys already converted)
|
||
|
|
python3 nav_keys.py --revert put Companion's built-in nav keys back everywhere
|
||
|
|
|
||
|
|
Only nav keys are touched. Every location changed is recorded in nav_locations.json.
|
||
|
|
"""
|
||
|
|
import argparse
|
||
|
|
import gzip
|
||
|
|
import json
|
||
|
|
import os
|
||
|
|
import urllib.error
|
||
|
|
import urllib.request
|
||
|
|
|
||
|
|
from make_page import NAV_LOCATIONS, NAV_MARKER
|
||
|
|
from push_page import Trpc, WebSocket
|
||
|
|
|
||
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
|
|
RECORD = os.path.join(HERE, "nav_locations.json")
|
||
|
|
NAV_TYPES = ("pageup", "pagenum", "pagedown")
|
||
|
|
|
||
|
|
|
||
|
|
def page_export(host, port, page):
|
||
|
|
url = "http://%s:%d/int/export/page/%d?includeSecrets=false" % (host, port, page)
|
||
|
|
try:
|
||
|
|
with urllib.request.urlopen(url, timeout=10) as r:
|
||
|
|
raw = r.read()
|
||
|
|
except urllib.error.HTTPError:
|
||
|
|
return None
|
||
|
|
try:
|
||
|
|
raw = gzip.decompress(raw)
|
||
|
|
except OSError:
|
||
|
|
pass
|
||
|
|
return json.loads(raw)
|
||
|
|
|
||
|
|
|
||
|
|
def nav_kind(control):
|
||
|
|
if control.get("type") in NAV_TYPES:
|
||
|
|
return control["type"]
|
||
|
|
notes = control.get("options", {}).get("notes", "") or ""
|
||
|
|
if control.get("type") == "button-layered" and notes.startswith(NAV_MARKER):
|
||
|
|
for kind in NAV_TYPES:
|
||
|
|
if "(%s)" % kind in notes:
|
||
|
|
return kind
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
def find_nav_keys(host, port, status_page):
|
||
|
|
"""[(page, row, column, kind)] for every nav key outside the status page."""
|
||
|
|
found, page = [], 1
|
||
|
|
while True:
|
||
|
|
export = page_export(host, port, page)
|
||
|
|
if export is None:
|
||
|
|
break
|
||
|
|
if page != status_page:
|
||
|
|
for r, cols in export["page"]["controls"].items():
|
||
|
|
for c, control in cols.items():
|
||
|
|
kind = nav_kind(control or {})
|
||
|
|
if kind:
|
||
|
|
found.append((page, int(r), int(c), kind))
|
||
|
|
page += 1
|
||
|
|
return found
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
cfg = json.load(open(os.path.join(HERE, "config.json")))
|
||
|
|
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||
|
|
ap.add_argument("--host", default="na-ingest.local")
|
||
|
|
ap.add_argument("--port", type=int, default=8000)
|
||
|
|
ap.add_argument("--dry-run", action="store_true")
|
||
|
|
ap.add_argument("--revert", action="store_true")
|
||
|
|
args = ap.parse_args()
|
||
|
|
status_page = cfg["page"]
|
||
|
|
|
||
|
|
record = json.load(open(RECORD)) if os.path.exists(RECORD) else {}
|
||
|
|
if args.revert:
|
||
|
|
targets = [(int(k.split("/")[0]), int(k.split("/")[1]), int(k.split("/")[2]), v) for k, v in record.items()]
|
||
|
|
else:
|
||
|
|
targets = find_nav_keys(args.host, args.port, status_page)
|
||
|
|
print("%d nav keys on %d pages" % (len(targets), len({t[0] for t in targets})))
|
||
|
|
if args.dry_run:
|
||
|
|
for t in targets:
|
||
|
|
print(" page %d row %d col %d: %s" % t)
|
||
|
|
return
|
||
|
|
|
||
|
|
ws = WebSocket(args.host, args.port, "/trpc")
|
||
|
|
done = 0
|
||
|
|
try:
|
||
|
|
api = Trpc(ws)
|
||
|
|
for page, row, col, kind in targets:
|
||
|
|
location = {"pageNumber": page, "row": row, "column": col}
|
||
|
|
if args.revert:
|
||
|
|
api.mutation("controls.resetControl", {"location": location, "newType": kind})
|
||
|
|
record.pop("%d/%d/%d" % (page, row, col), None)
|
||
|
|
else:
|
||
|
|
r, c = NAV_LOCATIONS[kind]
|
||
|
|
source = {"pageNumber": status_page, "row": int(r), "column": int(c)}
|
||
|
|
if not api.mutation("controls.copyControl", {"fromLocation": source, "toLocation": location}):
|
||
|
|
raise RuntimeError("copy to page %d row %d col %d failed" % (page, row, col))
|
||
|
|
record["%d/%d/%d" % (page, row, col)] = kind
|
||
|
|
done += 1
|
||
|
|
finally:
|
||
|
|
ws.close()
|
||
|
|
json.dump(record, open(RECORD, "w"), indent=1, sort_keys=True)
|
||
|
|
print("%s %d nav keys" % ("restored" if args.revert else "coloured", done))
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|