""" vu_meter.py — VU-meter widget der tegner L og R kanaler. Opdateres via set_levels(left, right) med værdier 0.0–1.0. """ from PyQt6.QtWidgets import QWidget from PyQt6.QtCore import Qt, QTimer from PyQt6.QtGui import QPainter, QColor import random NUM_BARS = 14 BAR_W = 14 BAR_H = 4 BAR_GAP = 2 CHAN_GAP = 6 PADDING = 4 COLOR_OFF = QColor("#1a2218") COLOR_GREEN = QColor("#28a050") COLOR_YELLOW = QColor("#c8a020") COLOR_RED = QColor("#c83020") # Grænser for farver (bar-indeks fra bunden) YELLOW_FROM = NUM_BARS - 4 RED_FROM = NUM_BARS - 2 class VUMeter(QWidget): def __init__(self, parent=None): super().__init__(parent) self._left = 0.0 self._right = 0.0 self._peak_l = 0.0 self._peak_r = 0.0 self._dark = True total_h = NUM_BARS * (BAR_H + BAR_GAP) + PADDING * 2 + 16 # +16 til label total_w = (BAR_W + CHAN_GAP) * 2 + PADDING * 2 self.setFixedSize(total_w, total_h) def set_dark(self, dark: bool): self._dark = dark self.update() def set_levels(self, left: float, right: float): """Sæt niveauer 0.0–1.0. Kaldes fra afspiller-tråden via signal.""" self._left = max(0.0, min(1.0, left)) self._right = max(0.0, min(1.0, right)) self._peak_l = max(self._peak_l * 0.92, self._left) self._peak_r = max(self._peak_r * 0.92, self._right) self.update() def reset(self): self._left = self._right = self._peak_l = self._peak_r = 0.0 self.update() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.RenderHint.Antialiasing) off_color = QColor("#d0d8cc") if not self._dark else COLOR_OFF for ch_idx, level in enumerate([self._left, self._right]): x = PADDING + ch_idx * (BAR_W + CHAN_GAP) active_bars = int(level * NUM_BARS) for bar_idx in range(NUM_BARS): y = PADDING + (NUM_BARS - 1 - bar_idx) * (BAR_H + BAR_GAP) if bar_idx < active_bars: if bar_idx >= RED_FROM: color = COLOR_RED elif bar_idx >= YELLOW_FROM: color = COLOR_YELLOW else: color = COLOR_GREEN else: color = off_color painter.fillRect(x, y, BAR_W, BAR_H, QColor(color.red(), color.green(), color.blue(), 220)) # Kanal-labels label_y = PADDING + NUM_BARS * (BAR_H + BAR_GAP) + 4 painter.setPen(QColor("#5a6070")) font = painter.font() font.setPointSize(8) font.setFamily("Courier New") painter.setFont(font) for ch_idx, label in enumerate(["L", "R"]): x = PADDING + ch_idx * (BAR_W + CHAN_GAP) + BAR_W // 2 painter.drawText(x - 4, label_y + 10, label) painter.end()