Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,5 @@ permissions:
contents: read

jobs:
build-native:
uses: ./.github/workflows/reusable-build-native.yml

test:
needs: build-native
uses: ./.github/workflows/reusable-test.yml
6 changes: 1 addition & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,8 @@ jobs:
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Resolved version: $VERSION"

build-native:
needs: version
uses: ./.github/workflows/reusable-build-native.yml

test:
needs: [version, build-native]
needs: version
uses: ./.github/workflows/reusable-test.yml

pack:
Expand Down
79 changes: 0 additions & 79 deletions .github/workflows/reusable-build-native.yml

This file was deleted.

1 change: 1 addition & 0 deletions .github/workflows/reusable-nuget-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
publish:
name: Publish to NuGet
runs-on: ubuntu-24.04
environment: production
steps:
- uses: actions/setup-dotnet@v5
with:
Expand Down
43 changes: 37 additions & 6 deletions .github/workflows/reusable-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ env:
DOTNET_NOLOGO: 'true'
DOTNET_CLI_TELEMETRY_OPTOUT: 'true'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true'
VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite'

permissions:
contents: read
Expand All @@ -29,26 +30,46 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0

- uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.0.x'

- name: Install hidapi runtime (macOS)
- name: Install hidapi + toolchain (macOS)
if: runner.os == 'macOS'
run: brew install hidapi

- name: Install hidapi runtime (Linux)
- name: Install hidapi + toolchain (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libhidapi-hidraw0 libhidapi-libusb0
cmake build-essential pkg-config libhidapi-dev

- uses: actions/download-artifact@v8
- name: Expose GHA cache tokens to vcpkg (Windows)
if: runner.os == 'Windows'
uses: actions/github-script@v9
with:
name: native-${{ matrix.rid }}
path: build/native/${{ matrix.rid }}/
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');

- name: Set vcpkg toolchain (Windows)
if: runner.os == 'Windows'
shell: bash
run: |
echo "CMAKE_EXTRA_ARGS=-DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT//\\//}/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows" >> "$GITHUB_ENV"

- name: Cache CMake build dir
uses: actions/cache@v5
with:
path: build/cmake/${{ matrix.rid }}
key: cmake-${{ matrix.rid }}-${{ hashFiles('headsetcontrollib/CMakeLists.txt', 'headsetcontrollib/lib/**/*.cpp', 'headsetcontrollib/lib/**/*.hpp', 'headsetcontrollib/lib/**/*.h', 'headsetcontrollib/vcpkg.json') }}
restore-keys: |
cmake-${{ matrix.rid }}-

- name: Cache NuGet packages
uses: actions/cache@v5
Expand All @@ -60,6 +81,8 @@ jobs:

- run: dotnet restore

# The HscPrepareNativeArtifacts target in HeadsetControl.NET.Native.csproj
# invokes build/build-native.sh for the host RID if no artefact is present.
- run: dotnet build -c Release --no-restore

- run: >-
Expand All @@ -68,6 +91,14 @@ jobs:
--logger "trx;LogFileName=test-results.trx"
--results-directory TestResults

- name: Upload native artefact
uses: actions/upload-artifact@v7
with:
name: native-${{ matrix.rid }}
path: build/native/${{ matrix.rid }}/
if-no-files-found: error
retention-days: 14

- if: always()
uses: actions/upload-artifact@v7
with:
Expand Down
10 changes: 8 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
<LangVersion>latest</LangVersion>

<Nullable>enable</Nullable>
Expand Down Expand Up @@ -35,7 +35,8 @@
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Version>0.2.0</Version>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Version>0.3.0</Version>
</PropertyGroup>

<PropertyGroup>
Expand All @@ -48,6 +49,11 @@
PackagePath="\"
Visible="false"
Condition="Exists('$(MSBuildThisFileDirectory)LICENSE')" />
<None Include="$(MSBuildThisFileDirectory)README.md"
Pack="true"
PackagePath="\"
Visible="false"
Condition="Exists('$(MSBuildThisFileDirectory)README.md')" />
</ItemGroup>

</Project>
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ headsetcontrollib/ git submodule with the native source

```bash
git submodule update --init --recursive
build/build-native.sh # host RID — or: --rid linux-x64
dotnet test -c Release
```

Expand Down
31 changes: 31 additions & 0 deletions build/build-native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,37 @@ BUILD_DIR="${BUILD_ROOT}/${RID}"
OUT_DIR="${OUT_ROOT}/${RID}"
mkdir -p "${BUILD_DIR}" "${OUT_DIR}"

# Serialise concurrent invocations for the same RID — when this script is
# wired into a multi-targeted .NET build, MSBuild may run it in parallel for
# each TFM, and the inner CMake build directory is not concurrency-safe.
# `mkdir` is atomic across processes, so we use a sentinel directory as the
# lock. The first process builds; later ones wait, then exit early once the
# artefact is in place.
LOCK_DIR="${BUILD_DIR}.lock"
trap 'rmdir "${LOCK_DIR}" 2>/dev/null || true' EXIT

WAITED=0
while ! mkdir "${LOCK_DIR}" 2>/dev/null; do
if [[ ${WAITED} -ge 600 ]]; then
echo "error: timed out waiting for ${LOCK_DIR}" >&2
exit 1
fi
sleep 1
WAITED=$((WAITED + 1))
done

case "${RID}" in
osx-*) EXPECTED="${OUT_DIR}/libheadsetcontrol.dylib" ;;
linux-*) EXPECTED="${OUT_DIR}/libheadsetcontrol.so" ;;
win-*) EXPECTED="${OUT_DIR}/headsetcontrol.dll" ;;
*) EXPECTED="" ;;
esac

if [[ -n "${EXPECTED}" && -f "${EXPECTED}" ]]; then
echo ">> ${EXPECTED} already present, skipping build"
exit 0
fi

echo ">> Configuring native HeadsetControl for ${RID}"
# shellcheck disable=SC2086
cmake -S "${NATIVE_SRC}" -B "${BUILD_DIR}" \
Expand Down
2 changes: 1 addition & 1 deletion headsetcontrollib
15 changes: 8 additions & 7 deletions samples/HeadsetControl.NET.Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using HeadsetControl.NET;
using HeadsetControl.NET.Exceptions;

bool useTestDevice = args.Contains("--test", StringComparer.OrdinalIgnoreCase);
var useTestDevice = args.Contains("--test", StringComparer.OrdinalIgnoreCase);

Console.WriteLine($"HeadsetControl native version: {HeadsetControlLibrary.Version}");
Console.WriteLine($"Supported device models: {HeadsetControlLibrary.SupportedDeviceCount}");
Expand All @@ -13,17 +14,17 @@
Console.WriteLine();
}

using HeadsetCollection headsets = HeadsetControlLibrary.Discover();
using var headsets = HeadsetControlLibrary.Discover();

if (headsets.Count == 0)
{
Console.WriteLine("No supported headset connected.");
return 0;
}

for (int i = 0; i < headsets.Count; i++)
for (var i = 0; i < headsets.Count; i++)
{
Headset headset = headsets[i];
var headset = headsets[i];

Console.WriteLine($"[{i}] {headset}");
Console.WriteLine($" Vendor : {headset.VendorName ?? "(unknown)"} (0x{headset.VendorId:X4})");
Expand All @@ -47,8 +48,8 @@ static void TryReadBattery(Headset headset)

try
{
BatteryInfo battery = headset.GetBattery();
string level = battery.LevelPercent is int pct ? $"{pct}%" : "n/a";
var battery = headset.GetBattery();
var level = battery.LevelPercent is int pct ? $"{pct}%" : "n/a";
Console.WriteLine($" Battery: {battery.Status} ({level})");
}
catch (HeadsetControlException ex)
Expand All @@ -66,7 +67,7 @@ static void TryReadChatMix(Headset headset)

try
{
ChatMixInfo mix = headset.GetChatMix();
var mix = headset.GetChatMix();
Console.WriteLine($" ChatMix: level={mix.Level} game={mix.GameVolumePercent}% chat={mix.ChatVolumePercent}%");
}
catch (HeadsetControlException ex)
Expand Down
Loading
Loading