diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index f8c20c0..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,50 +0,0 @@ -# Media Server for Home Assistant - -## Project Overview - -A server-client system to control PC media playback from Home Assistant. - -- **Server**: FastAPI REST API on Windows controlling system-wide media via WinRT -- **Client**: Home Assistant custom integration exposing a media player entity - -## Running the Server - -### Manual Start - -```bash -cd c:\Users\Alexei\Documents\haos-integration-media-player -python -m media_server.main -``` - -### Auto-Start on Boot (Windows Task Scheduler) - -Run in **Administrator PowerShell** from the project root: - -```powershell -.\media_server\service\install_task_windows.ps1 -``` - -To remove the scheduled task: - -```powershell -Unregister-ScheduledTask -TaskName "MediaServer" -Confirm:$false -``` - -## Home Assistant Integration - -Copy `custom_components/remote_media_player/` to your Home Assistant config folder. - -Integration files location: `U:\custom_components\remote_media_player` - -## API Token - -The API token is generated on first run and displayed in the console output. -Configure the same token in Home Assistant integration settings. - -## Server Port - -Default: `8765` - -## Git Rules - -Always ask for user approval before committing changes to git. diff --git a/README.md b/README.md index 06ce0c5..5e53913 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,35 @@ -# Remote Media Player for Home Assistant +# Remote Media Player Control your PC's media playback from Home Assistant. +This monorepo contains two separate components designed to be split into independent repositories: + ## Components -| Component | Description | Documentation | -|-----------|-------------|---------------| -| [Media Server](media_server/) | REST API server for your PC | [README](media_server/README.md) | -| [HAOS Integration](custom_components/remote_media_player/) | Home Assistant custom component | [README](custom_components/remote_media_player/README.md) | +| Component | Description | Future Repository | +|-----------|-------------|-------------------| +| [Media Server](media-server/) | REST API server for your PC | `media-server` | +| [HAOS Integration](haos-integration/) | HACS-ready Home Assistant integration | `haos-remote-media-player` | ## Overview ``` -┌─────────────────────┐ HTTP/REST ┌─────────────────────┐ -│ Home Assistant │◄─────────────────────────►│ Your PC │ -│ │ (Token Auth) │ │ -│ ┌───────────────┐ │ │ ┌───────────────┐ │ -│ │ Media Player │ │ │ │ Media Server │ │ -│ │ Entity │ │ │ │ (FastAPI) │ │ -│ └───────────────┘ │ │ └───────┬───────┘ │ -│ │ │ │ │ -└─────────────────────┘ │ ┌───────▼───────┐ │ - │ │ Media Control │ │ - │ │ - Windows │ │ - │ │ - Linux │ │ - │ │ - macOS │ │ - │ │ - Android │ │ - │ └───────────────┘ │ - └─────────────────────┘ +┌─────────────────────┐ HTTP/WebSocket ┌─────────────────────┐ +│ Home Assistant │◄────────────────────────►│ Your PC │ +│ │ (Token Auth) │ │ +│ ┌───────────────┐ │ │ ┌───────────────┐ │ +│ │ Media Player │ │ │ │ Media Server │ │ +│ │ Entity │ │ │ │ (FastAPI) │ │ +│ └───────────────┘ │ │ └───────┬───────┘ │ +│ ┌───────────────┐ │ │ │ │ +│ │ Script Button │ │ │ ┌───────▼───────┐ │ +│ │ Entities │ │ │ │ Media Control │ │ +│ └───────────────┘ │ │ │ - Windows │ │ +│ │ │ │ - Linux │ │ +└─────────────────────┘ │ │ - macOS │ │ + │ │ - Android │ │ + │ └───────────────┘ │ + └─────────────────────┘ ``` ## Features @@ -37,56 +39,49 @@ Control your PC's media playback from Home Assistant. - Volume control and mute - Seek within tracks - Display current track info (title, artist, album, artwork) +- Real-time updates via WebSocket +- Script buttons (shutdown, restart, lock, sleep, hibernate, custom) - Secure token-based authentication -## Supported Platforms - -| Platform | Media Control | Volume Control | Status | -|----------|---------------|----------------|--------| -| Windows | WinRT Media Transport | pycaw | Fully tested | -| Linux | MPRIS D-Bus | PulseAudio/PipeWire | Not tested | -| macOS | AppleScript | System volume | Not tested | -| Android | Termux:API | Termux volume | Not tested | - -> **Note:** Windows is the primary supported platform. Linux, macOS, and Android implementations exist but have not been thoroughly tested and may have limited functionality. - ## Quick Start -### 1. Set up the Server (on your PC) +### 1. Set up the Media Server (on your PC) ```bash -cd media_server +cd media-server pip install -r requirements.txt -python -m media_server.main --generate-config python -m media_server.main ``` -See [Media Server README](media_server/README.md) for detailed instructions. +See [Media Server README](media-server/README.md) for detailed instructions. ### 2. Set up Home Assistant Integration -1. Copy `custom_components/remote_media_player/` to your HA config -2. Restart Home Assistant -3. Add integration via UI with your server's IP and token +Copy `haos-integration/custom_components/remote_media_player/` to your HA config folder, or install via HACS. -See [Integration README](custom_components/remote_media_player/README.md) for detailed instructions. +See [HAOS Integration README](haos-integration/README.md) for detailed instructions. ## Project Structure ``` -haos-integration-media-player/ -├── media_server/ # Server component -│ ├── main.py # Entry point -│ ├── routes/ # API endpoints -│ ├── services/ # Platform media controllers -│ └── service/ # Service installers +/ +├── media-server/ # Standalone Media Server +│ ├── README.md # Server documentation +│ ├── requirements.txt # Python dependencies +│ ├── config.example.yaml # Example configuration +│ └── media_server/ # Python package +│ ├── main.py # Entry point +│ ├── routes/ # API endpoints +│ ├── services/ # Platform media controllers +│ └── service/ # Service installers │ -├── custom_components/ -│ └── remote_media_player/ # HAOS Integration -│ ├── media_player.py # Media player entity -│ └── config_flow.py # UI configuration +├── haos-integration/ # HACS-ready HA Integration +│ ├── README.md # Integration documentation +│ ├── hacs.json # HACS configuration +│ └── custom_components/ +│ └── remote_media_player/ # Integration code │ -└── README.md +└── README.md # This file ``` ## License diff --git a/haos-integration/.gitignore b/haos-integration/.gitignore new file mode 100644 index 0000000..e9a10d7 --- /dev/null +++ b/haos-integration/.gitignore @@ -0,0 +1,48 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +venv/ +ENV/ +env/ +.venv/ + +# IDE +.idea/ +.vscode/ +.claude/ +*.swp +*.swo +*~ + +# Config files with secrets +config.yaml +config.json +.env + +# Logs +*.log +logs/ + +# OS +.DS_Store +Thumbs.db diff --git a/haos-integration/CLAUDE.md b/haos-integration/CLAUDE.md new file mode 100644 index 0000000..461bf90 --- /dev/null +++ b/haos-integration/CLAUDE.md @@ -0,0 +1,25 @@ +# HAOS Integration - Development Guide + +## Overview + +HACS-ready Home Assistant custom integration for controlling remote PC media playback. + +## Installation + +Copy `custom_components/remote_media_player/` to your Home Assistant config folder. + +Or install via HACS as a custom repository. + +## Requirements + +Requires Media Server running on the target PC. + +Media Server Repository: `TODO: Add repository URL` + +## Integration Location + +Integration files location: `U:\custom_components\remote_media_player` + +## Git Rules + +Always ask for user approval before committing changes to git. diff --git a/haos-integration/README.md b/haos-integration/README.md new file mode 100644 index 0000000..0d32bc7 --- /dev/null +++ b/haos-integration/README.md @@ -0,0 +1,98 @@ +# Remote Media Player - Home Assistant Integration + +[![hacs_badge](https://img.shields.io/badge/HACS-Custom-41BDF5.svg)](https://github.com/hacs/integration) +[![GitHub Release](https://img.shields.io/github/v/release/YOUR_USERNAME/haos-remote-media-player)](https://github.com/YOUR_USERNAME/haos-remote-media-player/releases) + +A Home Assistant custom integration that allows you to control a remote PC's media playback as a media player entity. + +## Features + +- Full media player controls (play, pause, stop, next, previous) +- Volume control and mute +- Seek support with smooth timeline updates +- Displays current track info (title, artist, album, artwork) +- Real-time updates via WebSocket (with HTTP polling fallback) +- **Script buttons** - Execute pre-defined scripts (shutdown, restart, lock, sleep, etc.) +- Configurable via Home Assistant UI + +## Requirements + +- Home Assistant 2024.1.0 or newer +- A running **Media Server** on your PC + +### Media Server + +This integration requires the Media Server to be running on the PC you want to control. + +**Media Server Repository:** `TODO: Add repository URL` + +See the Media Server documentation for installation and setup instructions. + +## Installation + +### HACS (Recommended) + +1. Open HACS in Home Assistant +2. Click the three dots menu > **Custom repositories** +3. Add this repository URL: `https://github.com/YOUR_USERNAME/haos-remote-media-player` +4. Select category: **Integration** +5. Click **Add** +6. Search for "Remote Media Player" and click **Download** +7. Restart Home Assistant + +### Manual Installation + +1. Download the latest release from the [Releases](https://github.com/YOUR_USERNAME/haos-remote-media-player/releases) page +2. Extract and copy the `custom_components/remote_media_player` folder to your Home Assistant `config/custom_components/` directory +3. Restart Home Assistant + +## Configuration + +1. Go to **Settings** > **Devices & Services** +2. Click **+ Add Integration** +3. Search for "Remote Media Player" +4. Enter the connection details: + - **Host**: IP address or hostname of your PC running Media Server + - **Port**: Server port (default: 8765) + - **API Token**: The authentication token from your Media Server + - **Name**: Display name for this media player (optional) + +## Usage + +Once configured, the integration creates: + +### Media Player Entity + +A full-featured media player entity with: +- Play/Pause/Stop controls +- Next/Previous track +- Volume control and mute +- Seek functionality +- Current track information + +### Script Button Entities + +Button entities for each script defined on your Media Server: +- Lock/unlock workstation +- Shutdown, restart, sleep, hibernate +- Custom scripts + +## Example Lovelace Card + +```yaml +type: media-control +entity: media_player.remote_media_player +``` + +## Documentation + +For detailed documentation, see [custom_components/remote_media_player/README.md](custom_components/remote_media_player/README.md). + +## Support + +- [Report an Issue](https://github.com/YOUR_USERNAME/haos-remote-media-player/issues) +- [Media Server Repository](TODO) + +## License + +MIT License diff --git a/custom_components/remote_media_player/README.md b/haos-integration/custom_components/remote_media_player/README.md similarity index 98% rename from custom_components/remote_media_player/README.md rename to haos-integration/custom_components/remote_media_player/README.md index ccbd78b..6a433a5 100644 --- a/custom_components/remote_media_player/README.md +++ b/haos-integration/custom_components/remote_media_player/README.md @@ -14,8 +14,8 @@ A Home Assistant custom component that allows you to control a remote PC's media ## Requirements -- Home Assistant 2023.1 or newer -- A running [Media Server](../../media_server/README.md) on your PC +- Home Assistant 2024.1.0 or newer +- A running Media Server on your PC (see Media Server repository) ## Installation diff --git a/custom_components/remote_media_player/__init__.py b/haos-integration/custom_components/remote_media_player/__init__.py similarity index 100% rename from custom_components/remote_media_player/__init__.py rename to haos-integration/custom_components/remote_media_player/__init__.py diff --git a/custom_components/remote_media_player/api_client.py b/haos-integration/custom_components/remote_media_player/api_client.py similarity index 100% rename from custom_components/remote_media_player/api_client.py rename to haos-integration/custom_components/remote_media_player/api_client.py diff --git a/custom_components/remote_media_player/button.py b/haos-integration/custom_components/remote_media_player/button.py similarity index 94% rename from custom_components/remote_media_player/button.py rename to haos-integration/custom_components/remote_media_player/button.py index 9cc42be..8be1e76 100644 --- a/custom_components/remote_media_player/button.py +++ b/haos-integration/custom_components/remote_media_player/button.py @@ -38,6 +38,7 @@ async def async_setup_entry( script_name=script["name"], script_label=script["label"], script_description=script.get("description", ""), + script_icon=script.get("icon"), ) for script in scripts ] @@ -59,6 +60,7 @@ class ScriptButtonEntity(ButtonEntity): script_name: str, script_label: str, script_description: str, + script_icon: str | None = None, ) -> None: """Initialize the script button.""" self._client = client @@ -70,7 +72,8 @@ class ScriptButtonEntity(ButtonEntity): # Entity attributes self._attr_unique_id = f"{entry.entry_id}_script_{script_name}" self._attr_name = script_label - self._attr_icon = self._get_icon_for_script(script_name) + # Use custom icon if provided, otherwise auto-resolve from script name + self._attr_icon = script_icon or self._get_icon_for_script(script_name) def _get_icon_for_script(self, script_name: str) -> str: """Get an appropriate icon based on script name.""" diff --git a/custom_components/remote_media_player/config_flow.py b/haos-integration/custom_components/remote_media_player/config_flow.py similarity index 100% rename from custom_components/remote_media_player/config_flow.py rename to haos-integration/custom_components/remote_media_player/config_flow.py diff --git a/custom_components/remote_media_player/const.py b/haos-integration/custom_components/remote_media_player/const.py similarity index 100% rename from custom_components/remote_media_player/const.py rename to haos-integration/custom_components/remote_media_player/const.py diff --git a/custom_components/remote_media_player/manifest.json b/haos-integration/custom_components/remote_media_player/manifest.json similarity index 75% rename from custom_components/remote_media_player/manifest.json rename to haos-integration/custom_components/remote_media_player/manifest.json index be908fe..725b890 100644 --- a/custom_components/remote_media_player/manifest.json +++ b/haos-integration/custom_components/remote_media_player/manifest.json @@ -4,7 +4,7 @@ "codeowners": [], "config_flow": true, "dependencies": [], - "documentation": "https://github.com/your-username/haos-integration-media-player", + "documentation": "https://github.com/YOUR_USERNAME/haos-remote-media-player", "integration_type": "device", "iot_class": "local_push", "requirements": ["aiohttp>=3.8.0"], diff --git a/custom_components/remote_media_player/media_player.py b/haos-integration/custom_components/remote_media_player/media_player.py similarity index 100% rename from custom_components/remote_media_player/media_player.py rename to haos-integration/custom_components/remote_media_player/media_player.py diff --git a/custom_components/remote_media_player/services.yaml b/haos-integration/custom_components/remote_media_player/services.yaml similarity index 100% rename from custom_components/remote_media_player/services.yaml rename to haos-integration/custom_components/remote_media_player/services.yaml diff --git a/custom_components/remote_media_player/strings.json b/haos-integration/custom_components/remote_media_player/strings.json similarity index 100% rename from custom_components/remote_media_player/strings.json rename to haos-integration/custom_components/remote_media_player/strings.json diff --git a/custom_components/remote_media_player/translations/en.json b/haos-integration/custom_components/remote_media_player/translations/en.json similarity index 100% rename from custom_components/remote_media_player/translations/en.json rename to haos-integration/custom_components/remote_media_player/translations/en.json diff --git a/custom_components/remote_media_player/translations/ru.json b/haos-integration/custom_components/remote_media_player/translations/ru.json similarity index 100% rename from custom_components/remote_media_player/translations/ru.json rename to haos-integration/custom_components/remote_media_player/translations/ru.json diff --git a/haos-integration/hacs.json b/haos-integration/hacs.json new file mode 100644 index 0000000..c5a2abf --- /dev/null +++ b/haos-integration/hacs.json @@ -0,0 +1,5 @@ +{ + "name": "Remote Media Player", + "render_readme": true, + "homeassistant": "2024.1.0" +} diff --git a/media-server/.gitignore b/media-server/.gitignore new file mode 100644 index 0000000..e9a10d7 --- /dev/null +++ b/media-server/.gitignore @@ -0,0 +1,48 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +venv/ +ENV/ +env/ +.venv/ + +# IDE +.idea/ +.vscode/ +.claude/ +*.swp +*.swo +*~ + +# Config files with secrets +config.yaml +config.json +.env + +# Logs +*.log +logs/ + +# OS +.DS_Store +Thumbs.db diff --git a/media-server/CLAUDE.md b/media-server/CLAUDE.md new file mode 100644 index 0000000..c642099 --- /dev/null +++ b/media-server/CLAUDE.md @@ -0,0 +1,39 @@ +# Media Server - Development Guide + +## Overview + +Standalone REST API server (FastAPI) for controlling system-wide media playback on Windows, Linux, macOS, and Android. + +## Running the Server + +### Manual Start + +```bash +python -m media_server.main +``` + +### Auto-Start on Boot (Windows Task Scheduler) + +Run in **Administrator PowerShell** from the media-server directory: + +```powershell +.\media_server\service\install_task_windows.ps1 +``` + +To remove the scheduled task: + +```powershell +Unregister-ScheduledTask -TaskName "MediaServer" -Confirm:$false +``` + +## Configuration + +Copy `config.example.yaml` to `config.yaml` and customize. + +The API token is generated on first run and displayed in the console output. + +Default port: `8765` + +## Git Rules + +Always ask for user approval before committing changes to git. diff --git a/media_server/README.md b/media-server/README.md similarity index 99% rename from media_server/README.md rename to media-server/README.md index 7defc70..d36500a 100644 --- a/media_server/README.md +++ b/media-server/README.md @@ -258,6 +258,7 @@ Script configuration options: | `command` | Yes | Command to execute | | `label` | No | User-friendly display name (defaults to script name) | | `description` | No | Description of what the script does | +| `icon` | No | Custom MDI icon (e.g., `mdi:power`) | | `timeout` | No | Execution timeout in seconds (default: 30, max: 300) | | `working_dir` | No | Working directory for the command | | `shell` | No | Run in shell (default: true) | diff --git a/media-server/config.example.yaml b/media-server/config.example.yaml new file mode 100644 index 0000000..48e3433 --- /dev/null +++ b/media-server/config.example.yaml @@ -0,0 +1,47 @@ +# Media Server Configuration +# Copy this file to config.yaml and customize as needed. +# A secure token will be auto-generated on first run if not specified. + +# API Token (generate a secure random token) +api_token: "your-secure-token-here" + +# Server settings +host: "0.0.0.0" +port: 8765 + +# Custom scripts +scripts: + lock_screen: + command: "rundll32.exe user32.dll,LockWorkStation" + label: "Lock Screen" + description: "Lock the workstation" + timeout: 5 + shell: true + + hibernate: + command: "shutdown /h" + label: "Hibernate" + description: "Hibernate the PC" + timeout: 10 + shell: true + + sleep: + command: "rundll32.exe powrprof.dll,SetSuspendState 0,1,0" + label: "Sleep" + description: "Put PC to sleep" + timeout: 10 + shell: true + + shutdown: + command: "shutdown /s /t 0" + label: "Shutdown" + description: "Shutdown the PC immediately" + timeout: 10 + shell: true + + restart: + command: "shutdown /r /t 0" + label: "Restart" + description: "Restart the PC immediately" + timeout: 10 + shell: true \ No newline at end of file diff --git a/media_server/__init__.py b/media-server/media_server/__init__.py similarity index 100% rename from media_server/__init__.py rename to media-server/media_server/__init__.py diff --git a/media_server/auth.py b/media-server/media_server/auth.py similarity index 100% rename from media_server/auth.py rename to media-server/media_server/auth.py diff --git a/media_server/config.py b/media-server/media_server/config.py similarity index 98% rename from media_server/config.py rename to media-server/media_server/config.py index 885958c..8b0b8ed 100644 --- a/media_server/config.py +++ b/media-server/media_server/config.py @@ -16,6 +16,7 @@ class ScriptConfig(BaseModel): command: str = Field(..., description="Command or script to execute") label: Optional[str] = Field(default=None, description="User-friendly display label") description: str = Field(default="", description="Script description") + icon: Optional[str] = Field(default=None, description="Custom icon (e.g., 'mdi:power')") timeout: int = Field(default=30, description="Execution timeout in seconds", ge=1, le=300) working_dir: Optional[str] = Field(default=None, description="Working directory") shell: bool = Field(default=True, description="Run command in shell") diff --git a/media_server/main.py b/media-server/media_server/main.py similarity index 100% rename from media_server/main.py rename to media-server/media_server/main.py diff --git a/media_server/models/__init__.py b/media-server/media_server/models/__init__.py similarity index 100% rename from media_server/models/__init__.py rename to media-server/media_server/models/__init__.py diff --git a/media_server/models/media.py b/media-server/media_server/models/media.py similarity index 100% rename from media_server/models/media.py rename to media-server/media_server/models/media.py diff --git a/media_server/routes/__init__.py b/media-server/media_server/routes/__init__.py similarity index 100% rename from media_server/routes/__init__.py rename to media-server/media_server/routes/__init__.py diff --git a/media_server/routes/health.py b/media-server/media_server/routes/health.py similarity index 100% rename from media_server/routes/health.py rename to media-server/media_server/routes/health.py diff --git a/media_server/routes/media.py b/media-server/media_server/routes/media.py similarity index 100% rename from media_server/routes/media.py rename to media-server/media_server/routes/media.py diff --git a/media_server/routes/scripts.py b/media-server/media_server/routes/scripts.py similarity index 98% rename from media_server/routes/scripts.py rename to media-server/media_server/routes/scripts.py index e518fc9..ae7d743 100644 --- a/media_server/routes/scripts.py +++ b/media-server/media_server/routes/scripts.py @@ -38,6 +38,7 @@ class ScriptInfo(BaseModel): name: str label: str description: str + icon: str | None = None timeout: int @@ -53,6 +54,7 @@ async def list_scripts(_: str = Depends(verify_token)) -> list[ScriptInfo]: name=name, label=config.label or name.replace("_", " ").title(), description=config.description, + icon=config.icon, timeout=config.timeout, ) for name, config in settings.scripts.items() diff --git a/media_server/service/install_linux.sh b/media-server/media_server/service/install_linux.sh similarity index 100% rename from media_server/service/install_linux.sh rename to media-server/media_server/service/install_linux.sh diff --git a/media_server/service/install_task_windows.ps1 b/media-server/media_server/service/install_task_windows.ps1 similarity index 100% rename from media_server/service/install_task_windows.ps1 rename to media-server/media_server/service/install_task_windows.ps1 diff --git a/media_server/service/install_windows.py b/media-server/media_server/service/install_windows.py similarity index 100% rename from media_server/service/install_windows.py rename to media-server/media_server/service/install_windows.py diff --git a/media_server/service/media-server.service b/media-server/media_server/service/media-server.service similarity index 100% rename from media_server/service/media-server.service rename to media-server/media_server/service/media-server.service diff --git a/media_server/services/__init__.py b/media-server/media_server/services/__init__.py similarity index 100% rename from media_server/services/__init__.py rename to media-server/media_server/services/__init__.py diff --git a/media_server/services/android_media.py b/media-server/media_server/services/android_media.py similarity index 100% rename from media_server/services/android_media.py rename to media-server/media_server/services/android_media.py diff --git a/media_server/services/linux_media.py b/media-server/media_server/services/linux_media.py similarity index 100% rename from media_server/services/linux_media.py rename to media-server/media_server/services/linux_media.py diff --git a/media_server/services/macos_media.py b/media-server/media_server/services/macos_media.py similarity index 100% rename from media_server/services/macos_media.py rename to media-server/media_server/services/macos_media.py diff --git a/media_server/services/media_controller.py b/media-server/media_server/services/media_controller.py similarity index 100% rename from media_server/services/media_controller.py rename to media-server/media_server/services/media_controller.py diff --git a/media_server/services/websocket_manager.py b/media-server/media_server/services/websocket_manager.py similarity index 100% rename from media_server/services/websocket_manager.py rename to media-server/media_server/services/websocket_manager.py diff --git a/media_server/services/windows_media.py b/media-server/media_server/services/windows_media.py similarity index 100% rename from media_server/services/windows_media.py rename to media-server/media_server/services/windows_media.py diff --git a/media_server/requirements.txt b/media-server/requirements.txt similarity index 100% rename from media_server/requirements.txt rename to media-server/requirements.txt