Fix: Removed duplicates from merge botch. Stable version of seismo_lab.py
This commit is contained in:
+5
-154
@@ -114,8 +114,6 @@ class BridgePanel(tk.Frame):
|
||||
on_capture_complete(bw_path, s3_path, label)— a capture segment finished
|
||||
"""
|
||||
|
||||
def __init__(self, parent: tk.Widget, on_bridge_started, on_bridge_stopped,
|
||||
on_capture_started=None, on_capture_complete=None, **kw):
|
||||
def __init__(self, parent: tk.Widget, on_bridge_started, on_bridge_stopped,
|
||||
on_capture_started=None, on_capture_complete=None, **kw):
|
||||
super().__init__(parent, bg=BG2, **kw)
|
||||
@@ -141,10 +139,6 @@ class BridgePanel(tk.Frame):
|
||||
self._cap_history: list[dict] = [] # {label, status, bw, s3}
|
||||
# mode
|
||||
self._mode = tk.StringVar(value="serial")
|
||||
# Capture state
|
||||
self._capturing = False
|
||||
self._cap_label: Optional[str] = None
|
||||
self._cap_history: list[dict] = [] # {label, status, bw, s3}
|
||||
self._build()
|
||||
self._poll_stdout()
|
||||
self._poll_tcp_log()
|
||||
@@ -220,7 +214,7 @@ class BridgePanel(tk.Frame):
|
||||
tk.Button(cfg, text="Browse", bg=BG3, fg=FG, relief="flat", cursor="hand2",
|
||||
font=MONO, command=self._choose_dir).grid(row=2, column=5, **pad)
|
||||
|
||||
# Row 2: buttons + status
|
||||
# Row 3: buttons + status
|
||||
btn_row = tk.Frame(self, bg=BG2)
|
||||
btn_row.pack(side=tk.TOP, fill=tk.X, padx=4, pady=2)
|
||||
|
||||
@@ -246,18 +240,6 @@ class BridgePanel(tk.Frame):
|
||||
command=self._stop_capture, state="disabled")
|
||||
self.stop_cap_btn.pack(side=tk.LEFT, padx=4)
|
||||
|
||||
tk.Frame(btn_row, bg=BG2, width=16).pack(side=tk.LEFT) # spacer
|
||||
|
||||
self.cap_btn = tk.Button(btn_row, text="⬤ New Capture", bg=ORANGE, fg="#000000",
|
||||
relief="flat", padx=10, cursor="hand2", font=MONO_B,
|
||||
command=self._start_capture, state="disabled")
|
||||
self.cap_btn.pack(side=tk.LEFT, padx=4)
|
||||
|
||||
self.stop_cap_btn = tk.Button(btn_row, text="■ Stop Capture", bg=BG3, fg=RED,
|
||||
relief="flat", padx=10, cursor="hand2", font=MONO_B,
|
||||
command=self._stop_capture, state="disabled")
|
||||
self.stop_cap_btn.pack(side=tk.LEFT, padx=4)
|
||||
|
||||
self.mark_btn = tk.Button(btn_row, text="Add Mark", bg=BG3, fg=FG,
|
||||
relief="flat", padx=10, cursor="hand2", font=MONO,
|
||||
command=self.add_mark, state="disabled")
|
||||
@@ -289,37 +271,11 @@ class BridgePanel(tk.Frame):
|
||||
self._hist_lb.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
||||
self._hist_lb.bind("<Double-Button-1>", self._on_hist_dblclick)
|
||||
|
||||
tk.Label(hist_outer, text="dbl-click to reload", bg=BG2, fg=FG_DIM,
|
||||
font=MONO_SM, anchor="e").pack(side=tk.RIGHT, padx=6)
|
||||
|
||||
# Capture history list
|
||||
hist_outer = tk.Frame(self, bg=BG2)
|
||||
hist_outer.pack(side=tk.TOP, fill=tk.X, padx=4, pady=(2, 0))
|
||||
|
||||
tk.Label(hist_outer, text="Captures:", bg=BG2, fg=FG_DIM,
|
||||
font=MONO_SM, anchor="w").pack(side=tk.LEFT, padx=(4, 6))
|
||||
|
||||
hist_inner = tk.Frame(hist_outer, bg=BG2)
|
||||
hist_inner.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
||||
|
||||
self._hist_lb = tk.Listbox(
|
||||
hist_inner, bg=BG3, fg=FG, font=MONO_SM,
|
||||
height=3, relief="flat", selectbackground=BG,
|
||||
selectforeground=ACCENT, activestyle="none",
|
||||
highlightthickness=0,
|
||||
)
|
||||
hist_vsb = ttk.Scrollbar(hist_inner, orient="vertical", command=self._hist_lb.yview)
|
||||
self._hist_lb.configure(yscrollcommand=hist_vsb.set)
|
||||
hist_vsb.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
self._hist_lb.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
||||
self._hist_lb.bind("<Double-Button-1>", self._on_hist_dblclick)
|
||||
|
||||
tk.Label(hist_outer, text="dbl-click to reload", bg=BG2, fg=FG_DIM,
|
||||
font=MONO_SM, anchor="e").pack(side=tk.RIGHT, padx=6)
|
||||
|
||||
# Log output
|
||||
self.log_view = scrolledtext.ScrolledText(
|
||||
self, height=14, font=MONO_SM,
|
||||
self, height=14, font=MONO_SM,
|
||||
bg=BG, fg=FG, insertbackground=FG,
|
||||
relief="flat", state="disabled",
|
||||
@@ -462,15 +418,12 @@ class BridgePanel(tk.Frame):
|
||||
self.start_btn.configure(state="disabled")
|
||||
self.stop_btn.configure(state="normal", bg=RED)
|
||||
self.cap_btn.configure(state="normal")
|
||||
self.cap_btn.configure(state="normal")
|
||||
self._append_log(f"== Bridge started [{ts}] ==\n")
|
||||
self._append_log(" Click 'New Capture' when ready to record.\n")
|
||||
self._on_started(struct_bin_path)
|
||||
|
||||
# Notify parent — no raw files yet, just the structured bin path
|
||||
self._on_started(struct_bin_path)
|
||||
|
||||
def stop_bridge(self) -> None:
|
||||
def _stop_serial(self) -> None:
|
||||
if self.process and self.process.poll() is None:
|
||||
self.process.terminate()
|
||||
try:
|
||||
@@ -480,17 +433,6 @@ class BridgePanel(tk.Frame):
|
||||
self._bridge_ended()
|
||||
self._on_stopped()
|
||||
|
||||
def _bridge_ended(self) -> None:
|
||||
self.status_var.set("Stopped")
|
||||
self.start_btn.configure(state="normal")
|
||||
self.stop_btn.configure(state="disabled", bg=BG3)
|
||||
self.cap_btn.configure(state="disabled")
|
||||
self.stop_cap_btn.configure(state="disabled", bg=BG3)
|
||||
self.mark_btn.configure(state="disabled")
|
||||
self._capturing = False
|
||||
self._cap_label = None
|
||||
self._append_log("== Bridge stopped ==\n")
|
||||
|
||||
def _reader_thread(self) -> None:
|
||||
if not self.process or not self.process.stdout:
|
||||
return
|
||||
@@ -531,9 +473,7 @@ class BridgePanel(tk.Frame):
|
||||
# ── capture control ───────────────────────────────────────────────────
|
||||
|
||||
def _start_capture(self) -> None:
|
||||
"""Ask for a label and tell the bridge to start writing raw tap files."""
|
||||
if not self.process or self.process.poll() is not None:
|
||||
return
|
||||
"""Ask for a label and start writing raw tap files (serial subprocess or TCP files)."""
|
||||
label = simpledialog.askstring(
|
||||
"New Capture",
|
||||
"Label for this capture\n(e.g. 'recording_mode_continuous').\nLeave blank for timestamp only:",
|
||||
@@ -542,88 +482,6 @@ class BridgePanel(tk.Frame):
|
||||
if label is None:
|
||||
return # user hit Cancel
|
||||
label = label.strip()
|
||||
try:
|
||||
self.process.stdin.write(f"CAP_START:{label}\n")
|
||||
self.process.stdin.flush()
|
||||
except Exception as e:
|
||||
messagebox.showerror("Error", f"Failed to start capture:\n{e}")
|
||||
return
|
||||
self._capturing = True
|
||||
self._cap_label = label or datetime.datetime.now().strftime("%H%M%S")
|
||||
self.cap_btn.configure(state="disabled")
|
||||
self.stop_cap_btn.configure(state="normal", bg=RED)
|
||||
self.mark_btn.configure(state="normal")
|
||||
self._append_log(f"[CAPTURE] Starting: {self._cap_label!r}...\n")
|
||||
# Add to history as recording (paths filled in when [CAP_START] arrives)
|
||||
self._cap_history.append({"label": self._cap_label, "status": "recording",
|
||||
"bw": None, "s3": None})
|
||||
self._refresh_hist()
|
||||
|
||||
def _stop_capture(self) -> None:
|
||||
"""Tell the bridge to flush and close the current raw tap files."""
|
||||
if not self.process or self.process.poll() is not None:
|
||||
return
|
||||
try:
|
||||
self.process.stdin.write("CAP_STOP\n")
|
||||
self.process.stdin.flush()
|
||||
except Exception as e:
|
||||
messagebox.showerror("Error", f"Failed to stop capture:\n{e}")
|
||||
# UI is updated when [CAP_STOP] arrives in stdout
|
||||
|
||||
def _on_cap_started_msg(self, bw_path: str, s3_path: str) -> None:
|
||||
"""Called when bridge confirms capture has started (files are open)."""
|
||||
# Fill in paths for the last 'recording' history entry
|
||||
for entry in reversed(self._cap_history):
|
||||
if entry["status"] == "recording" and entry["bw"] is None:
|
||||
entry["bw"] = bw_path
|
||||
entry["s3"] = s3_path
|
||||
break
|
||||
if self._on_cap_started:
|
||||
self._on_cap_started(bw_path, s3_path, self._cap_label or "")
|
||||
|
||||
def _on_cap_stopped_msg(self, bw_path: str, s3_path: str) -> None:
|
||||
"""Called when bridge confirms capture has stopped (files are closed)."""
|
||||
label = self._cap_label or "capture"
|
||||
# Mark history entry as done
|
||||
for entry in reversed(self._cap_history):
|
||||
if entry["status"] == "recording":
|
||||
entry["status"] = "done"
|
||||
entry["bw"] = bw_path
|
||||
entry["s3"] = s3_path
|
||||
break
|
||||
self._refresh_hist()
|
||||
self._capturing = False
|
||||
self._cap_label = None
|
||||
self.cap_btn.configure(state="normal")
|
||||
self.stop_cap_btn.configure(state="disabled", bg=BG3)
|
||||
self._append_log(f"[CAPTURE] Done: {label!r} — ready in Analyzer\n")
|
||||
if self._on_cap_complete:
|
||||
self._on_cap_complete(bw_path, s3_path, label)
|
||||
|
||||
def _refresh_hist(self) -> None:
|
||||
self._hist_lb.delete(0, tk.END)
|
||||
for entry in self._cap_history:
|
||||
icon = "🔴" if entry["status"] == "recording" else "✅"
|
||||
label = entry["label"] or "(unlabeled)"
|
||||
self._hist_lb.insert(tk.END, f" {icon} {label}")
|
||||
if self._cap_history:
|
||||
self._hist_lb.see(tk.END)
|
||||
|
||||
def _on_hist_dblclick(self, _e=None) -> None:
|
||||
sel = self._hist_lb.curselection()
|
||||
if not sel:
|
||||
return
|
||||
entry = self._cap_history[sel[0]]
|
||||
if entry["status"] == "done" and entry["bw"] and entry["s3"]:
|
||||
if self._on_cap_complete:
|
||||
self._on_cap_complete(entry["bw"], entry["s3"], entry["label"])
|
||||
|
||||
# ── mark ──────────────────────────────────────────────────────────────
|
||||
|
||||
def add_mark(self) -> None:
|
||||
if not self.process or not self.process.stdin or self.process.poll() is not None:
|
||||
return
|
||||
label = label.strip()
|
||||
self._capturing = True
|
||||
self._cap_label = label or datetime.datetime.now().strftime("%H%M%S")
|
||||
|
||||
@@ -664,6 +522,7 @@ class BridgePanel(tk.Frame):
|
||||
self._append_log(f"[CAPTURE] Starting: {self._cap_label!r}...\n")
|
||||
|
||||
def _stop_capture(self) -> None:
|
||||
"""Flush and close the current raw tap files (TCP) or signal the bridge subprocess (serial)."""
|
||||
if self._mode.get() == "tcp":
|
||||
with self._tcp_cap_lock:
|
||||
bw_path = self._tcp_cap_bw_path
|
||||
@@ -686,6 +545,7 @@ class BridgePanel(tk.Frame):
|
||||
self.process.stdin.flush()
|
||||
except Exception as e:
|
||||
messagebox.showerror("Error", f"Failed to stop capture:\n{e}")
|
||||
# UI is updated when [CAP_STOP] arrives in stdout
|
||||
|
||||
# ── TCP mode ──────────────────────────────────────────────────────────
|
||||
|
||||
@@ -1173,14 +1033,6 @@ class AnalyzerPanel(tk.Frame):
|
||||
self.state.bw_path = bwp
|
||||
self._do_analyze(s3p, bwp)
|
||||
|
||||
def _browse_bin(self) -> None:
|
||||
path = filedialog.askopenfilename(
|
||||
title="Select session .bin file",
|
||||
filetypes=[("Binary", "*.bin"), ("All files", "*.*")],
|
||||
)
|
||||
if path:
|
||||
self.bin_var.set(path)
|
||||
|
||||
def _do_analyze(self, s3_path: Path, bw_path: Path) -> None:
|
||||
self.status_var.set("Parsing...")
|
||||
self.update_idletasks()
|
||||
@@ -1611,7 +1463,6 @@ class AnalyzerPanel(tk.Frame):
|
||||
w.configure(state="normal"); w.insert(tk.END, "\n"); w.configure(state="disabled")
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Serial Watch panel — tap the RS-232 line between device and modem
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user