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].
|
// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
|
||||||
func (c *RegistryGlobal) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }
|
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
|
// RegistryBind is sent when the client requests to bind to the
|
||||||
// global object with id and use the client proxy with new_id as
|
// 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
|
// 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
|
" 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 {
|
func (registry *Registry) consume(opcode byte, files []int, unmarshal func(v any)) error {
|
||||||
closeReceivedFiles(files...)
|
closeReceivedFiles(files...)
|
||||||
switch opcode {
|
switch opcode {
|
||||||
@@ -727,6 +759,17 @@ func (registry *Registry) consume(opcode byte, files []int, unmarshal func(v any
|
|||||||
registry.Objects[global.ID] = global
|
registry.Objects[global.ID] = global
|
||||||
return nil
|
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:
|
default:
|
||||||
return &UnsupportedOpcodeError{opcode, registry.String()}
|
return &UnsupportedOpcodeError{opcode, registry.String()}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -745,6 +745,23 @@ func TestRegistryGlobal(t *testing.T) {
|
|||||||
}.run(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) {
|
func TestRegistryBind(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -862,6 +862,14 @@ func TestContextErrors(t *testing.T) {
|
|||||||
ID: 0xbad,
|
ID: 0xbad,
|
||||||
Sequence: 0xcafe,
|
Sequence: 0xcafe,
|
||||||
}, "received Core::Ping seq 51966 targeting unknown proxy id 2989"},
|
}, "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 {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user