aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pipewire
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-11-30 01:39:39 +0900
committerOphestra <cat@gensokyo.uk>2025-11-30 01:39:39 +0900
commit3d4c7cdd9e82d1cc48e2564f4e5a569424a1819b (patch)
tree9d555cd3be52910e5dc05a352e60e3d631f8f31d /internal/pipewire
parent4fd6d6c037b30b02aff861542721b0cc40f083fe (diff)
internal/pipewire: implement Core::Error
Sample was captured from pw-cli. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pipewire')
-rw-r--r--internal/pipewire/core.go36
-rw-r--r--internal/pipewire/core_test.go46
-rw-r--r--internal/pipewire/header_test.go26
3 files changed, 96 insertions, 12 deletions
diff --git a/internal/pipewire/core.go b/internal/pipewire/core.go
index 99e4137e..a15d0803 100644
--- a/internal/pipewire/core.go
+++ b/internal/pipewire/core.go
@@ -167,6 +167,42 @@ func (c *CorePing) MarshalBinary() ([]byte, error) { return Marshal(c) }
// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
func (c *CorePing) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }
+// The CoreError can be emitted by both the client and the server.
+//
+// When emitted by the server, the error event is sent out when a fatal
+// (non-recoverable) error has occurred. The id argument is the proxy
+// object where the error occurred, most often in response to a request
+// to that object. The message is a brief description of the error, for
+// (debugging) convenience.
+//
+// When emitted by the client, it indicates an error occurred in an
+// object on the client.
+type CoreError struct {
+ // The id of the resource (proxy if emitted by the client) that is in error.
+ ID Int `json:"id"`
+ // A seq number from the failing request (if any).
+ Sequence Int `json:"seq"`
+ // A negative errno style error code.
+ Result Int `json:"res"`
+ // An error message.
+ Message String `json:"message"`
+}
+
+// Size satisfies [KnownSize] with a value computed at runtime.
+func (c *CoreError) Size() Word {
+ return SizePrefix +
+ Size(SizeInt) +
+ Size(SizeInt) +
+ Size(SizeInt) +
+ SizeString[Word](c.Message)
+}
+
+// MarshalBinary satisfies [encoding.BinaryMarshaler] via [Marshal].
+func (c *CoreError) MarshalBinary() ([]byte, error) { return Marshal(c) }
+
+// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
+func (c *CoreError) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }
+
// The CoreBoundProps event is emitted when a local object ID is bound to a global ID.
// It is emitted before the global becomes visible in the registry.
type CoreBoundProps struct {
diff --git a/internal/pipewire/core_test.go b/internal/pipewire/core_test.go
index d2a1a0d0..9771eff3 100644
--- a/internal/pipewire/core_test.go
+++ b/internal/pipewire/core_test.go
@@ -144,6 +144,52 @@ func TestCorePing(t *testing.T) {
}.run(t)
}
+func TestCoreError(t *testing.T) {
+ t.Parallel()
+
+ encodingTestCases[pipewire.CoreError, *pipewire.CoreError]{
+ // captured from pw-cli
+ {"pw-cli", []byte{
+ /* size: rest of data */ 0x58, 0, 0, 0,
+ /* type: Struct */ 0xe, 0, 0, 0,
+
+ /* size: 4 bytes */ 4, 0, 0, 0,
+ /* type: Int */ 4, 0, 0, 0,
+ /* value: 2 */ 2, 0, 0, 0,
+ /* padding */ 0, 0, 0, 0,
+
+ /* size: 4 bytes */ 4, 0, 0, 0,
+ /* type: Int */ 4, 0, 0, 0,
+ /* value: 0x67 */ 0x67, 0, 0, 0,
+ /* padding */ 0, 0, 0, 0,
+
+ /* size: 4 bytes */ 4, 0, 0, 0,
+ /* type: Int */ 4, 0, 0, 0,
+ /* value: -1 */ 0xff, 0xff, 0xff, 0xff,
+ /* padding */ 0, 0, 0, 0,
+
+ /* size: 0x1b bytes */ 0x1b, 0, 0, 0,
+ /*type: String*/ 8, 0, 0, 0,
+
+ // value: "no permission to destroy 0\x00"
+ 0x6e, 0x6f, 0x20, 0x70,
+ 0x65, 0x72, 0x6d, 0x69,
+ 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x74, 0x6f,
+ 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x72, 0x6f, 0x79,
+ 0x20, 0x30, 0,
+
+ /* padding */ 0, 0, 0, 0, 0,
+ }, pipewire.CoreError{
+ ID: 2,
+ Sequence: 0x67,
+ Result: -1,
+ Message: "no permission to destroy 0",
+ }, nil},
+ }.run(t)
+}
+
func TestCoreBoundProps(t *testing.T) {
t.Parallel()
diff --git a/internal/pipewire/header_test.go b/internal/pipewire/header_test.go
index 8dc58b94..eca12d89 100644
--- a/internal/pipewire/header_test.go
+++ b/internal/pipewire/header_test.go
@@ -336,6 +336,20 @@ func TestHeader(t *testing.T) {
Size: 0x28, Sequence: 44, FileCount: 0,
}, nil},
+ /* excerpts */
+
+ {"PW_CORE_EVENT_ERROR", []byte{
+ /* Id: */ 0, 0, 0, 0,
+ /* size: */ 0x60, 0, 0,
+ /* opcode: */ 3,
+ /* seq: */ 0xf5, 0, 0, 0,
+ /* n_fds: */ 0, 0, 0, 0,
+ }, pipewire.Header{
+ ID: pipewire.PW_ID_CORE,
+ Opcode: pipewire.PW_CORE_EVENT_ERROR,
+ Size: 0x60, Sequence: 0xf5, FileCount: 0,
+ }, nil},
+
/* handmade samples */
{"PW_CORE_EVENT_PING", []byte{
@@ -350,18 +364,6 @@ func TestHeader(t *testing.T) {
Size: 0xbed, Sequence: 0xffff, FileCount: 0xcafe,
}, nil},
- {"PW_CORE_EVENT_ERROR", []byte{
- /* Id: */ 0, 0, 0, 0,
- /* size: */ 0xad, 0xb, 0,
- /* opcode: */ 3,
- /* seq: */ 0xfe, 0xfe, 0, 0,
- /* n_fds: */ 0xfe, 0xca, 0, 0,
- }, pipewire.Header{
- ID: pipewire.PW_ID_CORE,
- Opcode: pipewire.PW_CORE_EVENT_ERROR,
- Size: 0xbad, Sequence: 0xfefe, FileCount: 0xcafe,
- }, nil},
-
{"PW_CORE_METHOD_PONG", []byte{
/* Id: */ 0, 0, 0, 0,
/* size: */ 0xed, 0xb, 0,