Kacheln und Fenster sprechen dieselbe Sprache
Alle Kacheln, Popovers und Fenster auf die Designschicht umgestellt: rund hundert gesetzte Schriftgrößen und 159 gesetzte Abstände und Radien sind jetzt Token. Übrig bleibt `spacing: 0` — das ist eine Aussage, keine geratene Zahl. Die Einstellungen bekommen eine Seitenleiste statt sieben Reitern, deren deutsche Beschriftungen zusammen 880 Punkte brauchten. Panel-Token stehen nicht mehr in Fenstern: dort gilt Systemsemantik, damit der Hellmodus nicht schwarz auf schwarz endet. Neu ist ein Schaufenster, das alle Bauteile nebeneinander zeigt — ohne das lässt sich eine Änderung an einem Token nur prüfen, indem man die App bedient, bis jede Kachel einmal zu sehen war. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9b600de9a9
commit
edb327cabe
@@ -0,0 +1,71 @@
|
||||
import Testing
|
||||
@testable import AudioProvider
|
||||
|
||||
// Der Mixer war an einem Headset völlig still. Nachgemessen am Aggregate-Gerät
|
||||
// über der „PRO X Wireless Gaming Headset":
|
||||
//
|
||||
// MacBook Pro-Lautsprecher Eingang 1 Puffer: 2 Kan. → nur der Tap
|
||||
// PRO X Headset Eingang 2 Puffer: 1 Kan. | 2 Kan. → Mikrofon, dann Tap
|
||||
//
|
||||
// Ein Ausgabegerät, das selbst einen Eingang mitbringt — jedes Headset, jedes
|
||||
// USB-Interface — schiebt seine eigenen Eingangspuffer vor die des Taps. Wer
|
||||
// blind Puffer null nimmt, greift das Mikrofon ab statt des Programms: der
|
||||
// Programmton wird nie ausgegeben, während der Tap das Original stumm hält.
|
||||
// Die eingebauten Lautsprecher haben keinen Eingang, deshalb fiel es dort nie auf.
|
||||
|
||||
@Suite("Wo der Tap im Aggregate-Gerät liegt")
|
||||
struct TapBufferLayoutTests {
|
||||
|
||||
@Test("Reines Ausgabegerät: der Tap liegt vorn")
|
||||
func outputOnlyDeviceKeepsTapFirst() {
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
|
||||
aggregateInputChannels: [2],
|
||||
tapChannels: 2) == 0)
|
||||
}
|
||||
|
||||
@Test("Headset: der eigene Mikrofonpuffer schiebt den Tap nach hinten")
|
||||
func headsetMicrophoneShiftsTap() {
|
||||
// Der gemessene Fall. Vorher wurde hier Puffer null genommen — das
|
||||
// Mikrofon — und der Programmton blieb liegen.
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 1,
|
||||
aggregateInputChannels: [1, 2],
|
||||
tapChannels: 2) == 1)
|
||||
}
|
||||
|
||||
@Test("Mehrere Eingangspuffer des Geräts zählen alle")
|
||||
func severalDeviceInputsCount() {
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 2,
|
||||
aggregateInputChannels: [1, 1, 2],
|
||||
tapChannels: 2) == 2)
|
||||
}
|
||||
|
||||
@Test("Passt die Kanalzahl an der erwarteten Stelle nicht, wird nicht geraten")
|
||||
func mismatchedChannelsAreRefused() {
|
||||
// Läge der Tap wider Erwarten woanders, wäre die Folge wieder Stille
|
||||
// bei stummgeschaltetem Original. Dann lieber gar kein Tap: der Aufbau
|
||||
// fliegt auf, das Programm bleibt hörbar.
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
|
||||
aggregateInputChannels: [1, 2],
|
||||
tapChannels: 2) == nil)
|
||||
}
|
||||
|
||||
@Test("Fehlt der Puffer ganz, wird nicht geraten")
|
||||
func missingBufferIsRefused() {
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 2,
|
||||
aggregateInputChannels: [1, 2],
|
||||
tapChannels: 2) == nil)
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
|
||||
aggregateInputChannels: [],
|
||||
tapChannels: 2) == nil)
|
||||
}
|
||||
|
||||
@Test("Unsinnige Angaben werden abgewiesen, nicht verrechnet")
|
||||
func nonsenseIsRefused() {
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: -1,
|
||||
aggregateInputChannels: [2],
|
||||
tapChannels: 2) == nil)
|
||||
#expect(TapBufferLayout.offset(subDeviceInputBuffers: 0,
|
||||
aggregateInputChannels: [2],
|
||||
tapChannels: 0) == nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user