Skip to content

Instantly share code, notes, and snippets.

@martinalderson
Last active March 19, 2026 09:36
Show Gist options
  • Select an option

  • Save martinalderson/2b4185675ac5afc3daeb909ce896e15b to your computer and use it in GitHub Desktop.

Select an option

Save martinalderson/2b4185675ac5afc3daeb909ce896e15b to your computer and use it in GitHub Desktop.
Airflow on Wine

Airflow on Wine (Linux)

Running the Windows Airflow media streaming app under Wine on Fedora Linux. Airflow streams video/audio to AirPlay and Chromecast devices.

Debugged with Claude Code Opus 4.6. By Martin Alderson - check out my blog if you found this useful: martinalderson.com

Hardware / OS

  • Fedora 43, AMD Ryzen 9 7900, AMD Radeon RX 9070 XT
  • Wine 11.0 Staging
  • MinGW cross-compiler: x86_64-w64-mingw32-gcc 15.2.1

Launch Command

WINEPREFIX=/home/martin/.wine-airflow \
WINEDLLOVERRIDES="powrprof=n;vcruntime140_1=n;vcruntime140=n;msvcp140=n;concrt140=n" \
WINEDEBUG=-all \
wine /home/martin/source/airflow/Airflow.exe

What Works

  • App launches and displays UI via DXVK (Vulkan translation of Direct3D)
  • AirPlay device discovery (via built-in mDNS in airflow_server.dll)
  • Chromecast streaming (play button, casting video)
  • AirPlay devices visible

Issues Fixed

1. powrprof.dll — Missing Power API

Wine doesn't implement PowerRegisterSuspendResumeNotification. Built a stub DLL that exports the required functions and returns success.

File: powrprof_override.c + powrprof.def

Build:

x86_64-w64-mingw32-gcc -shared -o powrprof.dll powrprof_override.c powrprof.def -lkernel32 -e DllMain

Deploy: Copy powrprof.dll into the Airflow directory. The WINEDLLOVERRIDES="powrprof=n" flag tells Wine to use our native DLL instead of its builtin.

2. airflow_server.dll — setsockopt IP_PKTINFO Level

The built-in mDNS responder in airflow_server.dll calls setsockopt with Windows socket option level 0xFFFB for IP_PKTINFO. Wine's Winsock translation doesn't handle this level, causing "unable to create recv socket" errors and automatic crashes on startup.

Fix: Binary patch at file offset 0x33BFD — changed BA FB FF 00 00 (mov edx, 0xFFFB) to BA 00 00 00 00 (mov edx, 0 = IPPROTO_IP).

Backup: airflow_server.dll.bak

3. Native MSVC Runtime — C++ Exception Handling

Wine's builtin vcruntime140_1.dll implements __CxxFrameHandler4 (the MSVC C++ exception handler) with bugs that corrupt exception objects and catch block state. This caused a chain of crashes:

  • DEP violation in foundation.dll vtable entry pointing to .rdata
  • Access violation during exception object destruction (corrupt tree structure)
  • Garbage vtable pointers (0x21F) in catch block handlers

Fix: Force Wine to load the native Microsoft MSVC runtime DLLs that ship with Airflow instead of Wine's builtin implementations:

WINEDLLOVERRIDES="vcruntime140_1=n;vcruntime140=n;msvcp140=n;concrt140=n"

The native DLLs are already present in the Airflow directory — Wine just needs to be told to prefer them (=n means native).

4. airflow_ui.dll — QGuiApplication::screenAt() Returns Null

When pressing play on a Chromecast device, the app calls QGuiApplication::screenAt(QPoint) to get the screen geometry. Under Wine, this returns null (Wine's display management doesn't map screen coordinates the same way as Windows), and the code calls QScreen::availableGeometry() on the null pointer.

Fix: Binary patch with a code cave. Added a null check after screenAt() — if null, skip the availableGeometry() call and take the fallback path.

  • Patch site (RVA 0x4B584, 13 bytes): test rax,rax; jz +0x5C; jmp cave
  • Code cave (RVA 0x15E392, 20 bytes in CC padding): original lea rdx; mov rcx; call [availableGeometry]; jmp back

Backup: modules/airflow_ui.dll.bak

5. airflow_ui.dll — Catch Handler Virtual Call Skip

A separate crash in a catch block at airflow_ui+0x9B90 where [this+0x38] pointed to an object with a corrupted sub-object. The function null-checks [this+0x38] but always found it non-null; the corruption was deeper.

Fix: Changed conditional jump at RVA 0x9BB8 from JE (74 12) to JMP (EB 12), making the code always take the null/fallback path and skip the problematic virtual call chain.

DPI Scaling

For 4K monitors, Wine defaults to 96 DPI making the UI tiny. Set higher DPI with:

WINEPREFIX=/home/martin/.wine-airflow wine reg add 'HKCU\Control Panel\Desktop' /v LogPixels /t REG_DWORD /d 192 /f

192 = 200% scaling. Use 144 for 150%.

Remaining Issues

  • Bonjour service (port 5354): dnssd.dll tries to connect to Apple's Bonjour daemon at 127.0.0.1:5354 which doesn't exist on Linux. Device discovery works anyway via the built-in mDNS in airflow_server.dll, but Bonjour-specific features may not work.
  • AirPlay Receiver permissions: Target devices (Apple TV, Mac) need AirPlay Receiver set to "Everyone" or "Anyone on the Same Network" in their settings.

Files

File Description
Airflow.exe Main application
powrprof_override.c Source for power API stub DLL
powrprof.def Exports definition for stub DLL
powrprof.dll Compiled stub (deployed to app directory)
kernel32_hook.c Named pipe path fix (from WSL2 era, may not be needed)
modules/airflow_server.dll Patched for setsockopt level
modules/airflow_ui.dll Patched for screenAt null + catch handler skip
foundation.dll Unmodified (native MSVC runtime fixes the exception issues)
*.bak / *.bak2 Backups of original DLLs before patching
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment