refactor: remove dead code from isr.py
- Drop unused struct import, AudioDevice.extra/description fields - Remove unused get_preferred_backend() and the backend priority machinery (only one backend exists) - Deduplicate SoundcardRecorder.close_current_file via super() - Remove duplicate config-exists check in main() - Simplify --list-devices output: drop dead monitor grouping and the nonexistent pipewire backend example Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,6 @@ import os
|
||||
import sys
|
||||
import time
|
||||
import wave
|
||||
import struct
|
||||
import signal
|
||||
import logging
|
||||
import threading
|
||||
@@ -18,7 +17,7 @@ import configparser
|
||||
import subprocess
|
||||
import shutil
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any, List, Callable
|
||||
@@ -57,8 +56,6 @@ class AudioDevice:
|
||||
backend: str # Backend name ('alsa')
|
||||
is_default: bool = False # Is system default
|
||||
is_monitor: bool = False # Is a monitor/loopback source
|
||||
description: str = "" # Extended description
|
||||
extra: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def __str__(self):
|
||||
flags = []
|
||||
@@ -74,7 +71,6 @@ class AudioBackend(ABC):
|
||||
"""Abstract base for audio capture backends."""
|
||||
|
||||
name: str = "base"
|
||||
priority: int = 0 # Higher = preferred
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
@@ -99,7 +95,6 @@ class ALSABackend(AudioBackend):
|
||||
"""ALSA backend using arecord (raw PCM output, no sound server required)."""
|
||||
|
||||
name = "alsa"
|
||||
priority = 5 # Lowest priority — direct hardware access, use when no sound server runs
|
||||
|
||||
@classmethod
|
||||
def is_available(cls) -> bool:
|
||||
@@ -251,19 +246,12 @@ class AudioSystem:
|
||||
def get_backend(self, name: str) -> Optional[AudioBackend]:
|
||||
return self._backends.get(name)
|
||||
|
||||
def get_preferred_backend(self) -> Optional[AudioBackend]:
|
||||
"""Get the highest priority available backend."""
|
||||
if not self._backends:
|
||||
return None
|
||||
return max(self._backends.values(), key=lambda b: b.__class__.priority)
|
||||
|
||||
def list_all_devices(self) -> List[AudioDevice]:
|
||||
"""List devices from all available backends."""
|
||||
all_devices = []
|
||||
seen_names = set()
|
||||
|
||||
# Get devices from backends in priority order
|
||||
for cls in sorted(self._backend_classes, key=lambda c: -c.priority):
|
||||
for cls in self._backend_classes:
|
||||
if cls.name in self._backends:
|
||||
for dev in cls.list_devices():
|
||||
# Deduplicate by name (same device may appear in multiple backends)
|
||||
@@ -733,16 +721,9 @@ class SoundcardRecorder(BaseRecorder):
|
||||
self.audio_buffer.clear()
|
||||
|
||||
def close_current_file(self):
|
||||
"""Close current recording file."""
|
||||
"""Flush any buffered audio, then close the current recording file."""
|
||||
self._flush_buffer_to_file()
|
||||
if self.current_file:
|
||||
try:
|
||||
self.current_file.close()
|
||||
self.logger.info(f"[{self.name}] Closed: {self.current_filename}")
|
||||
except Exception as e:
|
||||
self.logger.error(f"[{self.name}] Error closing file: {e}")
|
||||
self.current_file = None
|
||||
self.current_filename = None
|
||||
super().close_current_file()
|
||||
|
||||
def record(self):
|
||||
"""Main recording loop."""
|
||||
@@ -990,22 +971,15 @@ def list_audio_devices():
|
||||
print(" ISR Audio Device Discovery")
|
||||
print("=" * 70)
|
||||
|
||||
# Check available backends
|
||||
available_backends = []
|
||||
if ALSABackend.is_available():
|
||||
available_backends.append(('alsa', 'ALSA (arecord)', 5))
|
||||
|
||||
if not available_backends:
|
||||
if not ALSABackend.is_available():
|
||||
print("\n No audio backends available!")
|
||||
print("\n Install one of:")
|
||||
print(" sudo apt install alsa-utils (ALSA, always available on Linux)")
|
||||
print("\n Install ALSA utilities:")
|
||||
print(" sudo apt install alsa-utils")
|
||||
print()
|
||||
return
|
||||
|
||||
print("\n Available Backends:")
|
||||
for name, label, priority in sorted(available_backends, key=lambda x: -x[2]):
|
||||
marker = " (preferred)" if priority == max(b[2] for b in available_backends) else ""
|
||||
print(f" - {label}{marker}")
|
||||
print(" - ALSA (arecord)")
|
||||
|
||||
# Initialize audio system and list devices
|
||||
audio_system = AudioSystem(logger)
|
||||
@@ -1016,42 +990,21 @@ def list_audio_devices():
|
||||
print()
|
||||
return
|
||||
|
||||
# Group by type
|
||||
monitors = [d for d in devices if d.is_monitor]
|
||||
inputs = [d for d in devices if not d.is_monitor]
|
||||
|
||||
if inputs:
|
||||
print("\n Input Devices:")
|
||||
print(" " + "-" * 68)
|
||||
for dev in inputs:
|
||||
flags = []
|
||||
if dev.is_default:
|
||||
flags.append("DEFAULT")
|
||||
flag_str = f" [{', '.join(flags)}]" if flags else ""
|
||||
print(f"\n {dev.name}{flag_str}")
|
||||
print(f" ID: {dev.id} | Backend: {dev.backend}")
|
||||
print(f" Channels: {dev.channels} | Sample Rate: {dev.sample_rate} Hz")
|
||||
|
||||
if monitors:
|
||||
print("\n Monitor/Loopback Sources:")
|
||||
print(" " + "-" * 68)
|
||||
for dev in monitors:
|
||||
flags = ["MONITOR"]
|
||||
if dev.is_default:
|
||||
flags.append("DEFAULT")
|
||||
flag_str = f" [{', '.join(flags)}]"
|
||||
print(f"\n {dev.name}{flag_str}")
|
||||
print(f" ID: {dev.id} | Backend: {dev.backend}")
|
||||
print(f" Channels: {dev.channels} | Sample Rate: {dev.sample_rate} Hz")
|
||||
print("\n Input Devices:")
|
||||
print(" " + "-" * 68)
|
||||
for dev in devices:
|
||||
flag_str = " [DEFAULT]" if dev.is_default else ""
|
||||
print(f"\n {dev.name}{flag_str}")
|
||||
print(f" ID: {dev.id} | Backend: {dev.backend}")
|
||||
print(f" Channels: {dev.channels} | Sample Rate: {dev.sample_rate} Hz")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print(" Configuration Examples:")
|
||||
print("-" * 70)
|
||||
print(" device = default # Use system default input")
|
||||
print(" device = monitor # Use first monitor/loopback source")
|
||||
print(" device = <name> # Match by partial name")
|
||||
print(" device = <id> # Use exact backend ID")
|
||||
print(" backend = pipewire # Force specific backend")
|
||||
print(" device = <id> # Use exact ALSA ID, e.g. hw:0,0")
|
||||
print(" device = <pcm> # Any ALSA PCM name from asound.conf, e.g. shared_mic")
|
||||
print("=" * 70 + "\n")
|
||||
|
||||
|
||||
@@ -1061,17 +1014,11 @@ def main():
|
||||
list_audio_devices()
|
||||
return
|
||||
|
||||
# Get config file
|
||||
# Get config file (RecorderManager exits with a usage message if it's missing)
|
||||
config_file = 'config.ini'
|
||||
if len(sys.argv) > 1:
|
||||
config_file = sys.argv[1]
|
||||
|
||||
if not os.path.exists(config_file):
|
||||
print(f"Error: Configuration file '{config_file}' not found!")
|
||||
print("Usage: python ISR.py [config.ini]")
|
||||
print(" python ISR.py --list-devices")
|
||||
sys.exit(1)
|
||||
|
||||
# Docker sends SIGTERM before SIGKILL — treat it the same as Ctrl+C
|
||||
def _sigterm(sig, frame):
|
||||
raise KeyboardInterrupt()
|
||||
|
||||
Reference in New Issue
Block a user