Files
HMS MediaEngine Agent 362e089be0 AUFGERAUMT: Root auf 10 sichtbare Elemente reduziert
Der Nutzer hat recht: Der Ordner war voller Entwicklungs-Muell.
Jetzt ist sauber getrennt:

ROOT (was der Nutzer sieht und braucht):
- run.py                     = das Programm
- hms_app/                   = der Anwendungscode
- HMS MediaEngine.app        = macOS Doppelklick-Starter
- HMS-Start.vbs              = Windows Doppelklick-Starter
- HMS-Install.vbs             = Windows Erst-Installation
- HMS-Mac-Install.command     = macOS Homebrew-Installation
- HMS-Portable-Install.command = macOS Portable-Installation (16GB-Fix)
- installer_gui.py           = grafischer Installer
- launcher.pyw + launcher_core.py = interne Start-Logik
- LIESMICH.txt               = 10-Zeilen-Kurzanleitung
- .gitignore

_entwicklung/ (alles andere, NICHT benoetigt):
- packages/ apps/ native/ plugins/ tools/ schemas/ tests/ docs/
  build/ fixture_profiles/
- PLAN.md STATUS.md ERRORS.md TEST_REPORT.md CHANGELOG.md README.md
- pyproject.toml uv.lock setup_*.sh/ps1 make_mac_app.py

Diese Trennung gilt ab sofort fuer alle Commits. Der Nutzer kann
_entwicklung/ loeschen wenn er Platz braucht - die App laeuft ohne.

Verifiziert: App startet nach Aufraeumen unveraendert (Health 200).
2026-09-11 23:44:06 +02:00

260 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `plugin.json` Manifest-Referenz
Dieses Dokument beschreibt alle Felder des Plugin-Manifests `plugin.json`. Grundlage sind das JSON-Schema `schemas/plugin/plugin_manifest_v1.schema.json` und der Validator `packages/plugin_sdk/hms_plugin_sdk/manifest.py` (PLAN.md §14.214.3).
## Schema-Version und API-Version
| Feld | Typ | Pflicht | Wert |
| --- | --- | --- | --- |
| `schema_version` | integer | ja | `1` (konstant) |
| `api_version` | integer | ja | `1` (konstant) |
`schema_version` und `api_version` müssen exakt `1` sein. Der Validator lehnt jede andere Version ab (`manifest.py`).
## Pflichtfelder
Das Schema verlangt folgende Felder auf oberster Ebene:
```json
["schema_version", "id", "name", "version", "api_version", "kind", "vendor", "entrypoints", "capabilities", "failure_mode"]
```
### `id`
- **Typ:** string
- **Pflicht:** ja
- **Regeln:** Reverse-DNS-Notation, mindestens 5 Zeichen, mindestens zwei durch `.` getrennte Teile, nur Kleinbuchstaben `az`, Ziffern `09`, `.`, `_`, `-`. Kein `..` erlaubt.
- **Beispiel:** `com.hms.fx.vignette`
### `name`
- **Typ:** string, minLength 1
- **Pflicht:** ja
- **Beispiel:** `Vignette`
### `version`
- **Typ:** string
- **Pflicht:** ja
- **Regeln:** Semantische Version `X.Y.Z` (genau drei durch `.` getrennte Ganzzahlen).
- **Beispiel:** `1.0.0`
### `kind`
- **Typ:** enum
- **Pflicht:** ja
- **Werte:** `source`, `generator`, `filter`, `transition`, `mixer`, `output`, `control`, `automation` (PLAN.md §14.1)
- **Beispiel:** `filter`
### `vendor`
- **Typ:** string, minLength 1
- **Pflicht:** ja
- **Beispiel:** `HMS`
### `entrypoints`
- **Typ:** object, minProperties 1
- **Pflicht:** ja
- **Beschreibung:** Backend-Entrypoints mit Shader-Pässen. Erlaubte Backend-Schlüssel: `d3d11`, `gl`, `gles`.
Jeder Entrypoint ist ein Objekt mit:
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `type` | string | ja | Entrypoint-Typ, z. B. `hlsl`, `glsl`, `glsl_es`, `hlsl_multipass`, `glsl_multipass`, `glsl_es_multipass` |
| `passes` | array, minItems 1 | ja | Liste der Shader-Pässe |
Jeder Pass ist ein Objekt mit genau einem Shader-Pfad:
- **D3D11:** `pixel_shader` (z. B. `shaders/d3d11/main.hlsl`)
- **GL/GLES:** `fragment` (z. B. `shaders/gl/main.frag`)
**Beispiel (Einpass, Vignette):**
```json
"entrypoints": {
"d3d11": {
"type": "hlsl",
"passes": [{"pixel_shader": "shaders/d3d11/main.hlsl"}]
},
"gl": {
"type": "glsl",
"passes": [{"fragment": "shaders/gl/main.frag"}]
},
"gles": {
"type": "glsl_es",
"passes": [{"fragment": "shaders/gles/main.frag"}]
}
}
```
**Beispiel (Multipass, Gaussian Blur, PLAN.md §14.3):**
```json
"entrypoints": {
"d3d11": {
"type": "hlsl_multipass",
"passes": [
{"pixel_shader": "shaders/d3d11/horizontal.hlsl"},
{"pixel_shader": "shaders/d3d11/vertical.hlsl"}
]
},
"gl": {
"type": "glsl_multipass",
"passes": [
{"fragment": "shaders/gl/horizontal.frag"},
{"fragment": "shaders/gl/vertical.frag"}
]
},
"gles": {
"type": "glsl_es_multipass",
"passes": [
{"fragment": "shaders/gles/horizontal.frag"},
{"fragment": "shaders/gles/vertical.frag"}
]
}
}
```
Der Validator prüft, dass jeder deklarierte Shader-Pfad relativ und sicher ist (kein absoluter Pfad, kein `..`) und wenn ein Plugin-Root übergeben wird tatsächlich existiert (`manifest.py`).
### `capabilities`
- **Typ:** object
- **Pflicht:** ja
- **Pflichtfelder:** `minimum_tier`, `supported_backends`
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `minimum_tier` | enum | ja | `DESKTOP_FULL`, `DESKTOP_LITE`, `PI_LITE`, `HEADLESS_CONTROL` |
| `requires_input_texture` | boolean | nein | `true`, wenn der Effekt eine Eingangs-Textur braucht (Filter) |
| `supported_backends` | array, minItems 1 | ja | `d3d11`, `gl`, `gles` |
**Beispiel (Vignette):**
```json
"capabilities": {
"minimum_tier": "PI_LITE",
"requires_input_texture": true,
"supported_backends": ["d3d11", "gl", "gles"]
}
```
### `failure_mode`
- **Typ:** enum
- **Pflicht:** ja
- **Werte:** `bypass`, `hold`, `black`
- **Beschreibung:** Verhalten bei einem Pluginfehler. `bypass` überbrückt den Effekt (PLAN.md §3.5, §14.5).
- **Beispiel:** `bypass`
## Optionale Felder
### `parameters`
- **Typ:** array
- **Pflicht:** nein (im Schema), aber empfohlen
- **Beschreibung:** Liste der Plugin-Parameter. Details siehe [parameters-and-dmx.md](parameters-and-dmx.md).
Jeder Parameter ist ein Objekt mit:
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `id` | string, minLength 1 | ja | Eindeutige Parameter-ID |
| `label` | string, minLength 1 | ja | Anzeigename |
| `type` | enum | ja | `float`, `int`, `enum`, `bool`, `color` |
| `default` | beliebig | ja | Standardwert |
| `minimum` | number | nein | Untergrenze (für `float`/`int`) |
| `maximum` | number | nein | Obergrenze (für `float`/`int`) |
| `values` | array | nein | Werte für `enum` |
| `dmx_slots` | array, maxItems 8 | nein | DMX-Slot-Belegung (18) |
| `curve` | string | nein | Kurvenform, z. B. `quadratic` |
**Beispiel (Vignette):**
```json
"parameters": [
{"id": "amount", "label": "Amount", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [1]},
{"id": "radius", "label": "Radius", "type": "float", "minimum": 0, "maximum": 2, "default": 0.5, "dmx_slots": [2]},
{"id": "softness", "label": "Softness", "type": "float", "minimum": 0, "maximum": 1, "default": 0.4, "dmx_slots": [3]},
{"id": "roundness", "label": "Roundness", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [4]},
{"id": "center_x", "label": "Center X", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [5]},
{"id": "center_y", "label": "Center Y", "type": "float", "minimum": 0, "maximum": 1, "default": 0.5, "dmx_slots": [6]},
{"id": "color", "label": "Color", "type": "color", "default": [0, 0, 0], "dmx_slots": [7]},
{"id": "invert", "label": "Invert", "type": "bool", "default": 0, "dmx_slots": [8]},
{"id": "mix", "label": "Mix", "type": "float", "minimum": 0, "maximum": 1, "default": 1, "dmx_slots": []}
]
```
**Validator-Regeln für Parameter (`manifest.py`):**
- `id` muss vorhanden und ein String sein; doppelte IDs sind Fehler.
- `type` muss einer von `float`, `int`, `enum`, `bool`, `color` sein.
- Für `float` müssen `minimum`, `maximum` und `default` vorhanden sein.
- `dmx_slots` muss eine Liste von Ganzzahlen sein.
- Die Summe aller `dmx_slots` über alle Parameter darf **8 nicht überschreiten** (PLAN.md §14.7).
### `adaptive_quality`
- **Typ:** object
- **Pflicht:** nein (im Schema), aber für qualitätsabhängige Effekte empfohlen
- **Pflichtfelder:** `default`, `variants`
- **Beschreibung:** Adaptive-Quality-Varianten. Details siehe [adaptive-quality.md](adaptive-quality.md).
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `default` | string | ja | Standard-Variante, z. B. `auto` |
| `variants` | array, minItems 1 | ja | Liste der Varianten |
| `transition_ms` | number, minimum 0 | nein | Übergangszeit in Millisekunden |
| `semantic_parameters_unchanged` | array of string | nein | Parameter, deren Semantik beim Wechsel unverändert bleibt |
Jede Variante ist ein Objekt mit:
| Feld | Typ | Pflicht | Beschreibung |
| --- | --- | --- | --- |
| `id` | string | ja | Varianten-ID, z. B. `low`, `medium`, `high` |
| `internal_scale` | number, exclusiveMinimum 0, maximum 1 | nein | Interne Auflösungsskala |
| `samples` | integer, minimum 1 | nein | Sample-Anzahl |
**Beispiel (Vignette):**
```json
"adaptive_quality": {
"default": "auto",
"variants": [
{"id": "low", "internal_scale": 1.0, "samples": 1},
{"id": "medium", "internal_scale": 1.0, "samples": 1},
{"id": "high", "internal_scale": 1.0, "samples": 1}
],
"transition_ms": 180,
"semantic_parameters_unchanged": ["mix"]
}
```
## Validierung
Die Validierung (`manifest.py`) umfasst (PLAN.md §14.5):
- Manifest-Schema;
- eindeutige Plugin-ID und semantische Version;
- API-Kompatibilität;
- Pfad- und ZIP-Sicherheit;
- erlaubte Dateitypen und Größenlimits;
- Shader-Kompilierung;
- Capability-Prüfung;
- vollständige, vorab kompilierbare Adaptive-Quality-Varianten und unveränderte Parametersemantik;
- Lizenzmetadaten;
- Hash des Pakets.
## ZIP-Sicherheit (§27.2)
Beim Installieren als ZIP gelten zusätzlich (`manifest.py`):
- maximal 512 Dateien (`MAX_PLUGIN_FILES`);
- maximale entpackte Gesamtgröße 32 MiB (`MAX_TOTAL_UNPACKED`);
- maximale Dateigröße 8 MiB (`MAX_FILE_SIZE`);
- erlaubte Dateiendungen: `.json`, `.hlsl`, `.frag`, `.vert`, `.glsl`, `.png`, `.md`, `.txt`, `.toml`, `.csv`;
- keine absoluten Pfade, kein `..`;
- `plugin.json` muss an der Paketwurzel liegen.