✨ feat(panel): improve recording indicator reliability and timer accuracy
This commit is contained in:
1 parent
8a2efa3b5a
commit
d7287e50d4
1 file changed
+156
-38
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
@@ -9,8 +10,6 @@ from fabric.widgets.button import Button
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.svg import Svg
|
||||
|
||||
# FIX: Make the timer consistent with the recording start time
|
||||
|
||||
|
||||
class RecordingIndicator(Button):
|
||||
def __init__(self, **kwargs):
|
||||
@@ -18,6 +17,13 @@ class RecordingIndicator(Button):
|
||||
|
||||
self.script_path = get_relative_path("../../../scripts/screen-capture.sh")
|
||||
self.recording_start_time = None
|
||||
self.last_process_check = 0
|
||||
self.process_check_interval = 1.0
|
||||
self.timer_update_interval = 1000
|
||||
self.status_check_interval = 2000
|
||||
|
||||
self.timer_timeout_id = None
|
||||
self.status_timeout_id = None
|
||||
|
||||
self.recording_icon = Svg(
|
||||
name="indicators-icon",
|
||||
@@ -41,69 +47,181 @@ class RecordingIndicator(Button):
|
||||
self.add(self.recording_box)
|
||||
|
||||
self.connect("clicked", self.on_stop_recording)
|
||||
self.connect("button-press-event", self.on_button_press)
|
||||
self.hide()
|
||||
|
||||
GLib.timeout_add(1, self._delayed_init)
|
||||
GLib.timeout_add(100, self._delayed_init)
|
||||
|
||||
def check_recording_status(self):
|
||||
def on_button_press(self, *args):
|
||||
GLib.timeout_add(100, lambda: self.remove_style_class("pressed") or False)
|
||||
return False
|
||||
|
||||
def is_wf_recorder_running(self):
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[self.script_path, "status"], capture_output=True, text=True, timeout=2
|
||||
["pgrep", "-x", "wf-recorder"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=1,
|
||||
)
|
||||
is_recording = result.stdout.strip() == "true"
|
||||
return result.returncode == 0
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def check_recording_status(self):
|
||||
current_time = time.time()
|
||||
self.last_process_check = current_time
|
||||
|
||||
try:
|
||||
is_recording = self.is_wf_recorder_running()
|
||||
|
||||
if is_recording:
|
||||
if not self.get_visible():
|
||||
self.show()
|
||||
self.set_visible(True)
|
||||
if self.timer_timeout_id is None:
|
||||
self.timer_timeout_id = GLib.timeout_add(
|
||||
self.timer_update_interval, self.update_timer_display
|
||||
)
|
||||
|
||||
# Get the recording start time if we don't have it
|
||||
if self.recording_start_time is None:
|
||||
self.recording_start_time = self.get_recording_start_time()
|
||||
|
||||
# Update the recording time display
|
||||
if self.recording_start_time:
|
||||
elapsed_seconds = int(time.time() - self.recording_start_time)
|
||||
minutes = elapsed_seconds // 60
|
||||
seconds = elapsed_seconds % 60
|
||||
time_text = f"{minutes:02d}:{seconds:02d}"
|
||||
self.time_label.set_markup(time_text)
|
||||
self.set_tooltip_text(
|
||||
f"Recording in progress ({minutes:02d}:{
|
||||
seconds:02d}) - Click to stop"
|
||||
)
|
||||
else:
|
||||
self.set_tooltip_text("Recording in progress - Click to stop")
|
||||
self.update_timer_display()
|
||||
else:
|
||||
if self.get_visible():
|
||||
self.hide()
|
||||
self.recording_start_time = None
|
||||
self.set_visible(False)
|
||||
self.cleanup_recording_state()
|
||||
|
||||
except Exception:
|
||||
# If we can't check status, hide the indicator
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] Error checking recording status: {e}")
|
||||
if self.get_visible():
|
||||
self.hide()
|
||||
self.recording_start_time = None
|
||||
self.set_visible(False)
|
||||
self.cleanup_recording_state()
|
||||
|
||||
return True # Continue the timeout
|
||||
return True
|
||||
|
||||
def update_timer_display(self):
|
||||
if not self.get_visible() or self.recording_start_time is None:
|
||||
return False
|
||||
|
||||
try:
|
||||
elapsed_seconds = int(time.time() - self.recording_start_time)
|
||||
minutes = elapsed_seconds // 60
|
||||
seconds = elapsed_seconds % 60
|
||||
time_text = f"{minutes:02d}:{seconds:02d}"
|
||||
|
||||
self.time_label.set_markup(time_text)
|
||||
self.set_tooltip_text(
|
||||
f"Recording in progress ({time_text}) - Click to stop"
|
||||
)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] Error updating timer display: {e}")
|
||||
return False
|
||||
|
||||
def cleanup_recording_state(self):
|
||||
self.recording_start_time = None
|
||||
|
||||
if self.timer_timeout_id:
|
||||
GLib.source_remove(self.timer_timeout_id)
|
||||
self.timer_timeout_id = None
|
||||
|
||||
def get_recording_start_time(self):
|
||||
"""Get the recording start time from the file"""
|
||||
start_time_file = "/tmp/recording_start_time.txt"
|
||||
|
||||
try:
|
||||
with open("/tmp/recording_start_time.txt", "r") as f:
|
||||
return float(f.read().strip())
|
||||
except Exception:
|
||||
return None
|
||||
if not os.path.exists(start_time_file):
|
||||
return None
|
||||
|
||||
file_mtime = os.path.getmtime(start_time_file)
|
||||
|
||||
with open(start_time_file, "r") as f:
|
||||
content = f.read().strip()
|
||||
if content:
|
||||
recorded_time = float(content)
|
||||
|
||||
current_time = time.time()
|
||||
if abs(recorded_time - current_time) > 3600:
|
||||
return file_mtime
|
||||
|
||||
return recorded_time
|
||||
else:
|
||||
return file_mtime
|
||||
|
||||
except (ValueError, OSError):
|
||||
try:
|
||||
return os.path.getmtime(start_time_file)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
def on_stop_recording(self, *args):
|
||||
try:
|
||||
subprocess.Popen([self.script_path, "record", "stop"])
|
||||
except Exception as e:
|
||||
print(f"Error stopping recording: {e}")
|
||||
self.set_visible(False)
|
||||
self.cleanup_recording_state()
|
||||
|
||||
def send_stop_command():
|
||||
try:
|
||||
subprocess.Popen(
|
||||
[self.script_path, "record", "stop"],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] Error sending stop command: {e}")
|
||||
|
||||
GLib.idle_add(send_stop_command)
|
||||
GLib.timeout_add(500, self._verify_recording_stopped)
|
||||
GLib.timeout_add(1500, self._verify_recording_stopped)
|
||||
GLib.timeout_add(3000, self._verify_recording_stopped)
|
||||
|
||||
except Exception:
|
||||
self.set_visible(False)
|
||||
self.cleanup_recording_state()
|
||||
|
||||
def _verify_recording_stopped(self):
|
||||
try:
|
||||
if self.is_wf_recorder_running():
|
||||
if self.recording_start_time is None:
|
||||
self.recording_start_time = self.get_recording_start_time()
|
||||
|
||||
if self.recording_start_time:
|
||||
self.set_visible(True)
|
||||
self.update_timer_display()
|
||||
|
||||
if self.timer_timeout_id is None:
|
||||
self.timer_timeout_id = GLib.timeout_add(
|
||||
self.timer_update_interval, self.update_timer_display
|
||||
)
|
||||
|
||||
else:
|
||||
self.set_visible(False)
|
||||
self.cleanup_recording_state()
|
||||
|
||||
except Exception:
|
||||
self.set_visible(False)
|
||||
self.cleanup_recording_state()
|
||||
|
||||
return False
|
||||
|
||||
def _delayed_init(self):
|
||||
try:
|
||||
self.check_recording_status()
|
||||
self.timeout_id = GLib.timeout_add(5000, self.check_recording_status)
|
||||
self.status_timeout_id = GLib.timeout_add(
|
||||
self.status_check_interval, self.check_recording_status
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] Error in delayed recording indicator init: {e}")
|
||||
return False # Don't repeat this timeout
|
||||
return False
|
||||
|
||||
def destroy(self):
|
||||
if self.timer_timeout_id:
|
||||
GLib.source_remove(self.timer_timeout_id)
|
||||
self.timer_timeout_id = None
|
||||
|
||||
if self.status_timeout_id:
|
||||
GLib.source_remove(self.status_timeout_id)
|
||||
self.status_timeout_id = None
|
||||
|
||||
super().destroy()
|
||||
Reference in new issue
Block a user