Skip to content

Commit 5b96371

Browse files
committed
PipeWire.NET: .NET bindings for PipeWire
0 parents  commit 5b96371

189 files changed

Lines changed: 9349 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# editorconfig.org
2+
3+
# top-most EditorConfig file
4+
root = true
5+
6+
[*]
7+
insert_final_newline = true
8+
indent_style = space
9+
indent_size = 4
10+
trim_trailing_whitespace = true
11+
12+
[*{_AssemblyInfo.cs,.notsupported.cs,AsmOffsets.cs}]
13+
generated_code = true
14+
15+
[*.cs]
16+
csharp_new_line_before_open_brace = all
17+
csharp_new_line_before_else = true
18+
csharp_new_line_before_catch = true
19+
csharp_new_line_before_finally = true
20+
csharp_new_line_before_members_in_object_initializers = true
21+
csharp_new_line_before_members_in_anonymous_types = true
22+
csharp_new_line_between_query_expression_clauses = true
23+
csharp_indent_block_contents = true
24+
csharp_indent_braces = false
25+
csharp_indent_case_contents = true
26+
csharp_indent_case_contents_when_block = false
27+
csharp_indent_switch_labels = true
28+
csharp_indent_labels = one_less_than_current
29+
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion
30+
dotnet_style_qualification_for_field = false:suggestion
31+
dotnet_style_qualification_for_property = false:suggestion
32+
dotnet_style_qualification_for_method = false:suggestion
33+
dotnet_style_qualification_for_event = false:suggestion
34+
csharp_style_var_for_built_in_types = false:suggestion
35+
csharp_style_var_when_type_is_apparent = false:none
36+
csharp_style_var_elsewhere = false:suggestion
37+
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
38+
dotnet_style_predefined_type_for_member_access = true:suggestion
39+
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
40+
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
41+
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
42+
dotnet_naming_symbols.constant_fields.applicable_kinds = field
43+
dotnet_naming_symbols.constant_fields.required_modifiers = const
44+
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
45+
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
46+
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
47+
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
48+
dotnet_naming_symbols.static_fields.applicable_kinds = field
49+
dotnet_naming_symbols.static_fields.required_modifiers = static
50+
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
51+
dotnet_naming_style.static_prefix_style.required_prefix = s_
52+
dotnet_naming_style.static_prefix_style.capitalization = camel_case
53+
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
54+
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
55+
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
56+
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
57+
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
58+
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
59+
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
60+
csharp_using_directive_placement = outside_namespace:suggestion
61+
dotnet_sort_system_directives_first = true
62+
csharp_prefer_braces = true:silent
63+
csharp_prefer_static_local_function = true:suggestion
64+
csharp_style_prefer_switch_expression = true:suggestion
65+
dotnet_style_readonly_field = true:suggestion
66+
dotnet_style_object_initializer = true:suggestion
67+
dotnet_style_collection_initializer = true:suggestion
68+
dotnet_style_prefer_collection_expression = when_types_exactly_match
69+
dotnet_style_explicit_tuple_names = true:suggestion
70+
dotnet_style_coalesce_expression = true:suggestion
71+
dotnet_style_null_propagation = true:suggestion
72+
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
73+
dotnet_style_prefer_auto_properties = true:suggestion
74+
csharp_prefer_simple_default_expression = true:suggestion
75+
csharp_style_expression_bodied_methods = true:silent
76+
csharp_style_expression_bodied_constructors = true:silent
77+
csharp_style_expression_bodied_operators = true:silent
78+
csharp_style_expression_bodied_properties = true:silent
79+
csharp_style_expression_bodied_indexers = true:silent
80+
csharp_style_expression_bodied_accessors = true:silent
81+
csharp_style_expression_bodied_lambdas = true:silent
82+
csharp_style_expression_bodied_local_functions = true:silent
83+
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
84+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
85+
csharp_style_inlined_variable_declaration = true:suggestion
86+
csharp_style_throw_expression = true:suggestion
87+
csharp_style_conditional_delegate_call = true:suggestion
88+
csharp_space_after_cast = false
89+
csharp_space_after_colon_in_inheritance_clause = true
90+
csharp_space_after_comma = true
91+
csharp_space_after_dot = false
92+
csharp_space_after_keywords_in_control_flow_statements = true
93+
csharp_space_after_semicolon_in_for_statement = true
94+
csharp_space_around_binary_operators = before_and_after
95+
csharp_space_before_colon_in_inheritance_clause = true
96+
csharp_space_before_comma = false
97+
csharp_space_before_dot = false
98+
csharp_space_before_open_square_brackets = false
99+
csharp_space_before_semicolon_in_for_statement = false
100+
csharp_space_between_empty_square_brackets = false
101+
csharp_space_between_method_call_empty_parameter_list_parentheses = false
102+
csharp_space_between_method_call_name_and_opening_parenthesis = false
103+
csharp_space_between_method_call_parameter_list_parentheses = false
104+
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
105+
csharp_space_between_method_declaration_name_and_open_parenthesis = false
106+
csharp_space_between_method_declaration_parameter_list_parentheses = false
107+
csharp_space_between_parentheses = false
108+
csharp_space_between_square_brackets = false
109+
110+
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
111+
indent_size = 2
112+
113+
[*.{csproj,vbproj,proj,nativeproj,locproj}]
114+
charset = utf-8
115+
116+
[*.builds]
117+
indent_size = 2
118+
119+
[*.{xml,stylecop,resx,ruleset}]
120+
indent_size = 2
121+
122+
[*.{props,targets,config,nuspec}]
123+
indent_size = 2
124+
125+
[*.{yml,yaml}]
126+
indent_size = 2
127+
128+
[*.sh]
129+
end_of_line = lf
130+
[*.{cmd,bat}]
131+
end_of_line = crlf

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Bug report
2+
description: Report a problem with PipeWire.NET
3+
labels: [bug]
4+
body:
5+
- type: textarea
6+
id: what-happened
7+
attributes:
8+
label: What happened
9+
description: A clear description of the bug and what you expected instead.
10+
validations:
11+
required: true
12+
- type: textarea
13+
id: repro
14+
attributes:
15+
label: Steps to reproduce
16+
description: Minimal code or steps that trigger the problem.
17+
validations:
18+
required: true
19+
- type: input
20+
id: package-version
21+
attributes:
22+
label: PipeWire.NET version
23+
placeholder: e.g. 0.1.0
24+
validations:
25+
required: true
26+
- type: input
27+
id: pipewire-version
28+
attributes:
29+
label: PipeWire version
30+
description: Output of `pipewire --version`.
31+
placeholder: e.g. 1.0.5
32+
validations:
33+
required: true
34+
- type: input
35+
id: dotnet-version
36+
attributes:
37+
label: .NET version
38+
placeholder: e.g. 10.0.100
39+
validations:
40+
required: true
41+
- type: input
42+
id: distro
43+
attributes:
44+
label: Distribution / kernel
45+
placeholder: e.g. Ubuntu 24.04, x86_64
46+
validations:
47+
required: false
48+
- type: textarea
49+
id: logs
50+
attributes:
51+
label: Logs
52+
description: Relevant exception or `PIPEWIRE_DEBUG=3` output, if any.
53+
render: shell
54+
validations:
55+
required: false

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
blank_issues_enabled: false
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Feature request
2+
description: Suggest an addition or change
3+
labels: [enhancement]
4+
body:
5+
- type: textarea
6+
id: problem
7+
attributes:
8+
label: Problem
9+
description: What are you trying to do that the library does not support today?
10+
validations:
11+
required: true
12+
- type: textarea
13+
id: proposal
14+
attributes:
15+
label: Proposed solution
16+
description: What would the API or behaviour look like?
17+
validations:
18+
required: false

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Summary
2+
3+
<!-- What does this change and why? -->
4+
5+
## Checklist
6+
7+
- [ ] `dotnet build` is clean (warnings are errors)
8+
- [ ] `dotnet test --filter "TestCategory!=Integration"` passes
9+
- [ ] If the native surface changed, `generate/generate.sh` was re-run and the result committed
10+
- [ ] Public API changes are documented

.github/workflows/build.yml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: build
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ["v*"]
7+
pull_request:
8+
branches: [main]
9+
10+
jobs:
11+
build:
12+
runs-on: ubuntu-latest
13+
permissions:
14+
id-token: write # OIDC for NuGet.org trusted publishing
15+
contents: read
16+
17+
steps:
18+
- uses: actions/checkout@v6
19+
with:
20+
fetch-depth: 0 # MinVer needs full history
21+
22+
- name: Install PipeWire runtime + dev headers + libclang
23+
run: |
24+
sudo apt-get update -qq
25+
sudo apt-get install -y --no-install-recommends \
26+
libpipewire-0.3-0 \
27+
libpipewire-0.3-dev \
28+
libclang-dev \
29+
pkg-config
30+
31+
- uses: actions/setup-dotnet@v5
32+
with:
33+
# net11.0 target requires the .NET 11 preview SDK alongside the .NET 10 SDK.
34+
# global.json (rollForward latestMajor, allowPrerelease) then selects the 11 SDK,
35+
# which builds both the net10.0 and net11.0 target frameworks.
36+
dotnet-version: |
37+
10.0.x
38+
11.0.x
39+
40+
- name: Restore
41+
run: dotnet restore PipeWire.NET.slnx
42+
43+
- name: Build
44+
run: dotnet build PipeWire.NET.slnx --no-restore -c Release
45+
46+
- name: Test (non-integration on host runner)
47+
run: dotnet test PipeWire.NET.slnx --no-build -c Release
48+
--filter "TestCategory!=Integration"
49+
50+
- name: Install ClangSharpPInvokeGenerator + native runtime packages
51+
run: |
52+
dotnet tool install --global ClangSharpPInvokeGenerator --version 21.1.8.3
53+
# The dotnet tool packaging does not bundle libclang/libClangSharp;
54+
# pull matching native packages and let generate.sh point LD at them.
55+
mkdir -p /tmp/clangsharp-bootstrap
56+
cd /tmp/clangsharp-bootstrap
57+
dotnet new console -o dummy -n dummy --force
58+
cd dummy
59+
dotnet add package libclang.runtime.linux-x64 --version 21.1.8
60+
dotnet add package libClangSharp.runtime.linux-x64 --version 21.1.8
61+
62+
- name: Verify generated bindings are up to date
63+
run: |
64+
bash generate/generate.sh
65+
if ! git diff --quiet -- src/PipeWire.NET/generated/; then
66+
echo "::error::Generated bindings are out of date."
67+
echo "Run 'bash generate/generate.sh' locally and commit the result."
68+
git diff -- src/PipeWire.NET/generated/
69+
exit 1
70+
fi
71+
72+
- name: Run Linux integration tests (against installed runtime, no daemon required)
73+
run: dotnet test PipeWire.NET.slnx --no-build -c Release
74+
--filter "TestCategory=Integration&TestCategory!=RequiresDaemon"
75+
76+
- name: Daemon end-to-end tests (headless PipeWire + GStreamer real sources)
77+
run: |
78+
sudo apt-get install -y --no-install-recommends \
79+
pipewire wireplumber pipewire-bin \
80+
gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-pipewire
81+
export XDG_RUNTIME_DIR="$(mktemp -d)"
82+
# Headless daemon: no systemd/login session needed.
83+
pipewire & PW_PID=$!
84+
wireplumber & WP_PID=$!
85+
# Wait for the graph to answer.
86+
for i in $(seq 1 40); do pw-cli info 0 >/dev/null 2>&1 && break; sleep 0.25; done
87+
set +e
88+
# RequiresGpu tests need a render node + GStreamer GL/VA; excluded on GPU-less CI runners.
89+
dotnet test PipeWire.NET.slnx --no-build -c Release \
90+
--filter "TestCategory=RequiresDaemon&TestCategory!=RequiresGpu"
91+
RC=$?
92+
set -e
93+
kill $WP_PID $PW_PID 2>/dev/null || true
94+
exit $RC
95+
96+
- name: Pack
97+
if: startsWith(github.ref, 'refs/tags/v')
98+
run: dotnet pack src/PipeWire.NET/PipeWire.NET.csproj --no-build -c Release -o dist
99+
100+
- name: Login to NuGet.org via OIDC
101+
if: startsWith(github.ref, 'refs/tags/v')
102+
uses: NuGet/login@v1
103+
id: nuget-login
104+
with:
105+
user: ${{ vars.NUGET_USER }}
106+
107+
- name: Push to NuGet.org
108+
if: startsWith(github.ref, 'refs/tags/v')
109+
run: |
110+
dotnet nuget push dist/*.nupkg \
111+
--api-key "${{ steps.nuget-login.outputs.NUGET_API_KEY }}" \
112+
--source https://api.nuget.org/v3/index.json \
113+
--skip-duplicate

.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## .NET
2+
bin/
3+
obj/
4+
*.user
5+
.vs/
6+
*.suo
7+
project.lock.json
8+
project.fragment.lock.json
9+
artifacts/
10+
11+
## NuGet
12+
*.nupkg
13+
*.snupkg
14+
nuget/
15+
16+
# VS/Rider per-user launch profiles
17+
**/Properties/launchSettings.json

CONTRIBUTING.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Contributing
2+
3+
Thanks for your interest in PipeWire.NET.
4+
5+
## Building
6+
7+
```sh
8+
dotnet build PipeWire.NET.slnx
9+
dotnet test --filter "TestCategory!=Integration"
10+
```
11+
12+
The build treats warnings as errors and targets .NET 10 (and .NET 11 preview).
13+
14+
Integration tests need a running PipeWire daemon on Linux. Some use GStreamer to produce real
15+
sources; install `gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good
16+
gstreamer1.0-pipewire`. Tests tagged `RequiresGpu` need a DRM render node and are skipped otherwise.
17+
18+
## Generated bindings
19+
20+
Files under `src/PipeWire.NET/generated/` are produced by ClangSharp from the PipeWire headers
21+
and are committed. Do not edit them by hand. To regenerate after a header change, run
22+
`generate/generate.sh` on Linux with `libpipewire-0.3-dev` and `libclang-dev` installed. CI fails
23+
if the committed output does not match a fresh generation.
24+
25+
Hand-written code that extends the generated `Native` class lives in
26+
`src/PipeWire.NET/Native.Extensions.cs`, outside the generated folder.
27+
28+
## Pull requests
29+
30+
Keep changes focused. Make sure the build is clean and the non-integration tests pass. If you
31+
change the native surface, regenerate and commit the bindings in the same PR.
32+
33+
## License
34+
35+
By contributing you agree that your contributions are licensed under the MIT License.

0 commit comments

Comments
 (0)