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 scriptpull/125/head
| @@ -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 }} | |||
| @@ -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 | |||
| @@ -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! | |||
| @@ -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" | |||
| @@ -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). | |||
|  | |||
| 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. | |||
| @@ -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! 🎵🍷** | |||
| @@ -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, ¶ms)` | |||
| - If callback is pending, calls host's `bufferSwitch()` or `bufferSwitchTimeInfo()` | |||
| - Acknowledges callback with `UNIX_CALL(asio_callback_done, ¶ms)` | |||
| ```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. | |||
| @@ -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: | |||
| @@ -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; | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 */ | |||
| @@ -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 | |||