Files
onyx/docs/spikes/B-mediaremote.md
Guido Schmit 41ee3cc174 Phase 0: Repo-Gerüst und vier Verifikations-Spikes
Vier Annahmen des Plans vor jedem Implementierungscode geprüft:

A (SMC):  Lüftersteuerung bestätigt — F0md/F1md (klein!) als Auto/Manuell-
          Umschalter, F0Tg als Ziel, Grenzen aus F0Mn/F0Mx. SMC-Integer sind
          little-endian, nicht big-endian wie im verbreiteten Intel-Beispielcode.
          Ladelimit: CHWA/CH0B/CH0C/bfE0/bfF0 existieren auf Mac17,9 nicht.
          Key noch nicht identifiziert, deshalb smc-diff.sh für eine
          Differenzmessung ohne jeden Schreibzugriff.
B (Media): mediaremote-adapter läuft unter 26.6.1, aus dem Quellcode gebaut.
          Liefert vollständige Metadaten inkl. Cover aus Google Chrome — der
          Fall, den AppleScript nicht erreicht.
C (Audio): Process Tap + privates Aggregate-Device liefern echte Samples
          (469 Callbacks/5 s, 0 stille Puffer). Konflikt gefunden: SoundSource
          6.1.1 mit ARK.driver ist bereits installiert.
D (Group): App-Group-Container ist aus einem nicht-sandboxed Prozess erreichbar.
          Damit trägt die Sandbox-Entscheidung, die Bridge-App entfällt.

Spikes sind Wegwerfcode zur Verifikation, kein Produktionscode.
2026-08-10 16:47:54 +02:00

82 lines
3.3 KiB
Markdown

# Spike B — mediaremote-adapter unter macOS 26.6.1
Gemessen am 10.08.2026. Quelle aus dem Git geklont und **selbst kompiliert**, keine
Fremd-Binary geladen: `Spikes/build-mediaremote-adapter.sh` ersetzt das CMake-Setup
des Projekts durch einen direkten clang-Aufruf (cmake ist auf dieser Maschine nicht
installiert).
Projekt: [ungive/mediaremote-adapter](https://github.com/ungive/mediaremote-adapter), BSD-3-Clause,
~400 KB Objective-C plus ein Perl-Skript.
## Ergebnis: funktioniert, auch im schwierigsten Fall
```
perl mediaremote-adapter.pl <framework> <testclient> test → Exitcode 0
```
Exitcode 0 heißt: der Adapter ist berechtigt, MediaRemote zu benutzen. Apples Sperre aus
macOS 15.4 ist damit auf 26.6.1 weiterhin über den Perl-Trampolinweg umgehbar.
### `get` — vollständige Metadaten
Gelesen wurde eine laufende Wiedergabe in **Google Chrome** (YouTube). Das ist der wichtige
Befund: genau diese Quelle erreicht AppleScript nicht, sie ist der Grund für die
Adapter-Ebene überhaupt.
Gelieferte Felder:
| Feld | Beispiel |
|---|---|
| `title` | „Hanjos große Entdeckung in Thailand! \| Hanjo 2012" |
| `artist` | „FilowLIVE" |
| `album` | `""` |
| `duration` | 3051,04 s |
| `elapsedTime` | 432,06 s |
| `playbackRate` | 1 |
| `playing` | `true` |
| `bundleIdentifier` | `com.google.Chrome` |
| `processIdentifier` | 4525 |
| `artworkData` | JPEG, base64 |
| `artworkMimeType` | `image/jpeg` |
| `timestamp` | `2026-08-10T14:22:16Z` |
| `contentItemIdentifier` | UUID |
Das Cover kam sofort mit — die Warnung aus der Projekt-README („artwork often takes a bit of
time") traf hier nicht zu, ist aber weiterhin einzuplanen.
### `stream` — der Modus, den Onyx benutzt
Zeilenweises JSON auf stdout:
```json
{"type":"data","diff":false,"payload":{}}
{"type":"data","diff":false,"payload":{"title":"…","elapsedTime":432.06,}}
```
Erst ein leerer Payload, dann der vollständige. `diff` unterscheidet Voll- von
Teilaktualisierung — der Parser in `MediaProvider` muss beide Fälle behandeln und darf bei
einem leeren Payload **nicht** auf „nichts läuft" schließen.
`elapsedTime` wird nicht sekündlich nachgeliefert. Die Fortschrittsanzeige muss zwischen den
Ereignissen lokal hochzählen, ausgehend von `elapsedTime` + `timestamp` + `playbackRate`,
sonst steht der Scrubber still.
## Nicht getestet
Die Steuerbefehle (`send`, `seek`, `shuffle`, `repeat`, `speed`) wurden **absichtlich nicht**
ausgeführt — sie hätten die laufende Wiedergabe des Nutzers angehalten oder verstellt. Die
Prüfung erfolgt in Phase 4 an einer eigens gestarteten Wiedergabe.
## Auswirkungen auf den Plan
1. Die Kaskade aus dem Plan bleibt, aber die Gewichtung verschiebt sich: der Adapter deckt
mehr ab als erwartet, AppleScript ist reiner Rückfall.
2. Der Adapter wird **aus dem Quellcode mitgebaut**, nicht als Fremd-Binary eingebunden.
`Spikes/build-mediaremote-adapter.sh` wandert dafür als Build-Phase ins Xcode-Projekt.
Vorteil: kein blind eingebundenes Binärartefakt, und die Ad-hoc-Signatur passt zum
restlichen Bundle.
3. Die Perl-Datei und das Framework kommen nach `Onyx/Resources/Vendor/` und werden
**nicht** gelinkt (sonst greift Apples Entitlement-Prüfung im eigenen Prozess).
4. `disable-library-validation` in den Entitlements ist bestätigt nötig — das Framework ist
ad-hoc signiert, der Host wird es mit Team-Zertifikat sein.