aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--internal/pipewire/core.go37
-rw-r--r--internal/pipewire/pipewire.go35
2 files changed, 51 insertions, 21 deletions
diff --git a/internal/pipewire/core.go b/internal/pipewire/core.go
index a53f02d5..d115da33 100644
--- a/internal/pipewire/core.go
+++ b/internal/pipewire/core.go
@@ -642,33 +642,28 @@ func (registry *Registry) destroy(id Int) error {
}
// Destroy tries to destroy the global object with id.
-func (registry *Registry) Destroy(id Int) error {
- if err := registry.destroy(id); err != nil {
+func (registry *Registry) Destroy(id Int) (err error) {
+ asCoreError := registry.ctx.expectsCoreError(registry.ID, &err)
+ if err != nil {
+ return
+ }
+ if err = registry.destroy(id); err != nil {
return err
}
- destroySeq := registry.ctx.currentSeq()
-
- err := registry.ctx.GetCore().Sync()
- if err == nil {
+ if err = registry.ctx.GetCore().Sync(); err == nil {
return nil
}
- var coreError *CoreError
- if proxyErrors, ok := err.(ProxyConsumeError); !ok ||
- len(proxyErrors) != 1 ||
- !errors.As(proxyErrors[0], &coreError) ||
- coreError == nil ||
- coreError.ID != registry.ID ||
- coreError.Sequence != destroySeq {
- return err
- }
+ if coreError := asCoreError(); coreError == nil {
+ return
+ } else {
+ switch syscall.Errno(-coreError.Result) {
+ case syscall.EPERM:
+ return &PermissionError{registry.ID, coreError.Message}
- switch syscall.Errno(-coreError.Result) {
- case syscall.EPERM:
- return &PermissionError{registry.ID, coreError.Message}
-
- default:
- return coreError
+ default:
+ return coreError
+ }
}
}
diff --git a/internal/pipewire/pipewire.go b/internal/pipewire/pipewire.go
index 5473797c..636c7590 100644
--- a/internal/pipewire/pipewire.go
+++ b/internal/pipewire/pipewire.go
@@ -16,6 +16,7 @@ package pipewire
import (
"encoding/binary"
+ "errors"
"fmt"
"io"
"net"
@@ -786,6 +787,40 @@ func (ctx *Context) Close() (err error) {
}
}
+// expectsCoreError returns a function that inspects an error value and
+// returns the address of a [CoreError] if it is the only error present
+// and targets the specified proxy and sequence.
+//
+// The behaviour of expectsCoreError is only correct for an empty buf
+// prior to calling. If buf is not empty, [Core.Sync] is called, with
+// its return value stored to the value pointed to by errP if not nil,
+// and the function is not populated.
+//
+// The caller must queue a message and call [Core.Sync] immediately
+// after calling expectsCoreError.
+func (ctx *Context) expectsCoreError(id Int, errP *error) (asCoreError func() (coreError *CoreError)) {
+ if len(ctx.buf) > 0 {
+ if err := ctx.GetCore().Sync(); err != nil {
+ *errP = err
+ return nil
+ }
+ }
+
+ sequence := ctx.sequence
+ return func() (coreError *CoreError) {
+ if proxyErrors, ok := (*errP).(ProxyConsumeError); !ok ||
+ len(proxyErrors) != 1 ||
+ !errors.As(proxyErrors[0], &coreError) ||
+ coreError == nil ||
+ coreError.ID != id ||
+ coreError.Sequence != sequence {
+ // do not return a non-matching CoreError
+ coreError = nil
+ }
+ return
+ }
+}
+
// A PermissionError describes an error emitted by the server when trying to
// perform an operation that the client has no permission for.
type PermissionError struct {