internal/pipewire: implement Registry::GlobalRemove
All checks were successful
Test / Create distribution (push) Successful in 41s
Test / Sandbox (push) Successful in 2m47s
Test / Sandbox (race detector) (push) Successful in 5m6s
Test / Hakurei (push) Successful in 5m30s
Test / Hpkg (push) Successful in 5m39s
Test / Hakurei (race detector) (push) Successful in 7m18s
Test / Flake checks (push) Successful in 1m41s
All checks were successful
Test / Create distribution (push) Successful in 41s
Test / Sandbox (push) Successful in 2m47s
Test / Sandbox (race detector) (push) Successful in 5m6s
Test / Hakurei (push) Successful in 5m30s
Test / Hpkg (push) Successful in 5m39s
Test / Hakurei (race detector) (push) Successful in 7m18s
Test / Flake checks (push) Successful in 1m41s
This is emitted by PipeWire when a global object disappears, because PipeWire insists that all clients that had called Core::GetRegistry must constantly sync its local registry state with the remote. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -533,6 +533,30 @@ func (c *RegistryGlobal) MarshalBinary() ([]byte, error) { return Marshal(c) }
|
||||
// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
|
||||
func (c *RegistryGlobal) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }
|
||||
|
||||
// A RegistryGlobalRemove event is emitted when a global with id was removed.
|
||||
type RegistryGlobalRemove struct {
|
||||
// The global id that was removed.
|
||||
ID Int `json:"id"`
|
||||
}
|
||||
|
||||
// Opcode satisfies [Message] with a constant value.
|
||||
func (c *RegistryGlobalRemove) Opcode() byte { return PW_REGISTRY_EVENT_GLOBAL_REMOVE }
|
||||
|
||||
// FileCount satisfies [Message] with a constant value.
|
||||
func (c *RegistryGlobalRemove) FileCount() Int { return 0 }
|
||||
|
||||
// Size satisfies [KnownSize] with a constant value.
|
||||
func (c *RegistryGlobalRemove) Size() Word {
|
||||
return SizePrefix +
|
||||
Size(SizeInt)
|
||||
}
|
||||
|
||||
// MarshalBinary satisfies [encoding.BinaryMarshaler] via [Marshal].
|
||||
func (c *RegistryGlobalRemove) MarshalBinary() ([]byte, error) { return Marshal(c) }
|
||||
|
||||
// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
|
||||
func (c *RegistryGlobalRemove) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }
|
||||
|
||||
// RegistryBind is sent when the client requests to bind to the
|
||||
// global object with id and use the client proxy with new_id as
|
||||
// the proxy. After this call, methods can be sent to the remote
|
||||
@@ -714,6 +738,14 @@ func (e *GlobalIDCollisionError) Error() string {
|
||||
" stepping on previous id " + strconv.Itoa(int(e.ID)) + " for " + e.Previous.Type
|
||||
}
|
||||
|
||||
// An UnknownGlobalIDRemoveError describes a [RegistryGlobalRemove] event announcing the removal of
|
||||
// a global id that is not yet known to [Registry] or was already deleted.
|
||||
type UnknownGlobalIDRemoveError Int
|
||||
|
||||
func (e UnknownGlobalIDRemoveError) Error() string {
|
||||
return "Registry::GlobalRemove event targets unknown id " + strconv.Itoa(int(e))
|
||||
}
|
||||
|
||||
func (registry *Registry) consume(opcode byte, files []int, unmarshal func(v any)) error {
|
||||
closeReceivedFiles(files...)
|
||||
switch opcode {
|
||||
@@ -727,6 +759,17 @@ func (registry *Registry) consume(opcode byte, files []int, unmarshal func(v any
|
||||
registry.Objects[global.ID] = global
|
||||
return nil
|
||||
|
||||
case PW_REGISTRY_EVENT_GLOBAL_REMOVE:
|
||||
var globalRemove RegistryGlobalRemove
|
||||
unmarshal(&globalRemove)
|
||||
l := len(registry.Objects)
|
||||
delete(registry.Objects, globalRemove.ID)
|
||||
if len(registry.Objects) != l-1 {
|
||||
// this should never happen so is non-recoverable if it does
|
||||
panic(UnknownGlobalIDRemoveError(globalRemove.ID))
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
return &UnsupportedOpcodeError{opcode, registry.String()}
|
||||
}
|
||||
|
||||
@@ -745,6 +745,23 @@ func TestRegistryGlobal(t *testing.T) {
|
||||
}.run(t)
|
||||
}
|
||||
|
||||
func TestRegistryGlobalRemove(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
encodingTestCases[pipewire.RegistryGlobalRemove, *pipewire.RegistryGlobalRemove]{
|
||||
{"sample", []byte{
|
||||
/* size: rest of data*/ 0x10, 0, 0, 0,
|
||||
/* type: Struct */ 0xe, 0, 0, 0,
|
||||
/* size: 4 bytes */ 4, 0, 0, 0,
|
||||
/* type: Int */ 4, 0, 0, 0,
|
||||
/* value: 0xbad */ 0xad, 0xb, 0, 0,
|
||||
/* padding */ 0, 0, 0, 0,
|
||||
}, pipewire.RegistryGlobalRemove{
|
||||
ID: 0xbad,
|
||||
}, nil},
|
||||
}.run(t)
|
||||
}
|
||||
|
||||
func TestRegistryBind(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -862,6 +862,14 @@ func TestContextErrors(t *testing.T) {
|
||||
ID: 0xbad,
|
||||
Sequence: 0xcafe,
|
||||
}, "received Core::Ping seq 51966 targeting unknown proxy id 2989"},
|
||||
|
||||
{"GlobalIDCollisionError", &pipewire.GlobalIDCollisionError{
|
||||
ID: 0xbad,
|
||||
Previous: &pipewire.RegistryGlobal{Type: "PipeWire:Interface:Invalid"},
|
||||
Current: &pipewire.RegistryGlobal{Type: "PipeWire:Interface:NewInvalid"},
|
||||
}, "new Registry::Global event for PipeWire:Interface:NewInvalid stepping on previous id 2989 for PipeWire:Interface:Invalid"},
|
||||
|
||||
{"UnknownGlobalIDRemoveError", pipewire.UnknownGlobalIDRemoveError(0xbad), "Registry::GlobalRemove event targets unknown id 2989"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user