Files
media-player-server/media_server/service/install_windows.py
alexei.dolgolyov 83acf5f1ec Initial commit: Media Server for remote media control
FastAPI REST API server for controlling system-wide media playback
on Windows, Linux, macOS, and Android.

Features:
- Play/Pause/Stop/Next/Previous track controls
- Volume control and mute
- Seek within tracks
- Current track info (title, artist, album, artwork)
- WebSocket real-time status updates
- Script execution API
- Token-based authentication
- Cross-platform support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:41:00 +03:00

152 lines
4.5 KiB
Python

"""Windows service installer for Media Server.
This module allows the media server to be installed as a Windows service
that starts automatically on boot.
Usage:
Install: python -m media_server.service.install_windows install
Start: python -m media_server.service.install_windows start
Stop: python -m media_server.service.install_windows stop
Remove: python -m media_server.service.install_windows remove
Debug: python -m media_server.service.install_windows debug
"""
import os
import sys
import socket
import logging
try:
import win32serviceutil
import win32service
import win32event
import servicemanager
import win32api
WIN32_AVAILABLE = True
except ImportError:
WIN32_AVAILABLE = False
print("pywin32 not installed. Install with: pip install pywin32")
class MediaServerService:
"""Windows service wrapper for the Media Server."""
_svc_name_ = "MediaServer"
_svc_display_name_ = "Media Server"
_svc_description_ = "REST API server for controlling system media playback"
def __init__(self, args=None):
if WIN32_AVAILABLE:
win32serviceutil.ServiceFramework.__init__(self, args)
self.stop_event = win32event.CreateEvent(None, 0, 0, None)
self.is_running = False
self.server = None
def SvcStop(self):
"""Stop the service."""
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.stop_event)
self.is_running = False
if self.server:
self.server.should_exit = True
def SvcDoRun(self):
"""Run the service."""
servicemanager.LogMsg(
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ""),
)
self.is_running = True
self.main()
def main(self):
"""Main service loop."""
import uvicorn
from media_server.main import app
from media_server.config import settings
config = uvicorn.Config(
app,
host=settings.host,
port=settings.port,
log_level=settings.log_level.lower(),
)
self.server = uvicorn.Server(config)
self.server.run()
if WIN32_AVAILABLE:
# Dynamically inherit from ServiceFramework when available
MediaServerService = type(
"MediaServerService",
(win32serviceutil.ServiceFramework,),
dict(MediaServerService.__dict__),
)
def install_service():
"""Install the Windows service."""
if not WIN32_AVAILABLE:
print("Error: pywin32 is required for Windows service installation")
print("Install with: pip install pywin32")
return False
try:
# Get the path to the Python executable
python_exe = sys.executable
# Get the path to this module
module_path = os.path.abspath(__file__)
win32serviceutil.InstallService(
MediaServerService._svc_name_,
MediaServerService._svc_name_,
MediaServerService._svc_display_name_,
startType=win32service.SERVICE_AUTO_START,
description=MediaServerService._svc_description_,
)
print(f"Service '{MediaServerService._svc_display_name_}' installed successfully")
print("Start the service with: sc start MediaServer")
return True
except Exception as e:
print(f"Failed to install service: {e}")
return False
def remove_service():
"""Remove the Windows service."""
if not WIN32_AVAILABLE:
print("Error: pywin32 is required")
return False
try:
win32serviceutil.RemoveService(MediaServerService._svc_name_)
print(f"Service '{MediaServerService._svc_display_name_}' removed successfully")
return True
except Exception as e:
print(f"Failed to remove service: {e}")
return False
def main():
"""Main entry point for service management."""
if not WIN32_AVAILABLE:
print("Error: pywin32 is required for Windows service support")
print("Install with: pip install pywin32")
sys.exit(1)
if len(sys.argv) == 1:
# Running as a service
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(MediaServerService)
servicemanager.StartServiceCtrlDispatcher()
else:
# Command line management
win32serviceutil.HandleCommandLine(MediaServerService)
if __name__ == "__main__":
main()