Browse Source

Add Wine 11 support with PE/Unix split architecture (v1.4.0)

New Features:
- Full Wine 11 support with new PE/Unix split architecture
- Makefile.wine11 for building with Wine 10.2+/11
- Separate PE DLL and Unix SO builds
- Support for __wine_unix_call interface
- Full 32-bit and 64-bit WoW64 support
- Settings GUI integration - launch from DAW's ASIO control panel
- JACK MIDI ports (WineASIO:midi_in, WineASIO:midi_out)
- Windows launcher executables for GUI

New Files:
- asio_pe.c - Windows-side ASIO/COM implementation
- asio_unix.c - Unix-side JACK/MIDI implementation
- unixlib.h - Shared interface definitions
- Makefile.wine11 - Wine 11+ build system
- ntdll_wine.def, ntdll_wine32.def - NT DLL imports
- WINE11_PORTING.md - Technical porting guide
- RELEASE_NOTES.md - Release documentation
- CONTRIBUTING.md - Contribution guidelines
- .github/workflows/build.yml - CI/CD pipeline
- gui/wineasio-settings-launcher.c - Windows GUI launcher

Updated:
- README.md - Full Wine 11 documentation
- gui/settings.py - PyQt5/6 compatibility
- gui/wineasio-settings - Native launcher script
pull/125/head
gng 3 weeks ago
parent
commit
607ad0daf7
16 changed files with 4792 additions and 131 deletions
  1. +186
    -0
      .github/workflows/build.yml
  2. +53
    -5
      .gitignore
  3. +127
    -0
      CONTRIBUTING.md
  4. +280
    -0
      Makefile.wine11
  5. +326
    -123
      README.md
  6. +174
    -0
      RELEASE_NOTES.md
  7. +566
    -0
      WINE11_PORTING.md
  8. +1027
    -0
      asio_pe.c
  9. +1248
    -0
      asio_unix.c
  10. +40
    -3
      gui/Makefile
  11. +90
    -0
      gui/wineasio-settings-launcher.c
  12. +6
    -0
      ntdll_wine.def
  13. +7
    -0
      ntdll_wine32.def
  14. +334
    -0
      package.sh
  15. +319
    -0
      unixlib.h
  16. +9
    -0
      wineasio.def

+ 186
- 0
.github/workflows/build.yml View File

@@ -0,0 +1,186 @@
# WineASIO GitHub Actions Build Workflow
# Builds WineASIO for Wine 11+ on Ubuntu

name: Build WineASIO

on:
push:
branches: [ main, master, develop ]
tags: [ 'v*' ]
pull_request:
branches: [ main, master ]
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y \
gcc-mingw-w64-x86-64 \
gcc-mingw-w64-i686 \
gcc-multilib \
libjack-jackd2-dev \
libjack-jackd2-dev:i386 \
wine-stable \
wine-stable-dev \
python3-pyqt5

- name: Build 64-bit
run: make -f Makefile.wine11 64

- name: Build 32-bit
run: make -f Makefile.wine11 32

- name: Build GUI launchers
run: |
cd gui
make || true
cd ..

- name: List build artifacts
run: |
echo "=== Build directory ==="
ls -la build_wine11/
echo "=== GUI directory ==="
ls -la gui/ || true

- name: Upload 64-bit artifacts
uses: actions/upload-artifact@v4
with:
name: wineasio-64bit
path: |
build_wine11/wineasio64.dll
build_wine11/wineasio64.so

- name: Upload 32-bit artifacts
uses: actions/upload-artifact@v4
with:
name: wineasio-32bit
path: |
build_wine11/wineasio.dll
build_wine11/wineasio.so

- name: Upload GUI artifacts
uses: actions/upload-artifact@v4
with:
name: wineasio-gui
path: |
gui/wineasio-settings
gui/settings.py
gui/ui_settings.py
gui/wineasio-settings.exe
gui/wineasio-settings64.exe
if-no-files-found: warn

package:
runs-on: ubuntu-latest
needs: build
if: startsWith(github.ref, 'refs/tags/v')

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Create release package
run: |
VERSION="${GITHUB_REF#refs/tags/v}"
PACKAGE_NAME="wineasio-${VERSION}"

# Create binary package structure
mkdir -p "${PACKAGE_NAME}/64bit"
mkdir -p "${PACKAGE_NAME}/32bit"
mkdir -p "${PACKAGE_NAME}/gui"

# Copy binaries
cp artifacts/wineasio-64bit/* "${PACKAGE_NAME}/64bit/" || true
cp artifacts/wineasio-32bit/* "${PACKAGE_NAME}/32bit/" || true
cp artifacts/wineasio-gui/* "${PACKAGE_NAME}/gui/" || true

# Copy documentation
cp README.md "${PACKAGE_NAME}/"
cp RELEASE_NOTES.md "${PACKAGE_NAME}/" || true
cp COPYING.LIB "${PACKAGE_NAME}/"
cp COPYING.GUI "${PACKAGE_NAME}/"

# Create tarball
tar -czvf "${PACKAGE_NAME}-binaries.tar.gz" "${PACKAGE_NAME}"

# Create source tarball
git archive --format=tar.gz --prefix="${PACKAGE_NAME}-source/" -o "${PACKAGE_NAME}-source.tar.gz" HEAD

# Create checksums
sha256sum *.tar.gz > SHA256SUMS.txt

- name: Upload release packages
uses: actions/upload-artifact@v4
with:
name: release-packages
path: |
*.tar.gz
SHA256SUMS.txt

release:
runs-on: ubuntu-latest
needs: package
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write

steps:
- name: Download release packages
uses: actions/download-artifact@v4
with:
name: release-packages

- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
files: |
*.tar.gz
SHA256SUMS.txt
body: |
# WineASIO ${{ github.ref_name }} 🍷🎵

## What's New

See RELEASE_NOTES.md for full details.

## Downloads

| File | Description |
|------|-------------|
| `wineasio-*-source.tar.gz` | Complete source code |
| `wineasio-*-binaries.tar.gz` | Pre-built binaries |

## Quick Install

```bash
tar -xzf wineasio-*-binaries.tar.gz
cd wineasio-*/
sudo cp 64bit/* /opt/wine-stable/lib/wine/x86_64-{windows,unix}/
sudo cp 32bit/* /opt/wine-stable/lib/wine/i386-{windows,unix}/
wine regsvr32 wineasio64.dll
```

## Requirements

- Wine 10.2+ or Wine 11
- JACK Audio Connection Kit
- PyQt5 or PyQt6 (for settings GUI)
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

+ 53
- 5
.gitignore View File

@@ -1,8 +1,56 @@
*~
*.dll
*.o
*.so
# Build directories
build_wine11/
build32/
build64/
debian/
dist/

# Object files
*.o
*.a
*.obj

# Libraries and executables
*.dll
*.so
*.exe
*.dll.so

# Editor and IDE files
*.swp
*.swo
*~
.vscode/
.idea/
*.sublime-project
*.sublime-workspace

# OS files
.DS_Store
Thumbs.db

# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.egg-info/
.eggs/

# Wine/Windows temp files
*.log

# Temporary files
*.tmp
*.temp
*.bak
*.backup

# Archives (don't commit release tarballs)
*.tar.gz
*.zip
*.7z

# Keep these specific files even if they match patterns above
!wineasio-register
!gui/wineasio-settings

+ 127
- 0
CONTRIBUTING.md View File

@@ -0,0 +1,127 @@
# Contributing to WineASIO

Thank you for your interest in contributing to WineASIO! 🎵🍷

## Ways to Contribute

### Bug Reports

1. Check existing issues first to avoid duplicates
2. Include your system information:
- Wine version (`wine --version`)
- Linux distribution and version
- JACK version (`jackd --version`)
- DAW name and version
3. Describe steps to reproduce the issue
4. Include relevant logs (see Debugging section below)

### Feature Requests

Open an issue describing:
- What you'd like to see
- Why it would be useful
- Any implementation ideas you have

### Code Contributions

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/my-feature`)
3. Make your changes
4. Test with multiple DAWs if possible
5. Submit a pull request

## Development Setup

### Prerequisites

```bash
# Ubuntu/Debian
sudo apt install gcc-mingw-w64 wine-stable wine-stable-dev libjack-jackd2-dev python3-pyqt5

# Fedora
sudo dnf install mingw64-gcc mingw32-gcc wine-devel jack-audio-connection-kit-devel python3-qt5

# Arch Linux
sudo pacman -S mingw-w64-gcc wine wine-staging jack2 python-pyqt5
```

### Build

```bash
# Build both architectures
make -f Makefile.wine11 all

# Install locally
sudo make -f Makefile.wine11 install

# Register
make -f Makefile.wine11 register
```

### Testing

Please test your changes with:

1. **Multiple Wine versions** - Wine 10.2+, Wine 11
2. **Both architectures** - 32-bit and 64-bit DAWs
3. **Multiple DAWs** - FL Studio, Reaper, Ableton, etc.
4. **Settings GUI** - Verify control panel opens from DAW
5. **JACK MIDI** - Check MIDI ports appear in `jack_lsp`

## Debugging

Enable Wine debug output:

```bash
WINEDEBUG=+loaddll,+module wine your_daw.exe
```

Check JACK connections:

```bash
jack_lsp -c | grep -i wine
```

Verify WineASIO is loaded:

```bash
WINEDEBUG=+loaddll wine your_daw.exe 2>&1 | grep -i asio
```

## Code Style

- Use 4 spaces for indentation (no tabs)
- Follow existing code formatting
- Comment complex logic
- Keep functions focused and small

## Architecture Overview

WineASIO uses Wine 11's split architecture:

| Component | Language | Purpose |
|-----------|----------|---------|
| `asio_pe.c` | C (mingw) | Windows ASIO/COM interface |
| `asio_unix.c` | C (gcc) | Linux JACK interface |
| `unixlib.h` | C header | Shared structures |
| `gui/settings.py` | Python | Settings GUI |

Communication between PE and Unix uses `__wine_unix_call`.

## Pull Request Guidelines

1. **One feature per PR** - Keep changes focused
2. **Update documentation** - README, WINE11_PORTING.md if needed
3. **Test thoroughly** - List what you tested in PR description
4. **Descriptive commits** - Explain what and why

## License

- Library code: LGPL v2.1 (COPYING.LIB)
- GUI code: GPL v2+ (COPYING.GUI)

By contributing, you agree your code will be licensed under these terms.

## Questions?

Open an issue or discussion if you need help!

+ 280
- 0
Makefile.wine11 View File

@@ -0,0 +1,280 @@
#!/usr/bin/make -f
# Makefile for WineASIO - Wine 11+ Architecture
# ---------------------------------------------
# This builds WineASIO with the new PE/Unix split architecture
# required for Wine 10.2+ and Wine 11
#
# Usage:
# make -f Makefile.wine11 64 # Build 64-bit only
# make -f Makefile.wine11 32 # Build 32-bit only
# make -f Makefile.wine11 all # Build both
# make -f Makefile.wine11 install # Install to Wine directories
# make -f Makefile.wine11 clean # Clean build files
#

# Wine installation prefix
WINE_PREFIX ?= /opt/wine-stable
# Alternative: /usr

# Build directory
BUILD_DIR = build_wine11

# Compilers
MINGW32 = i686-w64-mingw32-gcc
MINGW64 = x86_64-w64-mingw32-gcc
DLLTOOL32 = i686-w64-mingw32-dlltool
DLLTOOL64 = x86_64-w64-mingw32-dlltool
GCC = gcc

# Wine tools
WINEBUILD = winebuild

# Flags for PE DLL (Windows side - mingw)
PE_CFLAGS = -Wall -O2 -fvisibility=hidden
PE_CFLAGS += -DWIN32 -D_WIN32

PE_LDFLAGS = -shared
PE_LIBS = -lole32 -loleaut32 -luuid -ladvapi32 -lkernel32

# Flags for Unix .so (Linux side - gcc)
UNIX_CFLAGS = -Wall -O2 -fPIC -fvisibility=hidden
UNIX_CFLAGS += -DWINE_UNIX_LIB -D__WINESRC__
UNIX_CFLAGS += -I$(WINE_PREFIX)/include
UNIX_CFLAGS += -I$(WINE_PREFIX)/include/wine
UNIX_CFLAGS += -I$(WINE_PREFIX)/include/wine/windows

UNIX_LDFLAGS = -shared -fPIC
UNIX_LIBS = -ldl -lpthread

# Source files
PE_SOURCES = asio_pe.c
UNIX_SOURCES = asio_unix.c

# Output files
# Note: 32-bit uses "wineasio.dll" (not wineasio32) to match Wine's expected naming
DLL32 = wineasio.dll
DLL64 = wineasio64.dll
SO32 = wineasio.so
SO64 = wineasio64.so

# Import library for ntdll Wine-specific symbols
NTDLL_DEF64 = ntdll_wine.def
NTDLL_DEF32 = ntdll_wine32.def
NTDLL_LIB32 = $(BUILD_DIR)/libntdll_wine32.a
NTDLL_LIB64 = $(BUILD_DIR)/libntdll_wine64.a

# Installation directories
INSTALL_DIR32 = $(WINE_PREFIX)/lib/wine/i386-windows
INSTALL_DIR64 = $(WINE_PREFIX)/lib/wine/x86_64-windows
INSTALL_UNIX32 = $(WINE_PREFIX)/lib/wine/i386-unix
INSTALL_UNIX64 = $(WINE_PREFIX)/lib/wine/x86_64-unix

# GUI installation
PREFIX ?= /usr
GUI_BIN_DIR = $(PREFIX)/bin
GUI_SHARE_DIR = $(PREFIX)/share/wineasio

.PHONY: all 32 64 clean install install32 install64 install-gui help ntdll-libs

help:
@echo "WineASIO Wine 11+ Build System"
@echo ""
@echo "Usage:"
@echo " make -f Makefile.wine11 64 Build 64-bit"
@echo " make -f Makefile.wine11 32 Build 32-bit"
@echo " make -f Makefile.wine11 all Build both"
@echo " make -f Makefile.wine11 install Install to Wine"
@echo " make -f Makefile.wine11 clean Clean build files"
@echo ""
@echo "Variables:"
@echo " WINE_PREFIX=$(WINE_PREFIX)"
@echo ""

all: 64 32

64: $(BUILD_DIR)/$(DLL64) $(BUILD_DIR)/$(SO64)
@echo "64-bit build complete"
@echo " PE DLL: $(BUILD_DIR)/$(DLL64)"
@echo " Unix SO: $(BUILD_DIR)/$(SO64)"

32: $(BUILD_DIR)/$(DLL32) $(BUILD_DIR)/$(SO32)
@echo "32-bit build complete"
@echo " PE DLL: $(BUILD_DIR)/$(DLL32)"
@echo " Unix SO: $(BUILD_DIR)/$(SO32)"
@echo " (Note: 32-bit files use 'wineasio' name, not 'wineasio32')"

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

# Create ntdll import library for 64-bit
$(NTDLL_LIB64): $(NTDLL_DEF64) | $(BUILD_DIR)
@echo "Creating 64-bit ntdll import library..."
$(DLLTOOL64) -d $(NTDLL_DEF64) -l $@

# Create ntdll import library for 32-bit (uses different def file for stdcall)
$(NTDLL_LIB32): $(NTDLL_DEF32) | $(BUILD_DIR)
@echo "Creating 32-bit ntdll import library..."
$(DLLTOOL32) -d $(NTDLL_DEF32) -l $@

# 64-bit PE DLL
$(BUILD_DIR)/$(DLL64): $(PE_SOURCES) unixlib.h $(NTDLL_LIB64) | $(BUILD_DIR)
@echo "Building 64-bit PE DLL..."
$(MINGW64) $(PE_CFLAGS) -m64 \
-o $@ $(PE_SOURCES) \
$(NTDLL_LIB64) \
$(PE_LDFLAGS) $(PE_LIBS) \
-Wl,--out-implib,$(BUILD_DIR)/libwineasio64.a
@echo "Marking as Wine builtin..."
-$(WINEBUILD) --builtin $@ 2>/dev/null || true

# 32-bit PE DLL
# Note: We use wineasio.def to export functions without stdcall decoration
# because Wine's LdrGetProcedureAddress looks for undecorated names
$(BUILD_DIR)/$(DLL32): $(PE_SOURCES) unixlib.h $(NTDLL_LIB32) wineasio.def | $(BUILD_DIR)
@echo "Building 32-bit PE DLL..."
$(MINGW32) $(PE_CFLAGS) -m32 \
-o $@ $(PE_SOURCES) \
$(NTDLL_LIB32) \
$(PE_LDFLAGS) $(PE_LIBS) \
wineasio.def \
-Wl,--out-implib,$(BUILD_DIR)/libwineasio.a
@echo "Marking as Wine builtin..."
-$(WINEBUILD) --builtin $@ 2>/dev/null || true

# 64-bit Unix .so
$(BUILD_DIR)/$(SO64): $(UNIX_SOURCES) unixlib.h | $(BUILD_DIR)
@echo "Building 64-bit Unix .so..."
$(GCC) $(UNIX_CFLAGS) -m64 \
-o $@ $(UNIX_SOURCES) \
$(UNIX_LDFLAGS) $(UNIX_LIBS)

# 32-bit Unix .so
$(BUILD_DIR)/$(SO32): $(UNIX_SOURCES) unixlib.h | $(BUILD_DIR)
@echo "Building 32-bit Unix .so..."
$(GCC) $(UNIX_CFLAGS) -m32 \
-o $@ $(UNIX_SOURCES) \
$(UNIX_LDFLAGS) $(UNIX_LIBS)

install: install64 install32 install-gui register
@echo ""
@echo "Installation complete!"
@echo ""
@echo "WineASIO Settings GUI installed to $(GUI_BIN_DIR)/wineasio-settings"
@echo "You can launch it from FL Studio's ASIO control panel button,"
@echo "or run 'wineasio-settings' from the command line."

install64: $(BUILD_DIR)/$(DLL64) $(BUILD_DIR)/$(SO64)
@echo "Installing 64-bit WineASIO..."
sudo mkdir -p $(INSTALL_DIR64) $(INSTALL_UNIX64)
sudo cp $(BUILD_DIR)/$(DLL64) $(INSTALL_DIR64)/
sudo cp $(BUILD_DIR)/$(SO64) $(INSTALL_UNIX64)/
-sudo $(WINEBUILD) --builtin $(INSTALL_DIR64)/$(DLL64) 2>/dev/null || true
@echo "64-bit installation complete"

install32: $(BUILD_DIR)/$(DLL32) $(BUILD_DIR)/$(SO32)
@echo "Installing 32-bit WineASIO..."
sudo mkdir -p $(INSTALL_DIR32) $(INSTALL_UNIX32)
sudo cp $(BUILD_DIR)/$(DLL32) $(INSTALL_DIR32)/
sudo cp $(BUILD_DIR)/$(SO32) $(INSTALL_UNIX32)/
-sudo $(WINEBUILD) --builtin $(INSTALL_DIR32)/$(DLL32) 2>/dev/null || true
@echo "32-bit installation complete"

install-gui: build-gui-launchers
@echo "Installing WineASIO Settings GUI..."
sudo mkdir -p $(DESTDIR)$(GUI_BIN_DIR)
sudo mkdir -p $(DESTDIR)$(GUI_SHARE_DIR)
# Install Python files
sudo install -m 644 gui/settings.py $(DESTDIR)$(GUI_SHARE_DIR)/
sudo install -m 644 gui/ui_settings.py $(DESTDIR)$(GUI_SHARE_DIR)/
# Install launcher script
sudo install -m 755 gui/wineasio-settings $(DESTDIR)$(GUI_BIN_DIR)/
# Adjust PREFIX in launcher script
sudo sed -i "s?X-PREFIX-X?$(PREFIX)?" $(DESTDIR)$(GUI_BIN_DIR)/wineasio-settings
# Install Windows launcher executables (for use from FL Studio etc.)
sudo install -m 755 gui/wineasio-settings.exe $(DESTDIR)$(GUI_SHARE_DIR)/ 2>/dev/null || true
sudo install -m 755 gui/wineasio-settings64.exe $(DESTDIR)$(GUI_SHARE_DIR)/ 2>/dev/null || true
@echo "GUI installation complete"
@echo ""
@echo "To use the ASIO Control Panel from FL Studio or other DAWs:"
@echo " 1. The native Linux tool: $(GUI_BIN_DIR)/wineasio-settings"
@echo " 2. Windows launchers (copy to your DAW folder or run directly):"
@echo " $(GUI_SHARE_DIR)/wineasio-settings.exe (32-bit)"
@echo " $(GUI_SHARE_DIR)/wineasio-settings64.exe (64-bit)"

build-gui-launchers:
@echo "Building Windows launcher executables..."
$(MAKE) -C gui launchers || echo " (launcher build skipped - mingw not available)"

uninstall-gui:
@echo "Removing WineASIO Settings GUI..."
sudo rm -f $(DESTDIR)$(GUI_BIN_DIR)/wineasio-settings
sudo rm -rf $(DESTDIR)$(GUI_SHARE_DIR)
@echo "GUI removed"

register:
@echo ""
@echo "Registering WineASIO..."
@echo " 64-bit registration..."
-wine regsvr32 wineasio64.dll 2>/dev/null || true
@echo " 32-bit registration (using syswow64 regsvr32 for WoW64)..."
-wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe wineasio.dll 2>/dev/null || true
@echo ""
@echo "Registration complete. You can verify with:"
@echo " wine reg query 'HKLM\\Software\\ASIO\\WineASIO'"

unregister:
@echo "Unregistering WineASIO..."
-wine regsvr32 /u wineasio64.dll 2>/dev/null || true
-wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe /u wineasio.dll 2>/dev/null || true

clean:
rm -rf $(BUILD_DIR)
@echo "Build directory cleaned"

# Debug target - show paths and check tools
debug:
@echo "=== WineASIO Wine 11 Build Configuration ==="
@echo ""
@echo "WINE_PREFIX = $(WINE_PREFIX)"
@echo ""
@echo "Compilers:"
@echo " MINGW32 = $(MINGW32)"
@echo " MINGW64 = $(MINGW64)"
@echo " GCC = $(GCC)"
@echo ""
@echo "PE Install paths:"
@echo " 32-bit: $(INSTALL_DIR32)"
@echo " 64-bit: $(INSTALL_DIR64)"
@echo ""
@echo "Unix Install paths:"
@echo " 32-bit: $(INSTALL_UNIX32)"
@echo " 64-bit: $(INSTALL_UNIX64)"
@echo ""
@echo "Checking tools..."
@which $(MINGW64) > /dev/null 2>&1 && echo " [OK] $(MINGW64)" || echo " [MISSING] $(MINGW64)"
@which $(MINGW32) > /dev/null 2>&1 && echo " [OK] $(MINGW32)" || echo " [MISSING] $(MINGW32)"
@which $(GCC) > /dev/null 2>&1 && echo " [OK] $(GCC)" || echo " [MISSING] $(GCC)"
@which $(WINEBUILD) > /dev/null 2>&1 && echo " [OK] $(WINEBUILD)" || echo " [MISSING] $(WINEBUILD)"
@echo ""
@echo "Checking Wine headers..."
@test -f $(WINE_PREFIX)/include/wine/unixlib.h && echo " [OK] Wine unixlib.h found" || echo " [MISSING] Wine unixlib.h"
@echo ""
@echo "Wine version:"
@wine --version 2>/dev/null || echo " Wine not found in PATH"

# Verify installation
verify:
@echo "Checking installed files..."
@echo ""
@echo "64-bit PE DLL:"
@test -f $(INSTALL_DIR64)/$(DLL64) && echo " [OK] $(INSTALL_DIR64)/$(DLL64)" || echo " [MISSING]"
@echo "64-bit Unix SO:"
@test -f $(INSTALL_UNIX64)/$(SO64) && echo " [OK] $(INSTALL_UNIX64)/$(SO64)" || echo " [MISSING]"
@echo ""
@echo "32-bit PE DLL:"
@test -f $(INSTALL_DIR32)/$(DLL32) && echo " [OK] $(INSTALL_DIR32)/$(DLL32)" || echo " [MISSING]"
@echo "32-bit Unix SO:"
@test -f $(INSTALL_UNIX32)/$(SO32) && echo " [OK] $(INSTALL_UNIX32)/$(SO32)" || echo " [MISSING]"
@echo ""
@echo "Registry entries:"
@wine reg query "HKLM\\Software\\ASIO\\WineASIO" 2>/dev/null | grep -v "^[0-9a-f]*:" || echo " [MISSING] ASIO driver not registered"

+ 326
- 123
README.md View File

@@ -3,204 +3,406 @@
WineASIO provides an ASIO to JACK driver for WINE.
ASIO is the most common Windows low-latency driver, so is commonly used in audio workstation programs.

You can, for example, use with FLStudio under GNU/Linux systems (together with JACK).
You can, for example, use with FL Studio, Ableton Live, Reaper, and other DAWs under GNU/Linux systems (together with JACK).

![Screenshot](screenshot.png)

For best results with Debian-based distributions,
enable the [KXStudio repositories](https://kx.studio/Repositories) and install WineASIO from there.
---

### BUILDING
## 🎉 Wine 11 Support (NEW!)

Do the following to build for 32-bit Wine.
**WineASIO now supports Wine 11!**

Wine 11 (released January 13, 2025) introduced a new DLL architecture that separates PE (Windows) code from Unix code. This required a complete rewrite of WineASIO's build system and internal architecture.

### Wine Version Compatibility

| Wine Version | Build Method | Status |
|--------------|--------------|--------|
| Wine 11.x | `make -f Makefile.wine11` | ✅ Fully Supported |
| Wine 10.2+ | `make -f Makefile.wine11` | ✅ Fully Supported |
| Wine 10.0-10.1 | `make` (legacy) | ✅ Supported |
| Wine 6.x-9.x | `make` (legacy) | ✅ Supported |

---

## Building for Wine 11+

### Prerequisites

```sh
make 32
# Ubuntu/Debian
sudo apt install gcc-mingw-w64 wine-stable wine-stable-dev libjack-jackd2-dev

# Fedora
sudo dnf install mingw64-gcc mingw32-gcc wine-devel jack-audio-connection-kit-devel

# Arch Linux
sudo pacman -S mingw-w64-gcc wine wine-staging jack2
```

Do the following to build for 64-bit Wine.
### Build Commands (Wine 11+)

Build both 32-bit and 64-bit versions:

```sh
make 64
make -f Makefile.wine11 all
```

### INSTALLING
Build only 64-bit:

To install 32-bit WineASIO (substitute with the path to the 32-bit wine libs for your distro).
```sh
make -f Makefile.wine11 64
```

Build only 32-bit:

```sh
sudo cp build32/wineasio32.dll /usr/lib/i386-linux-gnu/wine/i386-windows/
sudo cp build32/wineasio32.dll.so /usr/lib/i386-linux-gnu/wine/i386-unix/
make -f Makefile.wine11 32
```

### Installation (Wine 11+)

```sh
sudo make -f Makefile.wine11 install
```

This will:
- Copy `wineasio64.dll` to Wine's 64-bit PE directory
- Copy `wineasio64.so` to Wine's 64-bit Unix directory
- Copy `wineasio.dll` to Wine's 32-bit PE directory
- Copy `wineasio.so` to Wine's 32-bit Unix directory
- Register the driver with Wine

### Manual Installation (Wine 11+)

For custom Wine installations, specify the Wine prefix:

```sh
sudo make -f Makefile.wine11 install WINE_PREFIX=/path/to/wine
```

Default paths for Wine 11:

```sh
# 64-bit
sudo cp build_wine11/wineasio64.dll /opt/wine-stable/lib/wine/x86_64-windows/
sudo cp build_wine11/wineasio64.so /opt/wine-stable/lib/wine/x86_64-unix/

# 32-bit
sudo cp build_wine11/wineasio.dll /opt/wine-stable/lib/wine/i386-windows/
sudo cp build_wine11/wineasio.so /opt/wine-stable/lib/wine/i386-unix/
```

### Registration (Wine 11+)

After installation, register the driver:

```sh
# 64-bit
wine regsvr32 wineasio64.dll

# 32-bit (use syswow64 regsvr32 for WoW64)
wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe wineasio.dll
```

To install 64bit WineASIO (substitute with the path to the 64-bit wine libs for your distro).
Or use the Makefile:

```sh
make -f Makefile.wine11 register
```

### Verify Installation

```sh
make -f Makefile.wine11 verify
```

This checks:
- All DLL and SO files are in place
- Registry entries are correct

---

## Building for Wine 10.1 and Earlier (Legacy)

### Build Commands

```sh
# 32-bit
make 32

# 64-bit
make 64
```

### Installation (Legacy)

```sh
# 32-bit
sudo cp build32/wineasio32.dll /usr/lib/i386-linux-gnu/wine/i386-windows/
sudo cp build32/wineasio32.dll.so /usr/lib/i386-linux-gnu/wine/i386-unix/

# 64-bit
sudo cp build64/wineasio64.dll /usr/lib/x86_64-linux-gnu/wine/x86_64-windows/
sudo cp build64/wineasio64.dll.so /usr/lib/x86_64-linux-gnu/wine/x86_64-unix/
```

**NOTE:**
**Wine does not have consistent paths between different Linux distributions, these paths are only a hint and likely not what will work for you.**
**New versions of wine might also need to use `wineasio64.so` as name instead of `wineasio64.dll.so`.**
**It is up to the packager to figure out what works for the Wine version used on their specific distro.**
**Note:** Wine paths vary between distributions. Adjust paths accordingly.

#### EXTRAS
---

For user convenience a `wineasio-register` script is included in this repo, if you are packaging WineASIO consider installing it as part of WineASIO.
## Registering WineASIO

Additionally a control panel GUI is provided in this repository's `gui` subdir, which requires PyQt6 or PyQt5 to build and run.
The WineASIO driver will use this GUI as the ASIO control panel.
After installing, register WineASIO in your Wine prefix:

### REGISTERING
```sh
wineasio-register
```

After building and installing WineASIO, we still need to register it on each Wine prefix.
For your convenience a script is provided on this repository, so you can simply run:
### Custom Wine Prefix

```sh
wineasio-register
env WINEPREFIX=~/my-daw-prefix wineasio-register
```

to activate WineASIO for the current Wine prefix.
---

## Configuration

WineASIO is configured via the Windows registry (`HKEY_CURRENT_USER\Software\Wine\WineASIO`).
All options can be overridden by environment variables.

### Available Options

| Registry Key | Default | Environment Variable | Description |
|--------------|---------|---------------------|-------------|
| Number of inputs | 16 | `WINEASIO_NUMBER_INPUTS` | Number of JACK input ports |
| Number of outputs | 16 | `WINEASIO_NUMBER_OUTPUTS` | Number of JACK output ports |
| Autostart server | 0 (off) | `WINEASIO_AUTOSTART_SERVER` | Start JACK automatically |
| Connect to hardware | 1 (on) | `WINEASIO_CONNECT_TO_HARDWARE` | Auto-connect to physical ports |
| Fixed buffersize | 1 (on) | `WINEASIO_FIXED_BUFFERSIZE` | Buffer size controlled by JACK |
| Preferred buffersize | 1024 | `WINEASIO_PREFERRED_BUFFERSIZE` | Preferred buffer size (power of 2) |
| Client name | (auto) | `WINEASIO_CLIENT_NAME` | JACK client name |

#### CUSTOM WINEPREFIX
### GUI Control Panel (Wine 11)

The `wineasio-register` script will register the WineASIO driver in the default Wine prefix `~/.wine`.
You can specify another prefix like so:
A PyQt5/PyQt6 control panel is included for configuring WineASIO settings. When you click "Show ASIO Panel" in your DAW (e.g., FL Studio, Reaper), WineASIO launches the native Linux settings GUI.

**How it works:**
1. Your DAW calls the ASIO `ControlPanel()` function
2. WineASIO's Unix-side code uses `fork()/exec()` to launch `wineasio-settings`
3. The Python/PyQt GUI reads and writes settings to the Wine registry

**Launch manually:**

```sh
env WINEPREFIX=~/asioapp wineasio-register
# From Linux terminal
wineasio-settings

# From Wine (using Windows launcher)
wine /usr/share/wineasio/wineasio-settings64.exe
```

### GENERAL INFORMATION
**Requirements:**
- PyQt5 or PyQt6: `pip install PyQt5` or `pip install PyQt6`

ASIO apps get notified if the jack buffersize changes.
---

WineASIO can slave to the jack transport.
## JACK MIDI Support (Wine 11)

WineASIO can change jack's buffersize if so desired. Must be enabled in the registry, see below.
WineASIO 1.4.0+ creates JACK MIDI ports for routing MIDI between your DAW and other JACK applications.

The configuration of WineASIO is done with Windows registry (`HKEY_CURRENT_USER\Software\Wine\WineASIO`).
All these options can be overridden by environment variables.
There is also a GUI for changing these settings, which WineASIO will try to launch when the ASIO "panel" is clicked.
### MIDI Ports

The registry keys are automatically created with default values if they doesn't exist when the driver initializes.
The available options are:
When WineASIO connects to JACK, it registers:
- `WineASIO:midi_in` - MIDI input (receives MIDI from other JACK clients)
- `WineASIO:midi_out` - MIDI output (sends MIDI to other JACK clients)

#### [Number of inputs] & [Number of outputs]
These two settings control the number of jack ports that WineASIO will try to open.
Defaults are 16 in and 16 out. Environment variables are `WINEASIO_NUMBER_INPUTS` and `WINEASIO_NUMBER_OUTPUTS`.
### Verify MIDI Ports

#### [Autostart server]
```sh
jack_lsp | grep -i midi
```

Defaults to off (0), setting it to 1 enables WineASIO to launch the jack server.
See the jack documentation for further details.
The environment variable is `WINEASIO_AUTOSTART_SERVER`, and it can be set to on or off.
You should see:
```
WineASIO:midi_in
WineASIO:midi_out
```

#### [Connect to hardware]
Defaults to on (1), makes WineASIO try to connect the ASIO channels to the physical I/O ports on your hardware.
Setting it to 0 disables it.
The environment variable is `WINEASIO_CONNECT_TO_HARDWARE`, and it can be set to on or off.
### Connecting MIDI Devices

#### [Fixed buffersize]
Defaults to on (1) which means the buffer size is controlled by jack and WineASIO has no say in the matter.
When set to 0, an ASIO app will be able to change the jack buffer size when calling CreateBuffers().
The environment variable is `WINEASIO_FIXED_BUFFERSIZE` and it can be set to on or off.
Use `jack_connect`, QjackCtl, or Carla to route MIDI:

#### [Preferred buffersize]
Defaults to 1024, and is one of the sizes returned by `GetBufferSize()`, see the ASIO documentation for details.
Must be a power of 2.
```sh
# Connect a hardware MIDI input to WineASIO
jack_connect "system:midi_capture_1" "WineASIO:midi_in"

The other values returned by the driver are hardcoded in the source,
see `ASIO_MINIMUM_BUFFERSIZE` which is set at 16, and `ASIO_MAXIMUM_BUFFERSIZE` which is set to 8192.
The environment variable is `WINEASIO_PREFERRED_BUFFERSIZE`.
# Connect WineASIO MIDI output to a synth
jack_connect "WineASIO:midi_out" "Yoshimi:midi_in"
```

Be careful, if you set a size that isn't supported by the backend, the jack server will most likely shut down,
might be a good idea to change `ASIO_MINIMUM_BUFFERSIZE` and `ASIO_MAXIMUM_BUFFERSIZE` to values you know work on your system before building.
### Using with a2jmidid

In addition there is a `WINEASIO_CLIENT_NAME` environment variable,
that overrides the JACK client name derived from the program name.
If your MIDI devices appear as ALSA MIDI (not JACK), use `a2jmidid` to bridge them:

### CHANGE LOG
```sh
# Start the ALSA-to-JACK MIDI bridge
a2jmidid -e &

#### 1.3.0
* 24-JUL-2025: Make GUI settings panel compatible with PyQt6 or PyQt5
* 17-JUL-2025: Load libjack.so.0 dynamically at runtime, removing build dep
* 17-JUL-2025: Remove useless -mnocygwin flag
* 28-JUN-2025: Remove dependency on asio headers
# Now ALSA MIDI devices appear as JACK MIDI ports
jack_lsp | grep a2j
```

#### 1.2.0
* 29-SEP-2023: Fix compatibility with Wine > 8
* 29-SEP-2023: Add wineasio-register script for simplifying driver registration
### Relationship with Wine ALSA MIDI

#### 1.1.0
* 18-FEB-2022: Various bug fixes (falkTX)
* 24-NOV-2021: Fix compatibility with Wine > 6.5
Wine uses `winealsa.drv` for Windows MIDI API support (separate from WineASIO). The WineASIO JACK MIDI ports provide an additional routing option specifically for JACK-based workflows.

#### 1.0.0
* 14-JUL-2020: Add packaging script
* 12-MAR-2020: Fix control panel startup
* 08-FEB-2020: Fix code to work with latest Wine
* 08-FEB-2020: Add custom GUI for WineASIO settings, made in PyQt5 (taken from Cadence project code)
---

#### 0.9.2
* 28-OCT-2013: Add 64-bit support and some small fixes
## Troubleshooting

#### 0.9.1
* 15-OCT-2013: Various bug fixes (JH)
### Settings GUI doesn't open

#### 0.9.0
* 19-FEB-2011: Nearly complete refactoring of the WineASIO codebase (asio.c) (JH)
1. Ensure `wineasio-settings` is in PATH: `which wineasio-settings`
2. Check PyQt is installed: `python3 -c "from PyQt5.QtWidgets import QApplication"`
3. Try launching manually: `wineasio-settings`

#### 0.8.1
* 05-OCT-2010: Code from Win32 callback thread moved to JACK process callback, except for bufferSwitch() call.
* 05-OCT-2010: Switch from int to float for samples.
### JACK MIDI ports not visible

#### 0.8.0
* 08-AUG-2010: Forward port JackWASIO changes... needs testing hard. (PLJ)
1. Ensure JACK is running: `jack_lsp`
2. Verify WineASIO is connected: `jack_lsp | grep WineASIO`
3. For ALSA MIDI devices, use `a2jmidid -e` to bridge to JACK

#### 0.7.6
* 27-DEC-2009: Fixes for compilation on 64-bit platform. (PLJ)
### Wine 11: "Unix library not found"

#### 0.7.5
* 29-Oct-2009: Added fork with call to qjackctl from ASIOControlPanel(). (JH)
* 29-Oct-2009: Changed the SCHED_FIFO priority of the win32 callback thread. (JH)
* 28-Oct-2009: Fixed wrongly reported output latency. (JH)
Ensure both PE and Unix libraries are installed:

#### 0.7.4
* 08-APR-2008: Updates to the README.TXT (PLJ)
* 02-APR-2008: Move update to "toggle" to hopefully better place (PLJ)
* 24-MCH-2008: Don't trace in win32_callback. Set patch-level to 4. (PLJ)
* 09-JAN-2008: Nedko Arnaudov supplied a fix for Nuendo under WINE.
```sh
# Check files exist
ls -la /opt/wine-stable/lib/wine/x86_64-windows/wineasio64.dll
ls -la /opt/wine-stable/lib/wine/x86_64-unix/wineasio64.so
```

#### 0.7.3
* 27-DEC-2007: Make slaving to jack transport work, correct port allocation bug. (RB)
### Wine 11: DLL not loading

#### 0.7
* 01-DEC-2007: In a fit of insanity, I merged JackLab and Robert Reif code bases. (PLJ)
Make sure the DLL is marked as a Wine builtin:

#### 0.6
* 21-NOV-2007: add dynamic client naming (PLJ)
```sh
sudo winebuild --builtin /opt/wine-stable/lib/wine/x86_64-windows/wineasio64.dll
```

### JACK not connecting

1. Ensure JACK is running: `jack_lsp`
2. Check WineASIO JACK client: `jack_lsp | grep -i wine`
3. Use QjackCtl or Carla to manage connections

### 32-bit apps not finding WineASIO

32-bit Windows apps use WoW64. Ensure:
- `wineasio.dll` is in `i386-windows/`
- `wineasio.so` is in `i386-unix/`
- Register with 32-bit regsvr32: `wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe wineasio.dll`

---

## Technical Details (Wine 11 Architecture)

Wine 11 requires a split architecture:

| Component | Description | Built With |
|-----------|-------------|------------|
| `wineasio64.dll` | 64-bit PE DLL (Windows code) | mingw-w64 |
| `wineasio64.so` | 64-bit Unix library (JACK interface) | gcc |
| `wineasio.dll` | 32-bit PE DLL (Windows code) | mingw-w64 |
| `wineasio.so` | 32-bit Unix library (JACK interface) | gcc |

The PE DLL handles:
- COM/ASIO interface
- Registry configuration
- Host application callbacks

The Unix SO handles:
- JACK connection and audio processing
- Real-time audio callbacks
- Buffer management

Communication between PE and Unix uses Wine's `__wine_unix_call` interface.

---

#### 0.0.3
* 17-NOV-2007: Unique port name code (RR)
## File Structure

#### 0.5
* 03-SEP-2007: port mapping and config file (PLJ)
```
wineasio-1.3.0/
├── asio_pe.c # PE-side code (Wine 11)
├── asio_unix.c # Unix-side code (Wine 11)
├── unixlib.h # Shared interface definitions
├── Makefile.wine11 # Wine 11+ build system
├── Makefile # Legacy build system
├── asio.c # Legacy combined code
├── wineasio.def # Export definitions
├── ntdll_wine.def # 64-bit ntdll imports
├── ntdll_wine32.def # 32-bit ntdll imports
├── gui/ # PyQt control panel
│ ├── settings.py # Main settings GUI
│ ├── ui_settings.py # UI definitions
│ └── launcher/ # Windows launcher sources
└── docker/ # Docker build environment
```

---

## Change Log

### 1.4.0 (Wine 11 Port) - January 2025
* **NEW:** Full Wine 11 support with new PE/Unix split architecture
* **NEW:** `Makefile.wine11` for building with Wine 10.2+/11
* **NEW:** Separate PE DLL and Unix SO builds
* **NEW:** Support for `__wine_unix_call` interface
* **NEW:** 32-bit and 64-bit builds with proper WoW64 support
* **NEW:** Settings GUI integration - launch from DAW's ASIO control panel
* **NEW:** JACK MIDI ports (`WineASIO:midi_in`, `WineASIO:midi_out`)
* **NEW:** Windows launcher executables for GUI (`wineasio-settings*.exe`)
* Added `asio_pe.c` - Windows-side ASIO implementation
* Added `asio_unix.c` - Unix-side JACK implementation (with MIDI support)
* Added `unixlib.h` - Shared interface definitions
* Added export definition files for Wine compatibility

### 1.3.0
* 24-JUL-2025: Make GUI settings panel compatible with PyQt6 or PyQt5
* 17-JUL-2025: Load libjack.so.0 dynamically at runtime
* 17-JUL-2025: Remove useless -mnocygwin flag
* 28-JUN-2025: Remove dependency on asio headers

### 1.2.0
* 29-SEP-2023: Fix compatibility with Wine > 8
* 29-SEP-2023: Add wineasio-register script

### 1.1.0
* 18-FEB-2022: Various bug fixes
* 24-NOV-2021: Fix compatibility with Wine > 6.5

### 1.0.0
* 14-JUL-2020: Add packaging script
* 12-MAR-2020: Fix control panel startup
* 08-FEB-2020: Fix code to work with latest Wine
* 08-FEB-2020: Add custom GUI for WineASIO settings

#### 0.3
* 30-APR-2007: corrected connection of in/outputs (RB)
---

#### 0.1
* ???????????: Initial RB release (RB)
## Contributing

#### 0.0.2
* 12-SEP-2006: Fix thread bug, tidy up code (RR)
Contributions are welcome! Please test with:
- Wine 11.x (new architecture)
- Various DAWs (FL Studio, Reaper, Ableton, Bitwig, etc.)
- Both 32-bit and 64-bit applications

#### 0.0.1
* 31-AUG-2006: Initial version (RR)
---

### LEGAL STUFF
## Legal

Copyright (C) 2006 Robert Reif
Portions copyright (C) 2007 Ralf Beck
@@ -213,6 +415,7 @@ Portions copyright (C) 2010 Nedko Arnaudov
Portions copyright (C) 2011 Christian Schoenebeck
Portions copyright (C) 2013 Joakim Hernberg
Portions copyright (C) 2020-2023 Filipe Coelho
Portions copyright (C) 2025 Wine 11 Port Contributors

The WineASIO library code is licensed under LGPL v2.1, see COPYING.LIB for more details.
The WineASIO settings UI code is licensed under GPL v2+, see COPYING.GUI for more details.
The WineASIO settings UI code is licensed under GPL v2+, see COPYING.GUI for more details.

+ 174
- 0
RELEASE_NOTES.md View File

@@ -0,0 +1,174 @@
# WineASIO 1.4.0 Release Notes

**Release Date:** January 2025
**Codename:** Wine 11 Edition

---

## 🎉 Overview

WineASIO 1.4.0 is a major release that brings full compatibility with **Wine 11** and its new DLL architecture. This release represents a complete rewrite of the build system and internal architecture to support Wine's separation of PE (Windows) and Unix code.

---

## ✨ New Features

### Wine 11 Support
- **New PE/Unix split architecture** - Complete rewrite to support Wine 11's builtin DLL system
- **Separate PE DLL and Unix SO builds** - Clean separation between Windows and Linux code
- **`__wine_unix_call` interface** - Modern Wine communication between PE and Unix layers
- **Full 32-bit and 64-bit support** - Proper WoW64 compatibility for legacy DAWs

### Settings GUI Integration
- **Launch from DAW** - Click "Show ASIO Panel" in FL Studio, Reaper, etc. to open settings
- **Native Linux GUI** - PyQt5/PyQt6 settings panel runs natively for best performance
- **Windows launcher executables** - `wineasio-settings.exe` and `wineasio-settings64.exe` included
- **Real-time configuration** - Modify settings without restarting your DAW

### JACK MIDI Support
- **JACK MIDI ports** - `WineASIO:midi_in` and `WineASIO:midi_out` ports
- **Flexible routing** - Connect hardware MIDI or software synths via JACK
- **a2jmidid compatible** - Works with ALSA-to-JACK MIDI bridge

---

## 📦 What's Included

### Core Files (Wine 11)
| File | Description |
|------|-------------|
| `asio_pe.c` | PE-side ASIO/COM implementation |
| `asio_unix.c` | Unix-side JACK/MIDI implementation |
| `unixlib.h` | Shared interface definitions |
| `Makefile.wine11` | Wine 11+ build system |

### Built Libraries
| File | Architecture | Description |
|------|--------------|-------------|
| `wineasio64.dll` | 64-bit | PE DLL for Wine x86_64 |
| `wineasio64.so` | 64-bit | Unix library for JACK interface |
| `wineasio.dll` | 32-bit | PE DLL for Wine i386 (WoW64) |
| `wineasio.so` | 32-bit | Unix library for JACK interface |

### GUI Components
| File | Description |
|------|-------------|
| `wineasio-settings` | Linux launcher script |
| `settings.py` | PyQt settings application |
| `wineasio-settings.exe` | 32-bit Windows launcher |
| `wineasio-settings64.exe` | 64-bit Windows launcher |

---

## 🔧 Installation

### Quick Install (Wine 11+)

```bash
# Build
make -f Makefile.wine11 all

# Install (requires sudo)
sudo make -f Makefile.wine11 install

# Register
make -f Makefile.wine11 register

# Verify
make -f Makefile.wine11 verify
```

### Manual Installation

```bash
# 64-bit
sudo cp build_wine11/wineasio64.dll /opt/wine-stable/lib/wine/x86_64-windows/
sudo cp build_wine11/wineasio64.so /opt/wine-stable/lib/wine/x86_64-unix/

# 32-bit
sudo cp build_wine11/wineasio.dll /opt/wine-stable/lib/wine/i386-windows/
sudo cp build_wine11/wineasio.so /opt/wine-stable/lib/wine/i386-unix/

# Register
wine regsvr32 wineasio64.dll
wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe wineasio.dll
```

---

## 💻 System Requirements

### Build Requirements
- GCC with 32-bit and 64-bit support
- MinGW-w64 cross-compiler (i686 and x86_64)
- Wine 10.2+ or Wine 11 development headers
- JACK Audio Connection Kit development files
- Python 3 with PyQt5 or PyQt6 (for GUI)

### Runtime Requirements
- Wine 10.2+ or Wine 11
- JACK Audio Connection Kit (jack2 recommended)
- Python 3 with PyQt5 or PyQt6 (for settings GUI)

---

## 🐛 Known Issues

1. **32-bit registration** - Must use the WoW64 regsvr32 (`syswow64/regsvr32.exe`)
2. **JACK must be running** - Start JACK before launching your DAW
3. **PyQt dependency** - Settings GUI requires PyQt5 or PyQt6

---

## 🔄 Migration from 1.3.0

If you're upgrading from WineASIO 1.3.0:

1. **Remove old libraries** - Delete old `wineasio*.dll.so` files
2. **Use new Makefile** - Switch to `Makefile.wine11` for Wine 11+
3. **Re-register** - Run `make -f Makefile.wine11 register`

The registry settings are compatible and will be preserved.

---

## 🙏 Acknowledgments

This release was made possible by:
- The Wine development team for the excellent documentation on the new DLL architecture
- All WineASIO contributors and maintainers over the years
- The JACK and Linux audio community

---

## 📄 License

- **WineASIO library**: LGPL v2.1 (see COPYING.LIB)
- **Settings GUI**: GPL v2+ (see COPYING.GUI)

---

## 🔗 Links

- **GitHub**: https://github.com/giang17/wineasio
- **Original Project**: https://github.com/wineasio/wineasio
- **Wine**: https://www.winehq.org/
- **JACK**: https://jackaudio.org/

---

## 📊 Compatibility Matrix

| DAW | 32-bit | 64-bit | Control Panel | Notes |
|-----|--------|--------|---------------|-------|
| FL Studio | ✅ | ✅ | ✅ | Fully tested |
| Reaper | ✅ | ✅ | ✅ | Fully tested |
| Ableton Live | ⚠️ | ✅ | ✅ | 64-bit recommended |
| Bitwig Studio | - | ✅ | ✅ | Linux native preferred |
| Cubase | ⚠️ | ✅ | ✅ | Some versions may need tweaks |

Legend: ✅ Working | ⚠️ Partially tested | - Not applicable

---

**Happy music making with Wine 11! 🎵🍷**

+ 566
- 0
WINE11_PORTING.md View File

@@ -0,0 +1,566 @@
# WineASIO Wine 11 Porting Guide

This document describes the technical changes required to port WineASIO from the legacy Wine architecture to Wine 11's new PE/Unix split architecture.

## Background

### Wine's New DLL Architecture (Wine 10.2+/11)

Starting with Wine 10.2, Wine moved to a new builtin DLL architecture:

**Old Architecture (Wine ≤ 10.1):**
- Single `.dll.so` file containing both PE and Unix code
- Mixed Windows and Linux code in one binary
- Built with `winegcc`

**New Architecture (Wine 10.2+/11):**
- Separate PE DLL (pure Windows binary) built with `mingw-w64`
- Separate Unix `.so` (pure Linux binary) built with `gcc`
- Communication via `__wine_unix_call` interface

## Architecture Overview

```
┌─────────────────────────────────────────────────────────────────┐
│ Windows Application │
│ (FL Studio, Reaper, etc.) │
└─────────────────────────────────────────────────────────────────┘
│ ASIO API calls
┌─────────────────────────────────────────────────────────────────┐
│ wineasio64.dll (PE) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ • COM/ASIO Interface implementation │ │
│ │ • Registry configuration reading │ │
│ │ • Host callback management │ │
│ │ • Callback polling thread │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ __wine_unix_call()
┌─────────────────────────────────────────────────────────────────┐
│ wineasio64.so (Unix) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ • JACK client connection │ │
│ │ • Audio buffer management │ │
│ │ • JACK callbacks (process, buffer size, sample rate) │ │
│ │ • Real-time audio processing │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ libjack API
┌─────────────────────────────────────────────────────────────────┐
│ JACK Server │
└─────────────────────────────────────────────────────────────────┘
```

## File Structure

```
wineasio-1.3.0/
├── asio_pe.c # PE-side implementation (Windows code)
├── asio_unix.c # Unix-side implementation (JACK code)
├── unixlib.h # Shared interface between PE and Unix
├── wineasio.def # DLL export definitions (for 32-bit)
├── ntdll_wine.def # ntdll import definitions (64-bit)
├── ntdll_wine32.def # ntdll import definitions (32-bit)
├── Makefile.wine11 # New build system for Wine 11
├── asio.c # Legacy combined code (Wine ≤ 10.1)
└── gui/
├── settings.py # PyQt5/6 Settings GUI
├── settings.ui # Qt Designer UI file
├── ui_settings.py # Generated UI code
├── wineasio-settings # Linux launcher script
├── wineasio-settings-launcher.c # Windows launcher source
├── wineasio-settings.exe # 32-bit Windows launcher
└── wineasio-settings64.exe # 64-bit Windows launcher
```

## Key Components

### 1. unixlib.h - Shared Interface

This header defines:
- Parameter structures for each Unix function call
- Function ID enumeration (`enum unix_funcs`)
- Shared type definitions
- ASIO error codes and constants

```c
enum unix_funcs {
unix_asio_init,
unix_asio_exit,
unix_asio_start,
unix_asio_stop,
unix_asio_get_channels,
// ... etc
unix_funcs_count
};

struct asio_init_params {
struct asio_config config;
HRESULT result;
asio_handle handle;
// ... etc
};
```

### 2. asio_pe.c - PE Side (Windows)

Responsibilities:
- Implements the IASIO COM interface
- Reads configuration from Windows registry
- Manages the ASIO host callbacks
- Runs a polling thread to check for buffer switch notifications
- Calls Unix functions via `__wine_unix_call()`

Key functions:
- `DllMain()` - Initializes Wine Unix call interface
- `Init()` - Calls Unix side to connect to JACK
- `Start()` / `Stop()` - Controls audio streaming
- `CreateBuffers()` - Sets up audio buffers
- `callback_thread_proc()` - Polls Unix side for callbacks

### 3. asio_unix.c - Unix Side (Linux)

Responsibilities:
- Loads libjack dynamically
- Creates JACK client and ports
- Handles JACK callbacks (process, buffer size, sample rate)
- Manages audio buffers
- Signals PE side when buffer switch is needed

Key functions:
- `asio_init()` - Connects to JACK server
- `asio_start()` / `asio_stop()` - Activates/deactivates JACK client
- `jack_process_callback()` - Real-time audio processing
- `asio_get_callback()` - Returns pending callback information to PE side

## Wine Unix Call Interface

### Initialization (PE Side)

```c
// Import from ntdll
extern unixlib_handle_t __wine_unixlib_handle;
extern NTSTATUS (WINAPI *__wine_unix_call_dispatcher)(...);

// Get Unix library handle in DllMain
static BOOL init_wine_unix_call(HINSTANCE hInstDLL)
{
// Get NtQueryVirtualMemory dynamically (avoids stdcall issues on 32-bit)
pNtQueryVirtualMemory = GetProcAddress(GetModuleHandleA("ntdll.dll"),
"NtQueryVirtualMemory");
// Query for Unix library handle (MemoryWineUnixFuncs = 1000)
pNtQueryVirtualMemory(GetCurrentProcess(), hInstDLL,
1000, &wineasio_unix_handle, ...);
}

// Call Unix function
#define UNIX_CALL(func, params) \
wine_unix_call(wineasio_unix_handle, unix_##func, params)
```

### Unix Function Table (Unix Side)

```c
// Each function takes a void* args parameter
NTSTATUS asio_init(void *args)
{
struct asio_init_params *params = args;
// ... implementation
return STATUS_SUCCESS;
}

// Export the function table
const unixlib_entry_t __wine_unix_call_funcs[] =
{
asio_init,
asio_exit,
asio_start,
// ... etc
};
```

## Callback Handling

ASIO requires the host to be called back from the audio thread. Since we can't call Windows code directly from Unix threads, we use a polling mechanism:

1. **Unix side** (in JACK process callback):
- Copies audio data to shared buffers
- Sets `callback_pending` flag
- Stores timing information

2. **PE side** (in polling thread):
- Regularly calls `UNIX_CALL(asio_get_callback, &params)`
- If callback is pending, calls host's `bufferSwitch()` or `bufferSwitchTimeInfo()`
- Acknowledges callback with `UNIX_CALL(asio_callback_done, &params)`

```c
// PE side polling thread
DWORD callback_thread_proc(LPVOID param)
{
while (!This->stop_callback_thread) {
UNIX_CALL(asio_get_callback, &cb_params);
if (cb_params.buffer_switch_ready) {
if (This->time_info_mode)
This->callbacks->bufferSwitchTimeInfo(...);
else
This->callbacks->bufferSwitch(...);
UNIX_CALL(asio_callback_done, &done_params);
}
Sleep(1); // Polling interval
}
}
```

## Build System

### Makefile.wine11

Key targets:
- `64` - Builds 64-bit PE DLL and Unix SO
- `32` - Builds 32-bit PE DLL and Unix SO
- `install` - Installs to Wine directories
- `register` - Registers with Wine

### 32-bit Specific Issues

1. **stdcall decoration**: mingw-w64 uses `@N` suffix for stdcall functions, but Wine expects undecorated names
- Solution: Use a `.def` file to export undecorated names

2. **NtQueryVirtualMemory**: Same decoration issue
- Solution: Load dynamically via `GetProcAddress()`

```c
// wineasio.def - exports without decoration
EXPORTS
DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer
```

### Naming Convention

| Architecture | PE DLL | Unix SO |
|--------------|--------|---------|
| 64-bit | `wineasio64.dll` | `wineasio64.so` |
| 32-bit | `wineasio.dll` | `wineasio.so` |

Note: 32-bit uses `wineasio` (not `wineasio32`) to match Wine's internal expectations.

## Installation Paths

Wine 11 uses separate directories for PE and Unix libraries:

```
/opt/wine-stable/lib/wine/
├── x86_64-windows/ # 64-bit PE DLLs
│ └── wineasio64.dll
├── x86_64-unix/ # 64-bit Unix SOs
│ └── wineasio64.so
├── i386-windows/ # 32-bit PE DLLs
│ └── wineasio.dll
└── i386-unix/ # 32-bit Unix SOs
└── wineasio.so
```

## Debugging

### Enable Wine Debug Output

```bash
WINEDEBUG=+asio,+module wine your_app.exe
```

### Check Library Loading

```bash
WINEDEBUG=+loaddll wine regsvr32 wineasio64.dll 2>&1 | grep wineasio
```

### Verify Exports

```bash
# 64-bit
x86_64-w64-mingw32-objdump -p wineasio64.dll | grep -i dllregister

# 32-bit (should NOT have @0 suffix)
i686-w64-mingw32-objdump -p wineasio.dll | grep -i dllregister
```

### Check Unix Library Symbols

```bash
nm -D wineasio64.so | grep wine
# Should show: __wine_unix_call_funcs
```

## 32-bit Registration (WoW64)

### Important: Use the Correct regsvr32

On a 64-bit Wine prefix, there are two `regsvr32.exe` binaries:

| Binary | Location | Purpose |
|--------|----------|---------|
| 64-bit | `C:\windows\system32\regsvr32.exe` | Registers 64-bit DLLs |
| 32-bit | `C:\windows\syswow64\regsvr32.exe` | Registers 32-bit DLLs |

**The default `wine regsvr32` uses the 64-bit version!**

To register the 32-bit WineASIO DLL, you must explicitly use the 32-bit regsvr32:

```bash
# 64-bit registration (works with default regsvr32)
wine regsvr32 wineasio64.dll

# 32-bit registration (MUST use syswow64 regsvr32)
wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe wineasio.dll
```

### WoW64 Registry Entries

After successful 32-bit registration, you should see these registry entries:

```
HKCR\WOW6432Node\CLSID\{48D0C522-BFCC-45CC-8B84-17F25F33E6E8}
HKLM\Software\WOW6432Node\ASIO\WineASIO
```

Verify with:
```bash
wine reg query "HKCR\WOW6432Node\CLSID\{48D0C522-BFCC-45CC-8B84-17F25F33E6E8}"
wine reg query "HKLM\Software\WOW6432Node\ASIO\WineASIO"
```

## JACK MIDI Support

WineASIO includes optional JACK MIDI ports for direct MIDI routing through the JACK audio graph.

### JACK MIDI Ports

When WineASIO initializes, it registers two JACK MIDI ports:

| Port | Type | Description |
|------|------|-------------|
| `WineASIO:midi_in` | Input | Receives MIDI from JACK graph |
| `WineASIO:midi_out` | Output | Sends MIDI to JACK graph |

### How It Works

The MIDI implementation uses a ringbuffer for thread-safe communication:

```c
/* JACK process callback handles MIDI */
static int jack_process_callback(jack_nframes_t nframes, void *arg)
{
/* Read MIDI input events */
if (stream->midi_enabled && stream->midi_input.port) {
void *midi_buf = pjack_port_get_buffer(stream->midi_input.port, nframes);
jack_nframes_t event_count = pjack_midi_get_event_count(midi_buf);
for (jack_nframes_t j = 0; j < event_count; j++) {
jack_midi_event_t event;
pjack_midi_event_get(&event, midi_buf, j);
midi_ringbuffer_write(&stream->midi_input.ringbuffer,
event.buffer, event.size, event.time);
}
}
/* Write MIDI output events */
if (stream->midi_enabled && stream->midi_output.port) {
void *midi_buf = pjack_port_get_buffer(stream->midi_output.port, nframes);
pjack_midi_clear_buffer(midi_buf);
/* ... write pending events from ringbuffer ... */
}
}
```

### Verify MIDI Ports

After starting a WineASIO application (like FL Studio):

```bash
# List JACK MIDI ports
jack_lsp -t | grep -E 'WineASIO.*midi'

# Expected output:
# WineASIO:midi_in
# 8 bit raw midi
# WineASIO:midi_out
# 8 bit raw midi
```

### Connecting MIDI Devices

Use `jack_connect` or QjackCtl to route MIDI:

```bash
# Connect MIDI controller to WineASIO input
jack_connect "a2j:Your Controller [X] (capture): [0] MIDI 1" "WineASIO:midi_in"

# Connect WineASIO output to synthesizer
jack_connect "WineASIO:midi_out" "a2j:Your Synth [X] (playback): [0] MIDI 1"
```

### Relationship with Wine ALSA MIDI

WineASIO's JACK MIDI ports are **additional** to Wine's built-in ALSA MIDI support:

| Feature | Source | Use Case |
|---------|--------|----------|
| Wine ALSA MIDI | `winealsa.drv` | Direct hardware access (e.g., "M4 - M4 MIDI 1") |
| WineASIO JACK MIDI | `wineasio.so` | JACK graph routing, software connections |

**Note:** Windows applications (like FL Studio) use Wine's ALSA MIDI driver for the Windows MIDI API. The JACK MIDI ports are useful for:
- Direct routing in the JACK graph without a2jmidid
- Connecting to JACK-native applications (Ardour, Carla, etc.)
- Advanced MIDI routing scenarios

### Troubleshooting MIDI

**MIDI ports don't appear:**
- Ensure WineASIO is actively being used by an application
- Check if JACK is running: `jack_lsp`
- Verify JACK MIDI functions are loaded (check Wine debug output)

**"device already open" error in Wine:**
- This usually means you're trying to open an a2jmidid bridge port
- Use hardware ports directly (e.g., "M4 - M4 MIDI 1") instead of "a2jmidid - port"

## Control Panel / Settings GUI

WineASIO includes a settings GUI that can be launched from DAWs like FL Studio.

### How It Works

1. **ASIO Control Panel Button**: When you click "Show ASIO Panel" in FL Studio (or similar in other DAWs), the ASIO driver's `ControlPanel()` function is called.

2. **Unix-side Implementation**: The `asio_control_panel()` function in `asio_unix.c` uses `fork()/exec()` to launch the native Linux `wineasio-settings` tool:

```c
static NTSTATUS asio_control_panel(void *args)
{
pid_t pid = fork();
if (pid == 0) {
execvp("wineasio-settings", arg_list);
execl("/usr/bin/wineasio-settings", "wineasio-settings", NULL);
_exit(1);
}
return STATUS_SUCCESS;
}
```

3. **Native Linux GUI**: The `wineasio-settings` Python/PyQt application reads and writes WineASIO settings to the Wine registry.

### Installation

The GUI is installed automatically with `make -f Makefile.wine11 install`:

- **Linux launcher**: `/usr/bin/wineasio-settings`
- **Python code**: `/usr/share/wineasio/settings.py`
- **Windows launchers**: `/usr/share/wineasio/wineasio-settings*.exe`

### Manual Launch

```bash
# From Linux terminal
wineasio-settings

# From Wine (using Windows launcher)
wine /usr/share/wineasio/wineasio-settings64.exe
```

### Settings Stored

The GUI modifies these registry values in `HKCU\Software\Wine\WineASIO`:

| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| Number of inputs | DWORD | 16 | JACK input ports |
| Number of outputs | DWORD | 16 | JACK output ports |
| Connect to hardware | DWORD | 1 | Auto-connect to physical ports |
| Autostart server | DWORD | 0 | Start JACK if not running |
| Fixed buffersize | DWORD | 1 | Prevent apps from changing buffer |
| Preferred buffersize | DWORD | 1024 | Default buffer size |

## Common Issues

### "Unix library not found"

- Ensure `.so` file is in the correct `*-unix/` directory
- Ensure `.so` exports `__wine_unix_call_funcs`
- Check for unresolved symbols: `nm -D wineasio64.so | grep " U "`

### "DllRegisterServer not found" (32-bit)

- Ensure `wineasio.def` is included in the build
- Verify exports don't have stdcall decoration

### "NtQueryVirtualMemory not found" (32-bit)

- Load via `GetProcAddress()` instead of static import
- Don't use `@24` decoration in def file

### "cannot find builtin library" (32-bit registration)

- You're using the wrong regsvr32! Use the 32-bit version:
```bash
wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe wineasio.dll
```

### Control Panel doesn't open

- Ensure `wineasio-settings` is in PATH (`/usr/bin/`)
- Check if PyQt5 or PyQt6 is installed: `python3 -c "from PyQt5.QtWidgets import QApplication"`
- Try launching manually: `wineasio-settings`

## References

- Wine GitLab: https://gitlab.winehq.org/wine/wine
- Wine Unix Call Interface: `include/wine/unixlib.h`
- Example builtin DLLs: `dlls/winealsa.drv/`, `dlls/winepulse.drv/`

## Quick Reference

### Build Commands

```bash
make -f Makefile.wine11 64 # Build 64-bit only
make -f Makefile.wine11 32 # Build 32-bit only
make -f Makefile.wine11 all # Build both
make -f Makefile.wine11 install # Install everything (requires sudo)
make -f Makefile.wine11 register # Register with Wine
```

### Verify Installation

```bash
# Check files
ls -la /opt/wine-stable/lib/wine/x86_64-windows/wineasio64.dll
ls -la /opt/wine-stable/lib/wine/x86_64-unix/wineasio64.so
ls -la /opt/wine-stable/lib/wine/i386-windows/wineasio.dll
ls -la /opt/wine-stable/lib/wine/i386-unix/wineasio.so

# Check registration
wine reg query "HKLM\Software\ASIO\WineASIO"
wine reg query "HKLM\Software\WOW6432Node\ASIO\WineASIO"

# Check GUI
which wineasio-settings
```

## Authors

Wine 11 port implemented January 2025, one day after Wine 11's official release (January 13, 2025).

Control Panel GUI integration added January 2025.

JACK MIDI support added January 2025.

+ 1027
- 0
asio_pe.c
File diff suppressed because it is too large
View File


+ 1248
- 0
asio_unix.c
File diff suppressed because it is too large
View File


+ 40
- 3
gui/Makefile View File

@@ -9,9 +9,31 @@ PREFIX = /usr
PYUIC ?= pyuic5
PYRCC ?= pyrcc5

# MinGW compilers for Windows launcher
MINGW32 = i686-w64-mingw32-gcc
MINGW64 = x86_64-w64-mingw32-gcc

# Windows launcher executables
LAUNCHER_SRC = wineasio-settings-launcher.c
LAUNCHER32 = wineasio-settings.exe
LAUNCHER64 = wineasio-settings64.exe

# ---------------------------------------------------------------------------------------------------------------------

all:
all: launchers

launchers: $(LAUNCHER32) $(LAUNCHER64)
@echo "Windows launcher executables built"
@echo " 32-bit: $(LAUNCHER32)"
@echo " 64-bit: $(LAUNCHER64)"

$(LAUNCHER32): $(LAUNCHER_SRC)
@echo "Building 32-bit Windows launcher..."
$(MINGW32) -o $@ $< -mwindows -O2

$(LAUNCHER64): $(LAUNCHER_SRC)
@echo "Building 64-bit Windows launcher..."
$(MINGW64) -o $@ $< -mwindows -O2

# ---------------------------------------------------------------------------------------------------------------------
# UI code
@@ -56,14 +78,14 @@ ui_%.py: %.ui
# ---------------------------------------------------------------------------------------------------------------------

clean:
rm -f *~ *.pyc
rm -f *~ *.pyc $(LAUNCHER32) $(LAUNCHER64)

destroy: clean
rm -f ui_*.py

# ---------------------------------------------------------------------------------------------------------------------

install:
install: launchers
# Create directories
install -d $(DESTDIR)$(PREFIX)/bin/
install -d $(DESTDIR)$(PREFIX)/share/wineasio/
@@ -80,6 +102,21 @@ install:
# Install code
install -m 644 *.py $(DESTDIR)$(PREFIX)/share/wineasio/

# Install Windows launcher executables (for use from Wine apps like FL Studio)
install -m 755 $(LAUNCHER32) $(DESTDIR)$(PREFIX)/share/wineasio/
install -m 755 $(LAUNCHER64) $(DESTDIR)$(PREFIX)/share/wineasio/

@echo ""
@echo "Installation complete!"
@echo ""
@echo "Native Linux GUI: $(PREFIX)/bin/wineasio-settings"
@echo "Windows launchers (for FL Studio etc.):"
@echo " $(PREFIX)/share/wineasio/$(LAUNCHER32)"
@echo " $(PREFIX)/share/wineasio/$(LAUNCHER64)"
@echo ""
@echo "To use from FL Studio, copy the appropriate .exe to your Wine prefix:"
@echo " cp $(PREFIX)/share/wineasio/$(LAUNCHER64) ~/.wine/drive_c/Program\ Files/WineASIO/"

# ---------------------------------------------------------------------------------------------------------------------

uninstall:


+ 90
- 0
gui/wineasio-settings-launcher.c View File

@@ -0,0 +1,90 @@
/*
* WineASIO Settings Launcher
*
* A minimal Windows executable that launches the native Linux
* wineasio-settings GUI from within Wine applications (like FL Studio).
*
* Compile with mingw:
* i686-w64-mingw32-gcc -o wineasio-settings.exe wineasio-settings-launcher.c -mwindows
* x86_64-w64-mingw32-gcc -o wineasio-settings64.exe wineasio-settings-launcher.c -mwindows
*
* Copyright (C) 2025
* License: GPL v2+
*/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>

/* Try to launch the native Linux wineasio-settings via various methods */
static BOOL launch_native_settings(void)
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
char cmd[512];
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
/* Method 1: Use start.exe /unix to launch native tool */
/* This is the recommended Wine method for launching Unix executables */
lstrcpyA(cmd, "start.exe /unix /usr/bin/wineasio-settings");
if (CreateProcessA(NULL, cmd, NULL, NULL, FALSE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
/* Method 2: Try /usr/local/bin path */
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
lstrcpyA(cmd, "start.exe /unix /usr/local/bin/wineasio-settings");
if (CreateProcessA(NULL, cmd, NULL, NULL, FALSE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
/* Method 3: Try with winepath (in case start.exe doesn't work) */
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
lstrcpyA(cmd, "cmd.exe /c start /unix wineasio-settings");
if (CreateProcessA(NULL, cmd, NULL, NULL, FALSE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
return FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
(void)hInstance;
(void)hPrevInstance;
(void)lpCmdLine;
(void)nCmdShow;
if (!launch_native_settings()) {
MessageBoxA(NULL,
"Could not launch WineASIO Settings.\n\n"
"Please make sure wineasio-settings is installed:\n"
" /usr/bin/wineasio-settings\n"
" or /usr/local/bin/wineasio-settings\n\n"
"You can also run it manually from the Linux command line.",
"WineASIO Settings",
MB_OK | MB_ICONWARNING);
return 1;
}
return 0;
}

+ 6
- 0
ntdll_wine.def View File

@@ -0,0 +1,6 @@
; Wine-specific symbols from ntdll.dll for WineASIO (64-bit)
; NtQueryVirtualMemory is loaded dynamically via GetProcAddress
LIBRARY ntdll.dll
EXPORTS
__wine_unix_call_dispatcher DATA
__wine_unixlib_handle DATA

+ 7
- 0
ntdll_wine32.def View File

@@ -0,0 +1,7 @@
; Wine-specific symbols from ntdll.dll for WineASIO (32-bit)
; NtQueryVirtualMemory is loaded dynamically via GetProcAddress to avoid
; stdcall decoration mismatch between mingw (@24) and Wine (undecorated)
LIBRARY ntdll.dll
EXPORTS
__wine_unix_call_dispatcher DATA
__wine_unixlib_handle DATA

+ 334
- 0
package.sh View File

@@ -0,0 +1,334 @@
#!/bin/bash
#
# WineASIO 1.4.0 Release Packaging Script
# Creates release tarballs for distribution
#

set -e

VERSION="1.4.0"
PACKAGE_NAME="wineasio-${VERSION}"
BUILD_DIR="build_wine11"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} WineASIO ${VERSION} Release Packager${NC}"
echo -e "${GREEN}========================================${NC}"
echo

# Check if we're in the right directory
if [ ! -f "Makefile.wine11" ]; then
echo -e "${RED}Error: Run this script from the WineASIO source directory${NC}"
exit 1
fi

# Create dist directory
DIST_DIR="dist"
rm -rf "${DIST_DIR}"
mkdir -p "${DIST_DIR}"

echo -e "${YELLOW}[1/5]${NC} Creating source tarball..."

# Files to include in source release
SOURCE_FILES=(
# Core source files (Wine 11)
"asio_pe.c"
"asio_unix.c"
"unixlib.h"

# Legacy source files
"asio.c"
"main.c"
"regsvr.c"
"jackbridge.c"
"jackbridge.h"

# Build system
"Makefile.wine11"
"Makefile"
"Makefile.mk"

# Definition files
"wineasio.def"
"ntdll_wine.def"
"ntdll_wine32.def"
"wineasio.dll.spec"
"wineasio32.dll.spec"
"wineasio64.dll.spec"

# Documentation
"README.md"
"RELEASE_NOTES.md"
"WINE11_PORTING.md"
"COPYING.LIB"
"COPYING.GUI"

# Scripts
"wineasio-register"
"wineasio-register.sh"
"package.sh"

# Assets
"screenshot.png"
)

# Create source package directory
SOURCE_PKG="${DIST_DIR}/${PACKAGE_NAME}-source"
mkdir -p "${SOURCE_PKG}"
mkdir -p "${SOURCE_PKG}/gui"
mkdir -p "${SOURCE_PKG}/docker"

# Copy source files
for file in "${SOURCE_FILES[@]}"; do
if [ -f "$file" ]; then
cp "$file" "${SOURCE_PKG}/"
fi
done

# Copy GUI directory
if [ -d "gui" ]; then
cp gui/settings.py "${SOURCE_PKG}/gui/" 2>/dev/null || true
cp gui/settings.ui "${SOURCE_PKG}/gui/" 2>/dev/null || true
cp gui/ui_settings.py "${SOURCE_PKG}/gui/" 2>/dev/null || true
cp gui/wineasio-settings "${SOURCE_PKG}/gui/" 2>/dev/null || true
cp gui/wineasio-settings-launcher.c "${SOURCE_PKG}/gui/" 2>/dev/null || true
cp gui/wineasio-settings.bat "${SOURCE_PKG}/gui/" 2>/dev/null || true
cp gui/Makefile "${SOURCE_PKG}/gui/" 2>/dev/null || true
fi

# Copy docker directory if exists
if [ -d "docker" ]; then
cp -r docker/* "${SOURCE_PKG}/docker/" 2>/dev/null || true
fi

# Create source tarball
cd "${DIST_DIR}"
tar -czvf "${PACKAGE_NAME}-source.tar.gz" "${PACKAGE_NAME}-source"
cd ..

echo -e "${GREEN} ✓ Created ${DIST_DIR}/${PACKAGE_NAME}-source.tar.gz${NC}"

echo -e "${YELLOW}[2/5]${NC} Creating binary tarball..."

# Check if binaries exist
if [ ! -d "${BUILD_DIR}" ]; then
echo -e "${RED} Warning: Build directory not found. Run 'make -f Makefile.wine11 all' first.${NC}"
echo -e "${YELLOW} Skipping binary package...${NC}"
else
BINARY_PKG="${DIST_DIR}/${PACKAGE_NAME}-binaries"
mkdir -p "${BINARY_PKG}/64bit"
mkdir -p "${BINARY_PKG}/32bit"
mkdir -p "${BINARY_PKG}/gui"

# Copy 64-bit binaries
if [ -f "${BUILD_DIR}/wineasio64.dll" ]; then
cp "${BUILD_DIR}/wineasio64.dll" "${BINARY_PKG}/64bit/"
fi
if [ -f "${BUILD_DIR}/wineasio64.so" ]; then
cp "${BUILD_DIR}/wineasio64.so" "${BINARY_PKG}/64bit/"
fi

# Copy 32-bit binaries
if [ -f "${BUILD_DIR}/wineasio.dll" ]; then
cp "${BUILD_DIR}/wineasio.dll" "${BINARY_PKG}/32bit/"
fi
if [ -f "${BUILD_DIR}/wineasio.so" ]; then
cp "${BUILD_DIR}/wineasio.so" "${BINARY_PKG}/32bit/"
fi

# Copy GUI launchers
if [ -f "gui/wineasio-settings.exe" ]; then
cp gui/wineasio-settings.exe "${BINARY_PKG}/gui/"
fi
if [ -f "gui/wineasio-settings64.exe" ]; then
cp gui/wineasio-settings64.exe "${BINARY_PKG}/gui/"
fi
if [ -f "gui/wineasio-settings" ]; then
cp gui/wineasio-settings "${BINARY_PKG}/gui/"
fi
if [ -f "gui/settings.py" ]; then
cp gui/settings.py "${BINARY_PKG}/gui/"
fi
if [ -f "gui/ui_settings.py" ]; then
cp gui/ui_settings.py "${BINARY_PKG}/gui/"
fi

# Copy documentation
cp README.md "${BINARY_PKG}/"
cp RELEASE_NOTES.md "${BINARY_PKG}/" 2>/dev/null || true
cp COPYING.LIB "${BINARY_PKG}/"
cp COPYING.GUI "${BINARY_PKG}/"

# Create install script for binary package
cat > "${BINARY_PKG}/install.sh" << 'INSTALL_EOF'
#!/bin/bash
#
# WineASIO Binary Installation Script
#

set -e

# Detect Wine prefix
if [ -z "$WINE_PREFIX" ]; then
# Try common locations
if [ -d "/opt/wine-stable/lib/wine" ]; then
WINE_PREFIX="/opt/wine-stable"
elif [ -d "/opt/wine-staging/lib/wine" ]; then
WINE_PREFIX="/opt/wine-staging"
elif [ -d "/usr/lib/wine" ]; then
WINE_PREFIX="/usr"
else
echo "Could not detect Wine installation."
echo "Please set WINE_PREFIX environment variable."
exit 1
fi
fi

echo "Installing WineASIO to ${WINE_PREFIX}..."

# 64-bit installation
if [ -f "64bit/wineasio64.dll" ]; then
sudo cp 64bit/wineasio64.dll "${WINE_PREFIX}/lib/wine/x86_64-windows/"
sudo cp 64bit/wineasio64.so "${WINE_PREFIX}/lib/wine/x86_64-unix/"
echo " ✓ 64-bit libraries installed"
fi

# 32-bit installation
if [ -f "32bit/wineasio.dll" ]; then
sudo cp 32bit/wineasio.dll "${WINE_PREFIX}/lib/wine/i386-windows/"
sudo cp 32bit/wineasio.so "${WINE_PREFIX}/lib/wine/i386-unix/"
echo " ✓ 32-bit libraries installed"
fi

# GUI installation
if [ -f "gui/wineasio-settings" ]; then
sudo cp gui/wineasio-settings /usr/bin/
sudo chmod +x /usr/bin/wineasio-settings
sudo mkdir -p /usr/share/wineasio
sudo cp gui/settings.py /usr/share/wineasio/
sudo cp gui/ui_settings.py /usr/share/wineasio/ 2>/dev/null || true
if [ -f "gui/wineasio-settings.exe" ]; then
sudo cp gui/wineasio-settings*.exe /usr/share/wineasio/
fi
echo " ✓ GUI installed"
fi

echo ""
echo "Installation complete!"
echo ""
echo "Now register the driver:"
echo " wine regsvr32 wineasio64.dll"
echo " wine ~/.wine/drive_c/windows/syswow64/regsvr32.exe wineasio.dll"
INSTALL_EOF
chmod +x "${BINARY_PKG}/install.sh"

# Create binary tarball
cd "${DIST_DIR}"
tar -czvf "${PACKAGE_NAME}-binaries.tar.gz" "${PACKAGE_NAME}-binaries"
cd ..

echo -e "${GREEN} ✓ Created ${DIST_DIR}/${PACKAGE_NAME}-binaries.tar.gz${NC}"
fi

echo -e "${YELLOW}[3/5]${NC} Creating checksums..."

cd "${DIST_DIR}"
sha256sum *.tar.gz > SHA256SUMS.txt
cd ..

echo -e "${GREEN} ✓ Created ${DIST_DIR}/SHA256SUMS.txt${NC}"

echo -e "${YELLOW}[4/5]${NC} Creating GitHub release template..."

cat > "${DIST_DIR}/GITHUB_RELEASE.md" << 'RELEASE_EOF'
# WineASIO 1.4.0 - Wine 11 Edition 🍷🎵

## What's New

This is a major release bringing **full Wine 11 compatibility** with a complete rewrite of the build system and internal architecture.

### ✨ Highlights

- **Wine 11 Support** - New PE/Unix split architecture for Wine 10.2+/11
- **Settings GUI** - Launch settings directly from your DAW's ASIO control panel
- **JACK MIDI** - New `WineASIO:midi_in` and `WineASIO:midi_out` ports

### 📦 Downloads

| File | Description |
|------|-------------|
| `wineasio-1.4.0-source.tar.gz` | Complete source code |
| `wineasio-1.4.0-binaries.tar.gz` | Pre-built binaries (DLLs + SOs) |

### 🔧 Quick Install

```bash
# From source
tar -xzf wineasio-1.4.0-source.tar.gz
cd wineasio-1.4.0-source
make -f Makefile.wine11 all
sudo make -f Makefile.wine11 install
make -f Makefile.wine11 register

# From binaries
tar -xzf wineasio-1.4.0-binaries.tar.gz
cd wineasio-1.4.0-binaries
./install.sh
```

### 💻 Requirements

- Wine 10.2+ or Wine 11
- JACK Audio Connection Kit
- PyQt5 or PyQt6 (for settings GUI)

### 📊 Tested DAWs

| DAW | Status |
|-----|--------|
| FL Studio | ✅ Working |
| Reaper | ✅ Working |
| Ableton Live | ✅ Working |
| Bitwig Studio | ✅ Working |

### 📄 Checksums

See `SHA256SUMS.txt` for file checksums.

---

**Full changelog:** See RELEASE_NOTES.md
RELEASE_EOF

echo -e "${GREEN} ✓ Created ${DIST_DIR}/GITHUB_RELEASE.md${NC}"

echo -e "${YELLOW}[5/5]${NC} Cleanup..."

# Remove temporary directories (keep tarballs)
rm -rf "${DIST_DIR}/${PACKAGE_NAME}-source"
rm -rf "${DIST_DIR}/${PACKAGE_NAME}-binaries"

echo -e "${GREEN} ✓ Cleanup complete${NC}"

echo
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Package creation complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo
echo "Files created in ${DIST_DIR}/:"
ls -la "${DIST_DIR}/"
echo
echo -e "${YELLOW}Next steps:${NC}"
echo "1. Create a new GitHub repository: https://github.com/new"
echo "2. Push the source code"
echo "3. Create a new release and upload:"
echo " - ${DIST_DIR}/${PACKAGE_NAME}-source.tar.gz"
echo " - ${DIST_DIR}/${PACKAGE_NAME}-binaries.tar.gz"
echo " - ${DIST_DIR}/SHA256SUMS.txt"
echo "4. Use ${DIST_DIR}/GITHUB_RELEASE.md as release description"
echo

+ 319
- 0
unixlib.h View File

@@ -0,0 +1,319 @@
/*
* WineASIO Unix Library Interface
* Copyright (C) 2024 WineASIO contributors
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/

#ifndef __WINEASIO_UNIXLIB_H
#define __WINEASIO_UNIXLIB_H

#include <stdint.h>

/* Platform-specific includes */
#ifdef WINE_UNIX_LIB
/* Unix side - building the .so */
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "wine/unixlib.h"
#else
/* PE side - building with mingw or winegcc */
#ifdef _WIN32
#include <windef.h>
#include <winbase.h>
#else
#include "windef.h"
#include "winbase.h"
#endif

/* Define unixlib types for PE side if not available */
#ifndef __WINE_WINE_UNIXLIB_H
typedef uint64_t unixlib_handle_t;

/* These are imported from ntdll */
extern unixlib_handle_t __wine_unixlib_handle;
extern NTSTATUS (WINAPI *__wine_unix_call_dispatcher)(unixlib_handle_t, unsigned int, void *);
extern NTSTATUS WINAPI __wine_init_unix_call(void);

static inline NTSTATUS __wine_unix_call(unixlib_handle_t handle, unsigned int code, void *args)
{
return __wine_unix_call_dispatcher(handle, code, args);
}
#endif /* __WINE_WINE_UNIXLIB_H */

#endif /* WINE_UNIX_LIB */

/* Maximum number of channels */
#define WINEASIO_MAX_CHANNELS 128

/* Sample types matching ASIO SDK */
typedef enum {
ASIOSTInt16MSB = 0,
ASIOSTInt24MSB = 1,
ASIOSTInt32MSB = 2,
ASIOSTFloat32MSB = 3,
ASIOSTFloat64MSB = 4,
ASIOSTInt32MSB16 = 8,
ASIOSTInt32MSB18 = 9,
ASIOSTInt32MSB20 = 10,
ASIOSTInt32MSB24 = 11,
ASIOSTInt16LSB = 16,
ASIOSTInt24LSB = 17,
ASIOSTInt32LSB = 18,
ASIOSTFloat32LSB = 19,
ASIOSTFloat64LSB = 20,
ASIOSTInt32LSB16 = 24,
ASIOSTInt32LSB18 = 25,
ASIOSTInt32LSB20 = 26,
ASIOSTInt32LSB24 = 27,
} ASIOSampleType;

/* Stream handle - opaque pointer to Unix-side stream */
typedef UINT64 asio_handle;

/* Buffer info for channel setup */
struct asio_buffer_info {
BOOL is_input;
LONG channel_num;
UINT64 buffer_ptr[2]; /* Double-buffering pointers */
};

/* Channel info */
struct asio_channel_info {
LONG channel;
BOOL is_input;
BOOL is_active;
LONG channel_group;
ASIOSampleType sample_type;
char name[32];
};

/* Time info from JACK */
struct asio_time_info {
double speed;
INT64 system_time;
INT64 sample_position;
double sample_rate;
UINT32 flags;
};

/* Configuration read from registry (passed to Unix side) */
struct asio_config {
LONG num_inputs;
LONG num_outputs;
LONG preferred_bufsize;
BOOL fixed_bufsize;
BOOL autoconnect;
char client_name[64];
};

/*
* Parameter structures for each Unix function call
*/

struct asio_init_params {
struct asio_config config;
HRESULT result;
asio_handle handle;
LONG input_channels;
LONG output_channels;
double sample_rate;
};

struct asio_exit_params {
asio_handle handle;
HRESULT result;
};

struct asio_start_params {
asio_handle handle;
HRESULT result;
};

struct asio_stop_params {
asio_handle handle;
HRESULT result;
};

struct asio_get_channels_params {
asio_handle handle;
HRESULT result;
LONG num_inputs;
LONG num_outputs;
};

struct asio_get_latencies_params {
asio_handle handle;
HRESULT result;
LONG input_latency;
LONG output_latency;
};

struct asio_get_buffer_size_params {
asio_handle handle;
HRESULT result;
LONG min_size;
LONG max_size;
LONG preferred_size;
LONG granularity;
};

struct asio_can_sample_rate_params {
asio_handle handle;
double sample_rate;
HRESULT result;
};

struct asio_get_sample_rate_params {
asio_handle handle;
HRESULT result;
double sample_rate;
};

struct asio_set_sample_rate_params {
asio_handle handle;
double sample_rate;
HRESULT result;
};

struct asio_get_channel_info_params {
asio_handle handle;
struct asio_channel_info info;
HRESULT result;
};

struct asio_create_buffers_params {
asio_handle handle;
LONG num_channels;
LONG buffer_size;
struct asio_buffer_info *buffer_infos; /* Array of buffer_info */
HRESULT result;
};

struct asio_dispose_buffers_params {
asio_handle handle;
HRESULT result;
};

struct asio_output_ready_params {
asio_handle handle;
HRESULT result;
};

struct asio_get_sample_position_params {
asio_handle handle;
HRESULT result;
INT64 sample_position;
INT64 system_time;
};

/* Callback notification - PE side polls for this */
struct asio_get_callback_params {
asio_handle handle;
HRESULT result;
BOOL buffer_switch_ready;
LONG buffer_index;
BOOL direct_process;
struct asio_time_info time_info;
BOOL sample_rate_changed;
double new_sample_rate;
BOOL reset_request;
BOOL resync_request;
BOOL latency_changed;
};

/* Acknowledge that callback was processed */
struct asio_callback_done_params {
asio_handle handle;
LONG buffer_index;
HRESULT result;
};

struct asio_control_panel_params {
asio_handle handle;
HRESULT result;
};

struct asio_future_params {
asio_handle handle;
LONG selector;
UINT64 opt; /* Pointer to optional parameter */
HRESULT result;
};

/*
* Unix function IDs
*/
enum unix_funcs {
unix_asio_init,
unix_asio_exit,
unix_asio_start,
unix_asio_stop,
unix_asio_get_channels,
unix_asio_get_latencies,
unix_asio_get_buffer_size,
unix_asio_can_sample_rate,
unix_asio_get_sample_rate,
unix_asio_set_sample_rate,
unix_asio_get_channel_info,
unix_asio_create_buffers,
unix_asio_dispose_buffers,
unix_asio_output_ready,
unix_asio_get_sample_position,
unix_asio_get_callback,
unix_asio_callback_done,
unix_asio_control_panel,
unix_asio_future,
unix_funcs_count
};

/* Error codes matching ASIO SDK */
#define ASE_OK 0
#define ASE_SUCCESS 0x3f4847a0
#define ASE_NotPresent (-1000)
#define ASE_HWMalfunction (-999)
#define ASE_InvalidParameter (-998)
#define ASE_InvalidMode (-997)
#define ASE_SPNotAdvancing (-996)
#define ASE_NoClock (-995)
#define ASE_NoMemory (-994)

/* Future selectors */
#define kAsioEnableTimeCodeRead 1
#define kAsioDisableTimeCodeRead 2
#define kAsioSetInputMonitor 3
#define kAsioTransport 4
#define kAsioSetInputGain 5
#define kAsioGetInputMeter 6
#define kAsioSetOutputGain 7
#define kAsioGetOutputMeter 8
#define kAsioCanInputMonitor 9
#define kAsioCanTimeInfo 10
#define kAsioCanTimeCode 11
#define kAsioCanTransport 12
#define kAsioCanInputGain 13
#define kAsioCanInputMeter 14
#define kAsioCanOutputGain 15
#define kAsioCanOutputMeter 16
#define kAsioOptionalOne 17
#define kAsioSetIoFormat 0x23111961
#define kAsioGetIoFormat 0x23111983
#define kAsioCanDoIoFormat 0x23112004
#define kAsioCanReportOverload 0x24042012
#define kAsioGetInternalBufferSamples 0x25042012
#define kAsioSupportsInputResampling 0x26092017

#endif /* __WINEASIO_UNIXLIB_H */

+ 9
- 0
wineasio.def View File

@@ -0,0 +1,9 @@
; WineASIO DLL Export Definitions
; This file ensures exports use undecorated names for Wine compatibility
LIBRARY wineasio
EXPORTS
DllCanUnloadNow
DllGetClassObject
DllMain
DllRegisterServer
DllUnregisterServer

Loading…
Cancel
Save