diff --git a/CLAUDE.md b/CLAUDE.md index 9e63502..d40e20a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -166,6 +166,8 @@ Uninstall preserves `config.yaml` (user data). Reference: [gitea-python-ci-cd.md](https://git.dolgolyov-family.by/alexei.dolgolyov/claude-code-facts/src/branch/main/gitea-python-ci-cd.md) +**IMPORTANT:** When modifying CI/CD workflows, `installer.nsi`, or build scripts (`build-dist-*.sh`), always fetch and consult the guide above first to ensure changes stay in sync with established patterns. + ### Before Pushing Ensure CI will pass locally: diff --git a/build-dist-windows.sh b/build-dist-windows.sh index 5d53a53..0932630 100644 --- a/build-dist-windows.sh +++ b/build-dist-windows.sh @@ -68,6 +68,7 @@ WIN_DEPS=( "pycaw>=20230407" "screen-brightness-control>=0.20.0" "monitorcontrol>=3.0.0" + "pystray>=0.19.0" ) # Visualizer dependencies diff --git a/installer.nsi b/installer.nsi index 28ee096..0a460c0 100644 --- a/installer.nsi +++ b/installer.nsi @@ -18,13 +18,12 @@ InstallDir "$LOCALAPPDATA\${APPNAME}" RequestExecutionLevel user ; --- UI --- -; To use a custom icon, convert icon.svg to icon.ico and uncomment: -; !define MUI_ICON "media_server\static\icons\icon.ico" -; !define MUI_UNICON "media_server\static\icons\icon.ico" +!define MUI_ICON "media_server\static\icons\icon.ico" +!define MUI_UNICON "media_server\static\icons\icon.ico" !define MUI_ABORTWARNING -!define MUI_FINISHPAGE_RUN "wscript.exe" -!define MUI_FINISHPAGE_RUN_PARAMETERS '"$INSTDIR\scripts\${VBSNAME}"' +!define MUI_FINISHPAGE_RUN "" !define MUI_FINISHPAGE_RUN_TEXT "Launch ${APPNAME}" +!define MUI_FINISHPAGE_RUN_FUNCTION LaunchApp !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_DIRECTORY @@ -37,13 +36,38 @@ RequestExecutionLevel user !insertmacro MUI_LANGUAGE "English" +; --- Functions --- +Function LaunchApp + ExecShell "open" "wscript.exe" '"$INSTDIR\scripts\${VBSNAME}"' + ; Give the server a moment to start, then open the UI in the default browser + Sleep 2000 + ExecShell "open" "http://localhost:8765/" +FunctionEnd + +Function .onInit + ; Check if server is running by trying to open its Python executable exclusively + IfFileExists "$INSTDIR\python\python.exe" 0 done + ClearErrors + FileOpen $0 "$INSTDIR\python\python.exe" a + IfErrors locked + ; File opened fine — server is not running + FileClose $0 + Goto done + locked: + MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \ + "${APPNAME} is currently running.$\n$\nYes = Stop the server and continue$\nNo = Continue without stopping (may cause errors)$\nCancel = Abort installation" \ + IDYES kill IDNO done + Abort + kill: + nsExec::ExecToLog 'wmic process where "ExecutablePath like $\'%Media Server%python%$\'" call terminate' + Sleep 2000 + done: +FunctionEnd + ; --- Sections --- Section "!Core (required)" SecCore SectionIn RO - ; Stop running instance if any - nsExec::ExecToLog 'taskkill /F /IM python.exe /FI "WINDOWTITLE eq media_server*"' - SetOutPath "$INSTDIR" ; Copy entire distribution @@ -112,7 +136,8 @@ SectionEnd ; --- Uninstaller --- Section "Uninstall" ; Stop running instance - nsExec::ExecToLog 'taskkill /F /IM python.exe /FI "WINDOWTITLE eq media_server*"' + nsExec::ExecToLog 'wmic process where "ExecutablePath like $\'%Media Server%python%$\'" call terminate' + nsExec::ExecToLog 'taskkill /F /IM media-server.exe' ; Remove application files RMDir /r "$INSTDIR\python" diff --git a/media_server/static/icons/icon.ico b/media_server/static/icons/icon.ico new file mode 100644 index 0000000..41dda85 Binary files /dev/null and b/media_server/static/icons/icon.ico differ diff --git a/scripts/start-hidden.vbs b/scripts/start-hidden.vbs index a23d46f..1d4bae4 100644 --- a/scripts/start-hidden.vbs +++ b/scripts/start-hidden.vbs @@ -1,7 +1,13 @@ +Set fso = CreateObject("Scripting.FileSystemObject") Set WshShell = CreateObject("WScript.Shell") ' Get the directory of this script (scripts\), then go up to media-server root -scriptDir = CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) -serverRoot = CreateObject("Scripting.FileSystemObject").GetParentFolderName(scriptDir) +scriptDir = fso.GetParentFolderName(WScript.ScriptFullName) +serverRoot = fso.GetParentFolderName(scriptDir) WshShell.CurrentDirectory = serverRoot -' Run python completely hidden (0 = hidden, False = don't wait) -WshShell.Run "python -m media_server.main", 0, False +' Use embedded Python if present (installed distribution), otherwise system Python +embeddedPython = serverRoot & "\python\python.exe" +If fso.FileExists(embeddedPython) Then + WshShell.Run """" & embeddedPython & """ -m media_server.main", 0, False +Else + WshShell.Run "python -m media_server.main", 0, False +End If