From 026373dd77015ccda30faec20141976b65e5b86b Mon Sep 17 00:00:00 2001 From: Chris Frankland-Wright Date: Tue, 1 Jul 2025 21:45:34 +0100 Subject: [PATCH] reverted back to working version --- timeturner.py | 97 ++++++++++++++++++++------------------------------- 1 file changed, 38 insertions(+), 59 deletions(-) diff --git a/timeturner.py b/timeturner.py index 403f3aa..dce1be1 100644 --- a/timeturner.py +++ b/timeturner.py @@ -1,88 +1,67 @@ #!/usr/bin/env python3 -import os -import subprocess import curses -import time +import subprocess import shutil -import select -import signal +import time -FIFO_PATH = "/tmp/ltcpipe" - -def setup_fifo(): - if os.path.exists(FIFO_PATH): - os.remove(FIFO_PATH) - os.mkfifo(FIFO_PATH) - -def start_arecord(): - return subprocess.Popen([ - "arecord", "-f", "S16_LE", "-c", "1", "-r", "48000", "-D", "hw:2,0", FIFO_PATH - ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - -def start_ltcdump(): - return subprocess.Popen([ - "ltcdump", "-f", FIFO_PATH - ], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True, bufsize=1) - -def clean_up_processes(*procs): - for proc in procs: - if proc and proc.poll() is None: - proc.terminate() - try: - proc.wait(timeout=1) - except subprocess.TimeoutExpired: - proc.kill() - if os.path.exists(FIFO_PATH): - os.remove(FIFO_PATH) +def start_ltc_stream(): + # Launch ffmpeg piped into ltcdump + ffmpeg = subprocess.Popen( + ["ffmpeg", "-f", "alsa", "-i", "default", "-ac", "1", "-ar", "48000", "-f", "s16le", "-"], + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL + ) + ltcdump = subprocess.Popen( + ["ltcdump", "-f", "-"], + stdin=ffmpeg.stdout, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + text=True + ) + ffmpeg.stdout.close() # Let ltcdump consume the pipe + return ffmpeg, ltcdump def main(stdscr): curses.curs_set(0) stdscr.nodelay(True) - setup_fifo() - arecord_proc = start_arecord() - ltcdump_proc = start_ltcdump() + stdscr.addstr(1, 2, "🌀 NTP Timeturner Status") + stdscr.addstr(3, 4, "Streaming LTC from default input...") + + ffmpeg_proc, ltcdump_proc = start_ltc_stream() latest_tc = "⌛ Waiting for LTC..." - last_update = time.time() + last_refresh = time.time() try: while True: - # Non-blocking read from ltcdump - rlist, _, _ = select.select([ltcdump_proc.stdout], [], [], 0) - if rlist: - line = ltcdump_proc.stdout.readline() - if line and line[0].isdigit(): - latest_tc = line.strip() - last_update = time.time() - - # If stream stalls or breaks - if time.time() - last_update > 1: - if ltcdump_proc.poll() is not None or arecord_proc.poll() is not None: - latest_tc = "💥 Stream stopped or decoder crashed" - else: - latest_tc = "⚠️ No LTC signal detected" - - # Draw interface - stdscr.erase() + stdscr.clear() stdscr.addstr(1, 2, "🌀 NTP Timeturner Status") - stdscr.addstr(3, 4, f"Reading LTC from hw:2,0 via FIFO...") + stdscr.addstr(3, 4, "Streaming LTC from default input...") stdscr.addstr(5, 6, f"🕰️ LTC Timecode: {latest_tc}") stdscr.refresh() - time.sleep(0.04) # 25Hz refresh + # Check if new LTC line available + if ltcdump_proc.stdout.readable(): + line = ltcdump_proc.stdout.readline().strip() + if line and line[0].isdigit(): + latest_tc = line + + # Limit screen redraw to ~10fps + time.sleep(0.1) except KeyboardInterrupt: - stdscr.addstr(8, 6, "🔚 Exiting gracefully...") + stdscr.addstr(8, 6, "🔚 Shutting down...") stdscr.refresh() time.sleep(1) finally: - clean_up_processes(arecord_proc, ltcdump_proc) + ffmpeg_proc.terminate() + ltcdump_proc.terminate() if __name__ == "__main__": - if not shutil.which("ltcdump") or not shutil.which("arecord"): - print("❌ Required tools not found (ltcdump or arecord). Install and retry.") + if not shutil.which("ltcdump") or not shutil.which("ffmpeg"): + print("❌ Required tools not found (ltcdump or ffmpeg). Install and retry.") exit(1) curses.wrapper(main)