소스에서 빌드
목차
요구 사항
- rustup으로 설치한 Rust (stable, 1.90 이상)
- “C++를 사용한 데스크톱 개발” 워크로드가 설치된 Visual Studio 2022 이상(또는 Build Tools): 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 build tools”, x64 PC에서는 “C++ Clang Compiler for Windows”(rustls의
ring이 ARM64 어셈블리를 clang으로 빌드합니다.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: 상주 코어, 트레이, IPC 서버, --cli
│ │ ├── ui/ a2dpwb.exe: Tauri 2 + SolidJS (pnpm dev는 모의 코어와 함께 브라우저에서 실행)
│ │ ├── driver/ a2dpwb-driver.exe: WinUSB 할당 / 복원 (관리자 권한)
│ │ └── crates/ 라이브러리: btstack-sys, hci-transport, bt-host, codec, 코덱 -sys 크레이트,
│ │ pipeline, audio-capture, win-sys, core (a2dpwb-core), ipc, le-audio, lc3-sys
│ ├── lang/ 다국어 리소스 (en.json이 원본, 나머지는 tools/check_lang.py로 검사)
│ └── resources/ 아이콘과 매니페스트
├── Cargo.toml Cargo 워크스페이스
├── installer/ 릴리스 스크립트, NSIS 훅, 업데이터 메모 (installer/README.md)
├── compat/ AOSP 코드용 MSVC 호환 헤더
├── docs/ 문서 (이 사이트)와 설계 문서 (v2-design.md)
├── extern/ 서드파티 C 라이브러리 (git 서브모듈)
│ ├── btstack/ BTstack Bluetooth 스택
│ ├── libldac/ AOSP LDAC 인코더
│ ├── libopenaptx/ aptX / aptX HD / aptX LL 인코더
│ ├── fdk-aac/ Fraunhofer AAC 인코더
│ ├── lhdcv5-enc/ LHDC V5 인코더
│ └── opus/ libopus (Opus 인코더)
└── tools/
├── a2dp_decode/ a2dpwb_decode: HCI 캡처(.pklg)의 미디어 스트림 검사 / 디코딩
├── emu/ 가상 Bluetooth 싱크 대상 엔드투엔드 테스트 (Python)
└── linux_sink/ a2dpwb_sink: Linux용 측정 A2DP 수신기 (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의 가상 Bluetooth 싱크로 A2DPWB의 모든 코덱을 스트리밍합니다. 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 가상 컨트롤러 두 개를 실행합니다. 하나는 A2DPWB를 위해 TCP(127.0.0.1)를 통한 H4로 제공됩니다. 다른 하나는 SBC, AAC, aptX, aptX HD, aptX LL, LDAC을 제공하는 Bumble A2DP 싱크가 사용하며, 그 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가 별도의 설정 폴더를 사용하게 하므로, 가상 싱크와의 페어링이 실제 링크 키에 영향을 주지 않습니다.- 그런 다음 두 HCI 캡처를
a2dpwb_decode로 검사합니다(싱크 측은--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 크레이트와 UI의 npm 패키지는 Cargo와 pnpm이 가져옵니다(버전은 Cargo.lock과 app/src/ui/pnpm-lock.yaml에 고정, cargo deny check로 라이선스 검사).
| 라이브러리 | 방식 | 고정 버전 | 라이선스 |
|---|---|---|---|
| BTstack | git submodule | 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과 동일 | Public domain |
| 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 submodule | android-15.0.0_r36-4-geeee1a3 | Apache-2.0 |
| libopenaptx | git submodule | 0.2.0 (업데이트 금지) | LGPL-2.1+ |
| fdk-aac | git submodule | v2.0.3-158-gd8e6b1a | FDK AAC License |
| LHDC V5 encoder | git submodule | 고정된 버전 | Apache-2.0 |
| libopus | git submodule | v1.5.2 | BSD-3-Clause |
| Tauri, SolidJS, Rust 크레이트 | Cargo / pnpm | Cargo.lock, pnpm-lock.yaml | MIT / Apache-2.0 등 (릴리스의 licenses/rust-crates.txt) |
BTstack이 링크되어 있으므로, A2DPWB 소스 코드 자체는 Apache-2.0 또는 MIT 이중 라이선스이지만 직접 빌드한 A2DPWB도 개인적, 비상업적 목적으로만 사용 및 재배포할 수 있습니다.
전체 라이선스 정보는 THIRD_PARTY_LICENSES.md를 참조하십시오.