internal/pipewire: implement Core::Error
All checks were successful
Test / Create distribution (push) Successful in 39s
Test / Sandbox (push) Successful in 2m29s
Test / Hakurei (push) Successful in 3m23s
Test / Hpkg (push) Successful in 4m19s
Test / Sandbox (race detector) (push) Successful in 4m24s
Test / Hakurei (race detector) (push) Successful in 5m13s
Test / Flake checks (push) Successful in 1m31s

Sample was captured from pw-cli.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-11-30 01:39:39 +09:00
parent 4fd6d6c037
commit 3d4c7cdd9e
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
3 changed files with 96 additions and 12 deletions

View File

@ -167,6 +167,42 @@ func (c *CorePing) MarshalBinary() ([]byte, error) { return Marshal(c) }
// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal]. // UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
func (c *CorePing) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) } 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. // 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. // It is emitted before the global becomes visible in the registry.
type CoreBoundProps struct { type CoreBoundProps struct {

View File

@ -144,6 +144,52 @@ func TestCorePing(t *testing.T) {
}.run(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) { func TestCoreBoundProps(t *testing.T) {
t.Parallel() t.Parallel()

View File

@ -336,6 +336,20 @@ func TestHeader(t *testing.T) {
Size: 0x28, Sequence: 44, FileCount: 0, Size: 0x28, Sequence: 44, FileCount: 0,
}, nil}, }, 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 */ /* handmade samples */
{"PW_CORE_EVENT_PING", []byte{ {"PW_CORE_EVENT_PING", []byte{
@ -350,18 +364,6 @@ func TestHeader(t *testing.T) {
Size: 0xbed, Sequence: 0xffff, FileCount: 0xcafe, Size: 0xbed, Sequence: 0xffff, FileCount: 0xcafe,
}, nil}, }, 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{ {"PW_CORE_METHOD_PONG", []byte{
/* Id: */ 0, 0, 0, 0, /* Id: */ 0, 0, 0, 0,
/* size: */ 0xed, 0xb, 0, /* size: */ 0xed, 0xb, 0,