aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-11-25 15:15:20 +0900
committerOphestra <cat@gensokyo.uk>2025-11-25 15:16:12 +0900
commitcfeb7818eb3d7f3e83492bab092adce8f90f83c1 (patch)
tree19cd7154d81984fdae869bbc802b186d8cf7751d
parent05391da5562db46d379f81145b461a0a4ad10c8d (diff)
internal/pipewire: implement Core::Info and generation footer
These are not directly related but are first encountered on the same message in the capture. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--internal/pipewire/core.go45
-rw-r--r--internal/pipewire/core_test.go55
-rw-r--r--internal/pipewire/header_test.go6
-rw-r--r--internal/pipewire/pipewire_test.go7
-rw-r--r--internal/pipewire/testdata/08-recvmsg00-message00-headerbin0 -> 16 bytes
-rw-r--r--internal/pipewire/testdata/09-recvmsg00-message00-PODbin0 -> 1672 bytes
-rw-r--r--internal/pipewire/testdata/10-recvmsg00-message00-footerbin0 -> 48 bytes
7 files changed, 113 insertions, 0 deletions
diff --git a/internal/pipewire/core.go b/internal/pipewire/core.go
index 7a052086..e5b6abbb 100644
--- a/internal/pipewire/core.go
+++ b/internal/pipewire/core.go
@@ -66,6 +66,51 @@ const (
PW_VERSION_REGISTRY_METHODS = 0
)
+const (
+ FOOTER_CORE_OPCODE_GENERATION = iota
+
+ FOOTER_CORE_OPCODE_LAST
+)
+
+// The FooterCoreGeneration indicates to the client what is the current
+// registry generation number of the Context on the server side.
+//
+// The server shall include this footer in the next message it sends that
+// follows the increment of the registry generation number.
+type FooterCoreGeneration struct {
+ RegistryGeneration Long
+}
+
+// A CoreInfo event is emitted by the server upon connection
+// with the more information about the server.
+type CoreInfo struct {
+ // The id of the server (PW_ID_CORE).
+ ID Int
+ // A unique cookie for this server.
+ Cookie Int
+ // The name of the user running the server.
+ UserName String
+ // The name of the host running the server.
+ HostName String
+ // A version string of the server.
+ Version String
+ // The name of the server.
+ Name String
+ // A set of bits with changes to the info.
+ ChangeMask Long
+ // Optional key/value properties, valid when change_mask has PW_CORE_CHANGE_MASK_PROPS.
+ Props *SPADict
+}
+
+// MarshalBinary satisfies [encoding.BinaryMarshaler] via [Marshal].
+func (c *CoreInfo) MarshalBinary() ([]byte, error) { return Marshal(c) }
+
+// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
+func (c *CoreInfo) UnmarshalBinary(data []byte) error {
+ _, err := Unmarshal(data, c)
+ return err
+}
+
// CoreHello is the first message sent by a client.
type CoreHello struct {
// The version number of the client, usually PW_VERSION_CORE.
diff --git a/internal/pipewire/core_test.go b/internal/pipewire/core_test.go
index a04013c2..661dc391 100644
--- a/internal/pipewire/core_test.go
+++ b/internal/pipewire/core_test.go
@@ -6,6 +6,61 @@ import (
"hakurei.app/internal/pipewire"
)
+func TestFooterCoreGeneration(t *testing.T) {
+ encodingTestCases[pipewire.Footer[pipewire.FooterCoreGeneration], *pipewire.Footer[pipewire.FooterCoreGeneration]]{
+ {"sample", []byte(recvmsg00Message00Footer), pipewire.Footer[pipewire.FooterCoreGeneration]{
+ Opcode: pipewire.FOOTER_CORE_OPCODE_GENERATION,
+ Payload: pipewire.FooterCoreGeneration{RegistryGeneration: 34},
+ }, nil},
+ }.run(t)
+}
+
+func TestCoreInfo(t *testing.T) {
+ encodingTestCases[pipewire.CoreInfo, *pipewire.CoreInfo]{
+ {"sample", []byte(recvmsg00Message00POD), pipewire.CoreInfo{
+ ID: 0,
+ Cookie: -2069267610,
+ UserName: "alice",
+ HostName: "nixos",
+ Version: "1.4.7",
+ Name: "pipewire-0",
+ ChangeMask: pipewire.PW_CORE_CHANGE_MASK_PROPS,
+ Props: &pipewire.SPADict{NItems: 31, Items: []pipewire.SPADictItem{
+ {Key: "config.name", Value: "pipewire.conf"},
+ {Key: "application.name", Value: "pipewire"},
+ {Key: "application.process.binary", Value: "pipewire"},
+ {Key: "application.language", Value: "en_US.UTF-8"},
+ {Key: "application.process.id", Value: "1446"},
+ {Key: "application.process.user", Value: "alice"},
+ {Key: "application.process.host", Value: "nixos"},
+ {Key: "window.x11.display", Value: ":0"},
+ {Key: "cpu.vm.name", Value: "qemu"},
+ {Key: "link.max-buffers", Value: "16"},
+ {Key: "core.daemon", Value: "true"},
+ {Key: "core.name", Value: "pipewire-0"},
+ {Key: "default.clock.min-quantum", Value: "1024"},
+ {Key: "cpu.max-align", Value: "32"},
+ {Key: "default.clock.rate", Value: "48000"},
+ {Key: "default.clock.quantum", Value: "1024"},
+ {Key: "default.clock.max-quantum", Value: "2048"},
+ {Key: "default.clock.quantum-limit", Value: "8192"},
+ {Key: "default.clock.quantum-floor", Value: "4"},
+ {Key: "default.video.width", Value: "640"},
+ {Key: "default.video.height", Value: "480"},
+ {Key: "default.video.rate.num", Value: "25"},
+ {Key: "default.video.rate.denom", Value: "1"},
+ {Key: "log.level", Value: "2"},
+ {Key: "clock.power-of-two-quantum", Value: "true"},
+ {Key: "mem.warn-mlock", Value: "false"},
+ {Key: "mem.allow-mlock", Value: "true"},
+ {Key: "settings.check-quantum", Value: "false"},
+ {Key: "settings.check-rate", Value: "false"},
+ {Key: "object.id", Value: "0"},
+ {Key: "object.serial", Value: "0"}},
+ }}, nil},
+ }.run(t)
+}
+
func TestCoreHello(t *testing.T) {
encodingTestCases[pipewire.CoreHello, *pipewire.CoreHello]{
{"sample", []byte(sendmsg00Message00POD), pipewire.CoreHello{
diff --git a/internal/pipewire/header_test.go b/internal/pipewire/header_test.go
index d7ca468b..fb13be14 100644
--- a/internal/pipewire/header_test.go
+++ b/internal/pipewire/header_test.go
@@ -35,6 +35,12 @@ func TestHeader(t *testing.T) {
Size: 0x28, Sequence: 3, FileCount: 0,
}, nil},
+ {"PW_CORE_EVENT_INFO", []byte(recvmsg00Message00Header), pipewire.Header{
+ ID: pipewire.PW_ID_CORE,
+ Opcode: pipewire.PW_CORE_EVENT_INFO,
+ Size: 0x6b8, Sequence: 0, FileCount: 0,
+ }, nil},
+
{"PW_SECURITY_CONTEXT_METHOD_CREATE", []byte{
// Id
3, 0, 0, 0,
diff --git a/internal/pipewire/pipewire_test.go b/internal/pipewire/pipewire_test.go
index 28ba3293..a5770176 100644
--- a/internal/pipewire/pipewire_test.go
+++ b/internal/pipewire/pipewire_test.go
@@ -24,4 +24,11 @@ var (
sendmsg00Message03Header string
//go:embed testdata/07-sendmsg00-message03-POD
sendmsg00Message03POD string
+
+ //go:embed testdata/08-recvmsg00-message00-header
+ recvmsg00Message00Header string
+ //go:embed testdata/09-recvmsg00-message00-POD
+ recvmsg00Message00POD string
+ //go:embed testdata/10-recvmsg00-message00-footer
+ recvmsg00Message00Footer string
)
diff --git a/internal/pipewire/testdata/08-recvmsg00-message00-header b/internal/pipewire/testdata/08-recvmsg00-message00-header
new file mode 100644
index 00000000..60b6f0b8
--- /dev/null
+++ b/internal/pipewire/testdata/08-recvmsg00-message00-header
Binary files differ
diff --git a/internal/pipewire/testdata/09-recvmsg00-message00-POD b/internal/pipewire/testdata/09-recvmsg00-message00-POD
new file mode 100644
index 00000000..b0fa528d
--- /dev/null
+++ b/internal/pipewire/testdata/09-recvmsg00-message00-POD
Binary files differ
diff --git a/internal/pipewire/testdata/10-recvmsg00-message00-footer b/internal/pipewire/testdata/10-recvmsg00-message00-footer
new file mode 100644
index 00000000..a897629e
--- /dev/null
+++ b/internal/pipewire/testdata/10-recvmsg00-message00-footer
Binary files differ