Videre
This commit is contained in:
@@ -1,21 +1,21 @@
|
|||||||
# -*- mode: python ; coding: utf-8 -*-
|
# -*- mode: python ; coding: utf-8 -*-
|
||||||
|
from PyInstaller.utils.hooks import collect_all, collect_submodules
|
||||||
|
|
||||||
block_cipher = None
|
block_cipher = None
|
||||||
|
|
||||||
|
# Saml ALT fra PyQt6 inkl. plugins og DLL-filer
|
||||||
|
pyqt6_datas, pyqt6_binaries, pyqt6_hiddenimports = collect_all('PyQt6')
|
||||||
|
|
||||||
a = Analysis(
|
a = Analysis(
|
||||||
['main.py'],
|
['main.py'],
|
||||||
pathex=['.'],
|
pathex=['.'],
|
||||||
binaries=[],
|
binaries=pyqt6_binaries,
|
||||||
datas=[],
|
datas=pyqt6_datas,
|
||||||
hiddenimports=[
|
hiddenimports=pyqt6_hiddenimports + [
|
||||||
# PyQt6 — skal alle med eksplicit
|
'PyQt6.sip',
|
||||||
'PyQt6',
|
|
||||||
'PyQt6.QtCore',
|
'PyQt6.QtCore',
|
||||||
'PyQt6.QtGui',
|
'PyQt6.QtGui',
|
||||||
'PyQt6.QtWidgets',
|
'PyQt6.QtWidgets',
|
||||||
'PyQt6.QtNetwork',
|
|
||||||
'PyQt6.sip',
|
|
||||||
'PyQt6.QtPrintSupport',
|
|
||||||
# UI moduler
|
# UI moduler
|
||||||
'ui.main_window',
|
'ui.main_window',
|
||||||
'ui.playlist_panel',
|
'ui.playlist_panel',
|
||||||
@@ -29,50 +29,23 @@ a = Analysis(
|
|||||||
'ui.settings_dialog',
|
'ui.settings_dialog',
|
||||||
'ui.playlist_manager',
|
'ui.playlist_manager',
|
||||||
'ui.next_up_bar',
|
'ui.next_up_bar',
|
||||||
# Player
|
# Player + local
|
||||||
'player.player',
|
'player.player',
|
||||||
# Local
|
|
||||||
'local.local_db',
|
'local.local_db',
|
||||||
'local.tag_reader',
|
'local.tag_reader',
|
||||||
'local.file_watcher',
|
'local.file_watcher',
|
||||||
# Biblioteker
|
# Biblioteker
|
||||||
'mutagen',
|
'mutagen', 'mutagen.mp3', 'mutagen.id3', 'mutagen.flac',
|
||||||
'mutagen.mp3',
|
'mutagen.mp4', 'mutagen.oggvorbis', 'mutagen.ogg',
|
||||||
'mutagen.id3',
|
'mutagen.wave', 'mutagen.aiff', 'mutagen.asf',
|
||||||
'mutagen.flac',
|
'watchdog', 'watchdog.observers', 'watchdog.events',
|
||||||
'mutagen.mp4',
|
|
||||||
'mutagen.oggvorbis',
|
|
||||||
'mutagen.ogg',
|
|
||||||
'mutagen.wave',
|
|
||||||
'mutagen.aiff',
|
|
||||||
'mutagen.asf',
|
|
||||||
'watchdog',
|
|
||||||
'watchdog.observers',
|
|
||||||
'watchdog.observers.fsevents',
|
|
||||||
'watchdog.observers.inotify',
|
|
||||||
'watchdog.observers.winapi',
|
'watchdog.observers.winapi',
|
||||||
'watchdog.events',
|
'vlc', 'sqlite3',
|
||||||
'watchdog.tricks',
|
|
||||||
'vlc',
|
|
||||||
'sqlite3',
|
|
||||||
'json',
|
|
||||||
'threading',
|
|
||||||
'pathlib',
|
|
||||||
'urllib.request',
|
|
||||||
'urllib.parse',
|
|
||||||
],
|
],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
excludes=[
|
excludes=['tkinter', 'matplotlib', 'pandas', 'scipy', 'IPython'],
|
||||||
'tkinter',
|
|
||||||
'matplotlib',
|
|
||||||
'pandas',
|
|
||||||
'scipy',
|
|
||||||
'PIL',
|
|
||||||
'IPython',
|
|
||||||
'jupyter',
|
|
||||||
],
|
|
||||||
win_no_prefer_redirects=False,
|
win_no_prefer_redirects=False,
|
||||||
win_private_assemblies=False,
|
win_private_assemblies=False,
|
||||||
cipher=block_cipher,
|
cipher=block_cipher,
|
||||||
@@ -90,8 +63,8 @@ exe = EXE(
|
|||||||
debug=False,
|
debug=False,
|
||||||
bootloader_ignore_signals=False,
|
bootloader_ignore_signals=False,
|
||||||
strip=False,
|
strip=False,
|
||||||
upx=True,
|
upx=False, # UPX kan give problemer med PyQt6 DLL-filer
|
||||||
console=True, # Slå til så du kan se fejlbeskeder
|
console=True, # Vis fejlbeskeder
|
||||||
disable_windowed_traceback=False,
|
disable_windowed_traceback=False,
|
||||||
target_arch=None,
|
target_arch=None,
|
||||||
codesign_identity=None,
|
codesign_identity=None,
|
||||||
@@ -105,7 +78,7 @@ coll = COLLECT(
|
|||||||
a.zipfiles,
|
a.zipfiles,
|
||||||
a.datas,
|
a.datas,
|
||||||
strip=False,
|
strip=False,
|
||||||
upx=True,
|
upx=False,
|
||||||
upx_exclude=[],
|
upx_exclude=[],
|
||||||
name='LineDancePlayer',
|
name='LineDancePlayer',
|
||||||
)
|
)
|
||||||
|
|||||||
Binary file not shown.
@@ -44,9 +44,10 @@ def get_db():
|
|||||||
|
|
||||||
def init_db():
|
def init_db():
|
||||||
"""Opret alle tabeller hvis de ikke findes."""
|
"""Opret alle tabeller hvis de ikke findes."""
|
||||||
with get_db() as conn:
|
conn = _get_conn()
|
||||||
|
|
||||||
|
# Brug executescript direkte (ikke via context manager) da det auto-committer
|
||||||
conn.executescript("""
|
conn.executescript("""
|
||||||
-- Musikbiblioteker der overvåges
|
|
||||||
CREATE TABLE IF NOT EXISTS libraries (
|
CREATE TABLE IF NOT EXISTS libraries (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
path TEXT NOT NULL UNIQUE,
|
path TEXT NOT NULL UNIQUE,
|
||||||
@@ -55,7 +56,6 @@ def init_db():
|
|||||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Sange høstet fra filsystemet
|
|
||||||
CREATE TABLE IF NOT EXISTS songs (
|
CREATE TABLE IF NOT EXISTS songs (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
library_id INTEGER REFERENCES libraries(id),
|
library_id INTEGER REFERENCES libraries(id),
|
||||||
@@ -68,78 +68,32 @@ def init_db():
|
|||||||
file_format TEXT NOT NULL DEFAULT '',
|
file_format TEXT NOT NULL DEFAULT '',
|
||||||
file_modified_at TEXT NOT NULL,
|
file_modified_at TEXT NOT NULL,
|
||||||
file_missing INTEGER NOT NULL DEFAULT 0,
|
file_missing INTEGER NOT NULL DEFAULT 0,
|
||||||
api_song_id TEXT, -- NULL hvis ikke synkroniseret
|
extra_tags TEXT NOT NULL DEFAULT '{}',
|
||||||
|
api_song_id TEXT,
|
||||||
last_synced_at TEXT,
|
last_synced_at TEXT,
|
||||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Danse knyttet til en sang (kun MP3 kan skrive tags)
|
CREATE TABLE IF NOT EXISTS dance_levels (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
sort_order INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
description TEXT NOT NULL DEFAULT '',
|
||||||
|
synced_at TEXT
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS song_dances (
|
CREATE TABLE IF NOT EXISTS song_dances (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
song_id TEXT NOT NULL REFERENCES songs(id) ON DELETE CASCADE,
|
song_id TEXT NOT NULL REFERENCES songs(id) ON DELETE CASCADE,
|
||||||
dance_name TEXT NOT NULL,
|
dance_name TEXT NOT NULL,
|
||||||
dance_order INTEGER NOT NULL DEFAULT 1
|
dance_order INTEGER NOT NULL DEFAULT 1,
|
||||||
|
level_id INTEGER REFERENCES dance_levels(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Alternativ-danse relationer (kun online hvis logget ind, men caches lokalt)
|
|
||||||
CREATE TABLE IF NOT EXISTS dance_alternatives (
|
CREATE TABLE IF NOT EXISTS dance_alternatives (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
song_dance_id INTEGER NOT NULL REFERENCES song_dances(id) ON DELETE CASCADE,
|
song_dance_id INTEGER NOT NULL REFERENCES song_dances(id) ON DELETE CASCADE,
|
||||||
alt_song_dance_id INTEGER NOT NULL REFERENCES song_dances(id) ON DELETE CASCADE,
|
alt_dance_name TEXT NOT NULL DEFAULT '',
|
||||||
note TEXT NOT NULL DEFAULT '',
|
|
||||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
||||||
UNIQUE(song_dance_id, alt_song_dance_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Lokale afspilningslister (offline-projekter)
|
|
||||||
CREATE TABLE IF NOT EXISTS playlists (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
description TEXT NOT NULL DEFAULT '',
|
|
||||||
api_project_id TEXT, -- NULL hvis ikke synkroniseret
|
|
||||||
last_synced_at TEXT,
|
|
||||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Sange i en afspilningsliste
|
|
||||||
CREATE TABLE IF NOT EXISTS playlist_songs (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
playlist_id INTEGER NOT NULL REFERENCES playlists(id) ON DELETE CASCADE,
|
|
||||||
song_id TEXT NOT NULL REFERENCES songs(id),
|
|
||||||
position INTEGER NOT NULL,
|
|
||||||
status TEXT NOT NULL DEFAULT 'pending', -- pending|playing|played|skipped
|
|
||||||
UNIQUE(playlist_id, position)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Synkroniseringskø — ændringer der venter på at komme online
|
|
||||||
CREATE TABLE IF NOT EXISTS sync_queue (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
entity_type TEXT NOT NULL, -- 'song'|'playlist'|'playlist_song'
|
|
||||||
entity_id TEXT NOT NULL,
|
|
||||||
action TEXT NOT NULL, -- 'create'|'update'|'delete'
|
|
||||||
payload TEXT NOT NULL, -- JSON
|
|
||||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Indekser til hurtig søgning
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_songs_title ON songs(title);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_songs_artist ON songs(artist);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_songs_missing ON songs(file_missing);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_songs_library ON songs(library_id);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_song_dances ON song_dances(song_id);
|
|
||||||
""")
|
|
||||||
|
|
||||||
# Migration: tilføj tabeller der måske mangler i ældre databaser
|
|
||||||
_run_migrations(conn)
|
|
||||||
|
|
||||||
|
|
||||||
def _run_migrations(conn):
|
|
||||||
"""Kør migrations sikkert — CREATE IF NOT EXISTS er idempotent."""
|
|
||||||
conn.executescript("""
|
|
||||||
CREATE TABLE IF NOT EXISTS dance_alternatives (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
song_dance_id INTEGER NOT NULL REFERENCES song_dances(id) ON DELETE CASCADE,
|
|
||||||
alt_dance_name TEXT NOT NULL,
|
|
||||||
level_id INTEGER REFERENCES dance_levels(id),
|
level_id INTEGER REFERENCES dance_levels(id),
|
||||||
note TEXT NOT NULL DEFAULT '',
|
note TEXT NOT NULL DEFAULT '',
|
||||||
source TEXT NOT NULL DEFAULT 'local',
|
source TEXT NOT NULL DEFAULT 'local',
|
||||||
@@ -147,11 +101,6 @@ def _run_migrations(conn):
|
|||||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS event_state (
|
|
||||||
key TEXT PRIMARY KEY,
|
|
||||||
value TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS dance_names (
|
CREATE TABLE IF NOT EXISTS dance_names (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
name TEXT NOT NULL UNIQUE COLLATE NOCASE,
|
name TEXT NOT NULL UNIQUE COLLATE NOCASE,
|
||||||
@@ -160,16 +109,46 @@ def _run_migrations(conn):
|
|||||||
synced_at TEXT
|
synced_at TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS dance_levels (
|
CREATE TABLE IF NOT EXISTS playlists (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
sort_order INTEGER NOT NULL,
|
name TEXT NOT NULL,
|
||||||
name TEXT NOT NULL UNIQUE,
|
|
||||||
description TEXT NOT NULL DEFAULT '',
|
description TEXT NOT NULL DEFAULT '',
|
||||||
synced_at TEXT
|
api_project_id TEXT,
|
||||||
|
last_synced_at TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS playlist_songs (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
playlist_id INTEGER NOT NULL REFERENCES playlists(id) ON DELETE CASCADE,
|
||||||
|
song_id TEXT NOT NULL REFERENCES songs(id),
|
||||||
|
position INTEGER NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'pending',
|
||||||
|
UNIQUE(playlist_id, position)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS sync_queue (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
entity_type TEXT NOT NULL,
|
||||||
|
entity_id TEXT NOT NULL,
|
||||||
|
action TEXT NOT NULL,
|
||||||
|
payload TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS event_state (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_songs_title ON songs(title);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_songs_artist ON songs(artist);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_songs_missing ON songs(file_missing);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_songs_library ON songs(library_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_song_dances ON song_dances(song_id);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Tilføj kolonner der måske mangler i ældre databaser
|
# Kør migrations for ældre databaser (each separately)
|
||||||
migrations = [
|
migrations = [
|
||||||
"ALTER TABLE songs ADD COLUMN extra_tags TEXT NOT NULL DEFAULT '{}'",
|
"ALTER TABLE songs ADD COLUMN extra_tags TEXT NOT NULL DEFAULT '{}'",
|
||||||
"ALTER TABLE song_dances ADD COLUMN level_id INTEGER REFERENCES dance_levels(id)",
|
"ALTER TABLE song_dances ADD COLUMN level_id INTEGER REFERENCES dance_levels(id)",
|
||||||
@@ -181,10 +160,11 @@ def _run_migrations(conn):
|
|||||||
for sql in migrations:
|
for sql in migrations:
|
||||||
try:
|
try:
|
||||||
conn.execute(sql)
|
conn.execute(sql)
|
||||||
|
conn.commit()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # kolonnen eksisterer allerede
|
pass
|
||||||
|
|
||||||
# Indlæs standard-niveauer hvis tabellen er tom
|
# Seed standard-niveauer — KUN hvis tabellen er tom
|
||||||
count = conn.execute("SELECT COUNT(*) FROM dance_levels").fetchone()[0]
|
count = conn.execute("SELECT COUNT(*) FROM dance_levels").fetchone()[0]
|
||||||
if count == 0:
|
if count == 0:
|
||||||
defaults = [
|
defaults = [
|
||||||
@@ -198,10 +178,17 @@ def _run_migrations(conn):
|
|||||||
"INSERT OR IGNORE INTO dance_levels (sort_order, name, description) VALUES (?,?,?)",
|
"INSERT OR IGNORE INTO dance_levels (sort_order, name, description) VALUES (?,?,?)",
|
||||||
defaults
|
defaults
|
||||||
)
|
)
|
||||||
|
conn.commit()
|
||||||
|
print(f"Dans-niveauer seedet: {len(defaults)} niveauer")
|
||||||
|
else:
|
||||||
|
print(f"Dans-niveauer: {count} niveauer i databasen")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ── Biblioteker ───────────────────────────────────────────────────────────────
|
# ── Biblioteker ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def add_library(path: str) -> int:
|
def add_library(path: str) -> int:
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
cur = conn.execute(
|
cur = conn.execute(
|
||||||
|
|||||||
Binary file not shown.
@@ -33,6 +33,7 @@ class Player(QObject):
|
|||||||
self._duration: int = 0
|
self._duration: int = 0
|
||||||
self._demo_mode = False
|
self._demo_mode = False
|
||||||
self._demo_stop_sec = 10
|
self._demo_stop_sec = 10
|
||||||
|
self._demo_fading = False
|
||||||
self._volume = 78
|
self._volume = 78
|
||||||
|
|
||||||
if VLC_AVAILABLE:
|
if VLC_AVAILABLE:
|
||||||
@@ -78,11 +79,13 @@ class Player(QObject):
|
|||||||
self.state_changed.emit("playing")
|
self.state_changed.emit("playing")
|
||||||
|
|
||||||
def play_demo(self, stop_at_sec: int = 10):
|
def play_demo(self, stop_at_sec: int = 10):
|
||||||
"""Afspil fra start og stop automatisk ved stop_at_sec."""
|
"""Afspil fra start og stop automatisk ved stop_at_sec med 2 sek fade-out."""
|
||||||
self._demo_mode = True
|
self._demo_mode = True
|
||||||
self._demo_stop_sec = stop_at_sec
|
self._demo_stop_sec = stop_at_sec
|
||||||
|
self._demo_fading = False
|
||||||
if VLC_AVAILABLE and self._media_player:
|
if VLC_AVAILABLE and self._media_player:
|
||||||
self._media_player.set_time(0)
|
self._media_player.set_time(0)
|
||||||
|
self._media_player.audio_set_volume(self._volume)
|
||||||
self._media_player.play()
|
self._media_player.play()
|
||||||
self._poll_timer.start()
|
self._poll_timer.start()
|
||||||
self.state_changed.emit("playing")
|
self.state_changed.emit("playing")
|
||||||
@@ -94,7 +97,9 @@ class Player(QObject):
|
|||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._demo_mode = False
|
self._demo_mode = False
|
||||||
|
self._demo_fading = False
|
||||||
if VLC_AVAILABLE and self._media_player:
|
if VLC_AVAILABLE and self._media_player:
|
||||||
|
self._media_player.audio_set_volume(self._volume)
|
||||||
self._media_player.stop()
|
self._media_player.stop()
|
||||||
self._poll_timer.stop()
|
self._poll_timer.stop()
|
||||||
self.position_changed.emit(0.0)
|
self.position_changed.emit(0.0)
|
||||||
@@ -138,15 +143,33 @@ class Player(QObject):
|
|||||||
self.position_changed.emit(pos)
|
self.position_changed.emit(pos)
|
||||||
self.time_changed.emit(cur, self._duration)
|
self.time_changed.emit(cur, self._duration)
|
||||||
|
|
||||||
# Demo-stop
|
# Demo fade-out og stop
|
||||||
if self._demo_mode and cur >= self._demo_stop_sec:
|
if self._demo_mode and cur >= self._demo_stop_sec:
|
||||||
|
# Færdig — gendan volumen og stop
|
||||||
|
if VLC_AVAILABLE and self._media_player:
|
||||||
|
self._media_player.audio_set_volume(self._volume)
|
||||||
self.stop()
|
self.stop()
|
||||||
self._demo_mode = False
|
self._demo_mode = False
|
||||||
|
self._demo_fading = False
|
||||||
self.position_changed.emit(0.0)
|
self.position_changed.emit(0.0)
|
||||||
self.time_changed.emit(0, self._duration)
|
self.time_changed.emit(0, self._duration)
|
||||||
self.state_changed.emit("demo_ended")
|
self.state_changed.emit("demo_ended")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Demo fade-out — de sidste 2 sekunder
|
||||||
|
FADE_SEC = 2.0
|
||||||
|
if self._demo_mode and VLC_AVAILABLE and self._media_player:
|
||||||
|
secs_left = self._demo_stop_sec - cur
|
||||||
|
if secs_left <= FADE_SEC and secs_left > 0:
|
||||||
|
# Fade fra fuld volumen til 0 over FADE_SEC sekunder
|
||||||
|
fade_fraction = secs_left / FADE_SEC # 1.0 → 0.0
|
||||||
|
faded_vol = int(self._volume * fade_fraction)
|
||||||
|
self._media_player.audio_set_volume(max(0, faded_vol))
|
||||||
|
self._demo_fading = True
|
||||||
|
elif not self._demo_fading:
|
||||||
|
# Ikke i fade-zone endnu — sørg for fuld volumen
|
||||||
|
self._media_player.audio_set_volume(self._volume)
|
||||||
|
|
||||||
# VU-meter: brug VLC's audio-amplitude hvis tilgængelig, ellers simulér
|
# VU-meter: brug VLC's audio-amplitude hvis tilgængelig, ellers simulér
|
||||||
if VLC_AVAILABLE and self._media_player and self._media_player.is_playing():
|
if VLC_AVAILABLE and self._media_player and self._media_player.is_playing():
|
||||||
# VLC eksponerer ikke amplitude direkte — vi bruger en blød simulation
|
# VLC eksponerer ikke amplitude direkte — vi bruger en blød simulation
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user