从源代码构建

目录

  1. 环境要求
  2. 快速构建
  3. 如果克隆时没有使用 --recursive
  4. 项目结构
  5. 测试
  6. 发布包
  7. 无硬件测试(tools/emu)
  8. 依赖项

环境要求

  • Rust(stable,1.90 或更高版本),通过 rustup 安装
  • Visual Studio 2022 或更高版本(或其生成工具),并安装“使用 C++ 的桌面开发”工作负载:C 库(BTstack、各编解码器)使用 MSVC 编译
  • 用于 UI 的 Node.js 22 和 pnpm(corepack enable 即可提供 pnpm)
  • Git(用于子模块)
  • 用于 build.ps1 / build.bat 的 PowerShell 7(pwsh,winget install Microsoft.PowerShell)
  • ARM64 构建还需要:Visual Studio 组件“MSVC v143 - VS 2022 C++ ARM64 生成工具”,在 x64 电脑上还需要“适用于 Windows 的 C++ Clang 编译器”(rustls 的 ring 用 clang 汇编其 ARM64 代码;installer/build-release.ps1 会自行找到 Visual Studio 的 clang),以及 rustup target add aarch64-pc-windows-msvc

快速构建

git clone --recursive https://github.com/SeiyaFunaokaJP/A2DP-Windows-Bridge.git
cd A2DP-Windows-Bridge
pwsh ./build.ps1

也可以在资源管理器中双击 build.bat:它会运行 build.ps1,结束时等待按键(build.bat -Test 会把开关传给脚本)。build.ps1 会先检查 Rust、Node.js、pnpm 和子模块是否齐全,node_modules 不存在时运行 pnpm install,先构建窗口的页面,再把三个程序输出到 target/release/:a2dpwb-core.exe(常驻核心:Bluetooth、音频、托盘)、a2dpwb.exe(窗口)和 a2dpwb-driver.exe(以提升权限运行、负责分配 / 恢复 WinUSB 驱动程序的辅助程序)。请将这三个程序放在同一个文件夹中;a2dpwb-core.exe --cli 可在不打开窗口的情况下串流。

开关:-Debug(开发配置,target/debug/)、-Test(随后运行“测试”中的检查)、-Decoder(同时构建解码工具)、-Emu(同时运行无硬件测试)、-Release -Arch x64|arm64(仅运行发布脚本,见“发布包”)。

分步构建(即 build.ps1 所做的事;a2dpwb.exe 会嵌入窗口的页面,因此必须先构建页面):

cargo build --release -p a2dpwb-core-exe -p a2dpwb-driver
cd app/src/ui
pnpm install --frozen-lockfile
pnpm build
cd ../../..
cargo build --release -p a2dpwb-ui

如果克隆时没有使用 --recursive

git submodule update --init --recursive

项目结构

A2DP-Windows-Bridge/
├── app/
│   ├── src/
│   │   ├── core/           a2dpwb-core.exe: resident core, tray, IPC server, --cli
│   │   ├── ui/             a2dpwb.exe: Tauri 2 + SolidJS (pnpm dev runs it in a browser with a mock core)
│   │   ├── driver/         a2dpwb-driver.exe: WinUSB assign / restore (elevated)
│   │   └── crates/         Libraries: btstack-sys, hci-transport, bt-host, codec, the codec -sys crates,
│   │                       pipeline, audio-capture, win-sys, core (a2dpwb-core), ipc, le-audio, lc3-sys
│   ├── lang/               Localization (en.json is the source; tools/check_lang.py checks the others)
│   └── resources/          Icon and manifest
├── Cargo.toml              Cargo workspace
├── installer/              Release script, NSIS hooks, updater notes (installer/README.md)
├── compat/                 MSVC compatibility headers for the AOSP code
├── docs/                   Documentation (this site) and the design document (v2-design.md)
├── extern/                 Third-party C libraries (git submodules)
│   ├── btstack/            BTstack Bluetooth stack
│   ├── libldac/            AOSP LDAC encoder
│   ├── libopenaptx/        aptX / aptX HD / aptX LL encoder
│   ├── fdk-aac/            Fraunhofer AAC encoder
│   ├── lhdcv5-enc/         LHDC V5 encoder
│   └── opus/               libopus (Opus encoder)
└── tools/
    ├── a2dp_decode/        a2dpwb_decode: checks / decodes the media stream in an HCI capture (.pklg)
    ├── emu/                End-to-end test against a virtual Bluetooth sink (Python)
    └── linux_sink/         a2dpwb_sink: measuring A2DP receiver on Linux (Python, Bumble)

测试

cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cd app/src/ui && pnpm exec tsc --noEmit && pnpm exec vitest run
python tools/check_lang.py

发布包

pwsh installer/build-release.ps1 -Arch x64

会将安装程序(A2DPWB-<version>-win64-setup.exe)、便携版 zip 和更新程序清单写入 target/dist。应用内更新的签名及其他细节请参阅 installer/README.md。

无硬件测试(tools/emu)

tools/emu 在同一台 PC 上将 A2DPWB 的每种编解码器串流到虚拟 Bluetooth 接收端,无需适配器或耳机。它只能在 Windows 上运行,需要 Python 3.11 或更高版本,解码工具还需要 CMake(随 Visual Studio 附带)。

python tools/emu/setup_env.py                       # once: creates tools/emu/.venv with pinned packages
cmake -S tools/a2dp_decode -B build/a2dp_decode     # once: the decoder tool
cmake --build build/a2dp_decode --config Release
cargo build --release -p a2dpwb-core-exe
python tools/emu/run_test.py                        # about 35 s for all codecs

工作原理:

  • emu_sink.py 在进程内链路上运行两个 Bumble 虚拟控制器。其中一个以 H4 over TCP(127.0.0.1)的形式提供给 A2DPWB。另一个由 Bumble A2DP 接收端使用,它提供 SBC、AAC、aptX、aptX HD、aptX LL 和 LDAC,并记录自身的 HCI 通信。
  • run_test.py 针对每种编解码器,使用开发选项运行 a2dpwb-core.exe --cli:--hci-tcp(使用虚拟控制器代替 WinUSB)、--test-tone(以左 1 kHz / 右 1.5 kHz 的测试音代替系统音频)、--duration、--hci-capture。环境变量 A2DPWB_CONFIG_DIR 让 A2DPWB 使用单独的配置文件夹,因此与虚拟接收端的配对不会影响你真实的链接密钥。
  • 随后用 a2dpwb_decode 检查两份 HCI 捕获(接收端一侧使用 --received)。

满足以下所有条件时,该编解码器即通过测试:

  • 协商的是所请求的编解码器
  • a2dpwb_decode 在发送端和接收端都没有发现问题
  • 接收端收到了 A2DPWB 发送的每个媒体数据包和帧,并且至少发送了所请求音频时长的 90%
  • LDAC 除外(没有开源解码器):两端解码后的音频完全相同,且为测试音
选项 说明
--codecs sbc aac ... 只测试这些编解码器(sbc aac aptx aptxhd aptxll ldac,默认:全部)
--duration <s> 每种编解码器的串流秒数(默认 5)
--max-packet <bytes> 传递给 A2DPWB(最大媒体数据包大小,请参阅使用方法)
--a2dpwb <exe> 要测试的核心(默认 target/release/a2dpwb-core.exe)
--decoder <exe> 解码工具(默认 build/a2dp_decode/Release/a2dpwb_decode.exe)
--out <dir> 输出文件夹(默认 tools/emu/out)

对于每种编解码器,tools/emu/out/<codec>/ 中保存捕获文件(a2dpwb.pklg、sink.pklg)、日志、a2dpwb_decode 报告和解码后的 WAV 文件。所有编解码器都通过时,退出代码为 0。

虚拟链路没有无线电:它检查的是编码、分包、AVDTP / L2CAP 信令以及与独立 Bluetooth 堆栈(Bumble)的互操作性,但不检查无线环境、真实硬件上的时序,也不检查真实耳机如何播放音频。Bumble 软件包仅为测试工具,不属于 A2DPWB(请参阅 THIRD_PARTY_LICENSES.md)。

emu_vhci.py 面向 Linux Bluetooth 堆栈完成同样的工作:在 Linux 上,它通过 /dev/vhci 向 BlueZ 挂载一个虚拟适配器,测量用接收器 tools/linux_sink 会像对待真实适配器一样接管它——因此无需硬件即可测试,还可以选择模拟丢失或延迟的媒体数据包(--drop、--stall)。请参阅 tools/linux_sink/README.md。

依赖项

C 库以 git 子模块的形式包含;Rust crate 和 UI 的 npm 软件包由 Cargo 和 pnpm 获取(版本固定在 Cargo.lock 和 app/src/ui/pnpm-lock.yaml 中;cargo deny check 会检查它们的许可证)。

库 方式 固定版本 许可证
BTstack git 子模块 v1.8.1-6-g5bc5cbdbe BTstack License(BSD-3-Clause 风格,附带非商业条款)
Bluedroid SBC codec 编码器已移植为 Rust;解码器(测试、工具用)取自 BTstack 附带的副本 与 BTstack 相同 Apache-2.0
rijndael 随 BTstack 附带(3rd-party/rijndael) 与 BTstack 相同 公有领域
liblc3 (lc3-google) 随 BTstack 附带(3rd-party/lc3-google) 与 BTstack 相同 Apache-2.0
micro-ecc 随 BTstack 附带(3rd-party/micro-ecc) 与 BTstack 相同 BSD-2-Clause
libldac (AOSP) git 子模块 android-15.0.0_r36-4-geeee1a3 Apache-2.0
libopenaptx git 子模块 0.2.0(请勿更新) LGPL-2.1+
fdk-aac git 子模块 v2.0.3-158-gd8e6b1a FDK AAC License
LHDC V5 编码器 git 子模块 以固定的版本为准 Apache-2.0
libopus git 子模块 v1.5.2 BSD-3-Clause
Tauri、SolidJS、Rust crate Cargo / pnpm Cargo.lock、pnpm-lock.yaml MIT / Apache-2.0 等(见发布包中的 licenses/rust-crates.txt)

由于链接了 BTstack,你构建的任何 A2DPWB 都只能用于个人非商业用途的使用和再分发,尽管 A2DPWB 源代码本身采用 Apache-2.0 或 MIT 双重许可。

完整的许可证详情请参阅 THIRD_PARTY_LICENSES.md。