diff --git a/README.md b/README.md index c92eb8c..915003b 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,11 @@ device, and QEMU links sdl2-compat over SDL3 where pausing a logical device leaves the physical one running. The device being held was not even from playback — `sdl_init_out` opens one at startup purely to negotiate a format, and nothing released it. The host resampled silence for the life of the VM. +Microphone capture is stricter: its initial device open is deferred until an +Omarchy application actually records, and the device is closed again when the +guest capture stream stops. The first recording may therefore take one device +open longer to begin, but merely launching Try Omarchy does not activate the +Mac microphone. **An unconditional re-render every refresh tick.** The vendored GPU-resolution patch cleared `gl_dirty` inside an `if (cocoa_gl_trace_enabled())` diff --git a/macos/build-qemu-gpu-runtime.sh b/macos/build-qemu-gpu-runtime.sh index 9805ef4..f1a461b 100755 --- a/macos/build-qemu-gpu-runtime.sh +++ b/macos/build-qemu-gpu-runtime.sh @@ -66,7 +66,7 @@ identity_patch_sha256=5c9358c2858a74d6a678eacaae550a021f3e616c98c4e4e98c0e50bd86 display_patch_sha256=d2b1ba0d8103640815b00a2bd02e59a7452bf79de524a33081011895101cf6ea immersive_patch_sha256=fd1cd1a619778bda5c0c4cf58001fa7053af70ac717153ed9da819d8511a2574 full_grab_patch_sha256=d325ba4fb0b88c77cfdbcc1d6f114fc9a8fa461ca7f4673341b5ab0ccd12dcf7 -audio_device_patch_sha256=ccceaff1eabe5db54cbab03d5823c9ab73e922fc727702d3b790443d07f470a3 +audio_device_patch_sha256=03aca71c26163c337338cc3b2013c35430690fc0e8b66c5ce92a42f59a9b3334 shared_folder_patch_sha256=41247692501655393ae3a40f56915472ab29b6e89c5173e33db1f62cca56632f strchrnul_patch_sha256=ec1048dd0e8ebe53bf7e8a3bca9bf2f5f4336cd607d4cd077437470e9a32094a macos_deployment_target=15.0 diff --git a/macos/patches/qemu-sdl-audio-device-selection.patch b/macos/patches/qemu-sdl-audio-device-selection.patch index e344534..ac41863 100644 --- a/macos/patches/qemu-sdl-audio-device-selection.patch +++ b/macos/patches/qemu-sdl-audio-device-selection.patch @@ -1,7 +1,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c -@@ -46,6 +46,11 @@ +@@ -57,6 +57,11 @@ int initialized; Audiodev *dev; SDL_AudioDeviceID devid; @@ -13,7 +13,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c } SDLVoiceOut; typedef struct SDLVoiceIn { -@@ -54,6 +59,11 @@ +@@ -65,6 +70,11 @@ int initialized; Audiodev *dev; SDL_AudioDeviceID devid; @@ -24,8 +24,8 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c + bool enabled; } SDLVoiceIn; - static void G_GNUC_PRINTF (1, 2) sdl_logerr (const char *fmt, ...) -@@ -160,8 +170,73 @@ + static int aud_to_sdlfmt (AudioFormat fmt) +@@ -157,8 +167,73 @@ return 0; } @@ -100,7 +100,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c { SDL_AudioDeviceID devid; #ifndef _WIN32 -@@ -181,7 +256,18 @@ +@@ -178,7 +253,18 @@ } #endif @@ -118,9 +118,9 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c + } + } if (!devid) { - sdl_logerr("SDL_OpenAudioDevice for %s failed\n", - rec ? "recording" : "playback"); -@@ -287,12 +373,193 @@ + error_report("SDL_OpenAudioDevice for %s failed: %s", + rec ? "recording" : "playback", SDL_GetError()); +@@ -280,12 +366,193 @@ } } @@ -314,7 +314,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c SDL_LockAudioDevice(sdl->devid); \ ret = glue(audio_generic_, name)args; \ SDL_UnlockAudioDevice(sdl->devid); \ -@@ -305,6 +572,7 @@ +@@ -298,6 +565,7 @@ { \ glue(SDLVoice, dir) *sdl = (glue(SDLVoice, dir) *)hw; \ \ @@ -322,7 +322,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c SDL_LockAudioDevice(sdl->devid); \ glue(audio_generic_, name)args; \ SDL_UnlockAudioDevice(sdl->devid); \ -@@ -331,6 +599,8 @@ +@@ -324,6 +592,8 @@ SDLVoiceOut *sdl = (SDLVoiceOut *)hw; sdl_close_out(sdl); @@ -330,8 +330,8 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c + sdl->next_route_check = 0; } - static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, -@@ -353,7 +623,9 @@ + static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as) +@@ -345,7 +615,9 @@ req.userdata = sdl; sdl->dev = dev; @@ -342,7 +342,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c if (!sdl->devid) { return -1; } -@@ -371,8 +643,12 @@ +@@ -363,8 +635,12 @@ hw->samples = (spdo->has_buffer_count ? spdo->buffer_count : 4) * obt.samples; @@ -355,7 +355,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c return 0; } -@@ -380,7 +656,18 @@ +@@ -372,7 +648,18 @@ { SDLVoiceOut *sdl = (SDLVoiceOut *)hw; @@ -375,7 +375,7 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c } static void sdl_fini_in(HWVoiceIn *hw) -@@ -388,6 +675,8 @@ +@@ -380,6 +667,8 @@ SDLVoiceIn *sdl = (SDLVoiceIn *)hw; sdl_close_in(sdl); @@ -383,19 +383,27 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c + sdl->next_route_check = 0; } - static int sdl_init_in(HWVoiceIn *hw, audsettings *as, void *drv_opaque) -@@ -409,7 +698,9 @@ + static int sdl_init_in(HWVoiceIn *hw, audsettings *as) +@@ -401,10 +690,13 @@ req.userdata = sdl; sdl->dev = dev; - sdl->devid = sdl_open(&req, &obt, 1); +- if (!sdl->devid) { +- return -1; +- } + sdl->device_name = sdl_initial_device_name(1); -+ sdl->devid = sdl_open(&req, &obt, 1, sdl->device_name, -+ &sdl->route_matches); - if (!sdl->devid) { - return -1; - } -@@ -430,8 +721,12 @@ ++ /* ++ * Opening a recording device starts CoreAudio capture and trips macOS's ++ * privacy indicator. SDL is called with allowed_changes=0, so a ++ * successful open cannot change this requested spec; defer the real open ++ * until the guest enables a recording stream. ++ */ ++ obt = req; +- + err = sdl_to_audfmt(obt.format, &obt_as.fmt, &obt_as.big_endian); + if (err) { +@@ -422,6 +715,9 @@ hw->buf_emul = g_malloc(hw->size_emul); hw->pos_emul = hw->pending_emul = 0; @@ -404,11 +412,8 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c + sdl->reopen_spec.userdata = sdl; sdl->initialized = 1; sdl->exit = 0; -+ sdl_release_in(sdl); return 0; - } - -@@ -439,7 +734,18 @@ +@@ -431,7 +727,18 @@ { SDLVoiceIn *sdl = (SDLVoiceIn *)hw; @@ -427,4 +432,4 @@ diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c + SDL_PauseAudioDevice(sdl->devid, 0); } - static void *sdl_audio_init(Audiodev *dev, Error **errp) + static bool audio_sdl_realize(AudioBackend *abe, Audiodev *dev, Error **errp)