diff --git a/GEMINI.md b/GEMINI.md index 83fe543..67d713e 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -85,6 +85,9 @@ busctl --user call org.mpris.MediaPlayer2.winamp /org/mpris/MediaPlayer2 org.mpr - **`winamp_mpris_old.py`**: A previous iteration of the bridge. - **`sample_Winamp Web Interface.html`**: A sample of the HTML returned by the Winamp Web Interface, used for reference in parsing logic. +> [!NOTE] +> The source code in `Wawi Source/` and `gen_httpSrv_systray/` is provided for reference only. The bridge currently interacts with the compiled binaries. + ## Development Conventions - **D-Bus Interface:** Defined via XML introspection string within the `WinampMPRIS` class. diff --git a/bridge.pid b/bridge.pid new file mode 100644 index 0000000..e896ce7 --- /dev/null +++ b/bridge.pid @@ -0,0 +1 @@ +3051439 diff --git a/winamp_mpris.py b/winamp_mpris.py index 5f798b5..f862893 100755 --- a/winamp_mpris.py +++ b/winamp_mpris.py @@ -14,6 +14,7 @@ from bs4 import BeautifulSoup # --- CONFIGURATION & XDG PATHS --- BASE_URL = "http://localhost:5666" AUTH = ('winamp', 'llama') +POSSIBLE_CREDS = [('winamp', 'llama'), ('winamp', ''), None] APP_ID = "org.mpris.MediaPlayer2.winamp" DEFAULT_ART = "https://webamp.org/favicon.ico" @@ -39,6 +40,29 @@ logging.basicConfig( ) logger = logging.getLogger("winamp-mpris") +def authenticated_get(url, timeout=2): + """Helper to perform GET with authentication fallback.""" + global AUTH + try: + r = requests.get(url, auth=AUTH, timeout=timeout) + if r.status_code != 401: + return r + except requests.RequestException as e: + raise e + + for cred in POSSIBLE_CREDS: + if cred == AUTH: + continue + try: + r = requests.get(url, auth=cred, timeout=timeout) + if r.status_code != 401: + logger.info(f"Authentication fallback successful: switched to {cred}") + AUTH = cred + return r + except requests.RequestException: + continue + return r + def write_pid_file(): try: with open(PID_FILE, "w") as f: @@ -127,9 +151,9 @@ class WinampMPRIS: def _request(self, endpoint): logger.info(f"COMMAND RECEIVED: {endpoint}") try: - r = requests.get(f"{BASE_URL}/{endpoint}", auth=AUTH, timeout=2) + r = authenticated_get(f"{BASE_URL}/{endpoint}", timeout=2) if r.status_code == 401: - msg = "401 Unauthorized: Check gen_httpsrv.dll plugin config. Ensure user 'winamp' has correct password and 'Play' permissions in Users tab." + msg = "401 Unauthorized: All authentication attempts failed (winamp:llama, winamp:, anon). Check plugin config." logger.warning(f"ERROR: {msg}") subprocess.run(["notify-send", "-u", "critical", "-t", "10000", "Winamp Bridge Auth Error", msg]) elif r.status_code != 200: @@ -334,7 +358,7 @@ def update_loop(player): # 2. Poll Web UI (Status and Time source) try: - r = requests.get(f"{BASE_URL}/main", auth=AUTH, timeout=1) + r = authenticated_get(f"{BASE_URL}/main", timeout=1) if r.status_code == 200: offline_logged = False auth_error_logged = False @@ -396,12 +420,12 @@ def update_loop(player): player._album = "" elif r.status_code == 401: if not auth_error_logged: - msg = "401 Unauthorized: Check gen_httpsrv.dll plugin config. Ensure user 'winamp' has correct password and 'Play' permissions in Users tab." + msg = "401 Unauthorized: All authentication attempts failed (winamp:llama, winamp:, anon). Check plugin config." logger.warning(f"ERROR: {msg}") subprocess.run(["notify-send", "-u", "critical", "-t", "10000", "Winamp Bridge Auth Error", msg]) auth_error_logged = True player._status = "Stopped" - except requests.exceptions.RequestException: + except requests.RequestException: if not window_title: if not offline_logged: logger.info("Winamp Web Interface offline and no window found.")