aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/outcome
diff options
context:
space:
mode:
Diffstat (limited to 'internal/outcome')
-rw-r--r--internal/outcome/outcome.go4
-rw-r--r--internal/outcome/run_test.go10
-rw-r--r--internal/outcome/shim.go75
-rw-r--r--internal/outcome/sppipewire.go4
4 files changed, 88 insertions, 5 deletions
diff --git a/internal/outcome/outcome.go b/internal/outcome/outcome.go
index 45ef4431..3516eaef 100644
--- a/internal/outcome/outcome.go
+++ b/internal/outcome/outcome.go
@@ -257,6 +257,10 @@ type outcomeStateParams struct {
// Populated by spRuntimeOp.
runtimeDir *check.Absolute
+ // Path to pipewire-pulse server.
+ // Populated by spPipeWireOp if DirectPipeWire is false.
+ pipewirePulsePath *check.Absolute
+
as hst.ApplyState
*outcomeState
}
diff --git a/internal/outcome/run_test.go b/internal/outcome/run_test.go
index db18e02c..0f58dec6 100644
--- a/internal/outcome/run_test.go
+++ b/internal/outcome/run_test.go
@@ -100,7 +100,6 @@ func TestOutcomeRun(t *testing.T) {
"GOOGLE_DEFAULT_CLIENT_ID=77185425430.apps.googleusercontent.com",
"GOOGLE_DEFAULT_CLIENT_SECRET=OTJgUOQcT7lO7GsGZq2G4IlT",
"HOME=/data/data/org.chromium.Chromium",
- "PIPEWIRE_REMOTE=/run/user/1971/pipewire-0",
"SHELL=/run/current-system/sw/bin/zsh",
"TERM=xterm-256color",
"USER=chronos",
@@ -150,9 +149,6 @@ func TestOutcomeRun(t *testing.T) {
// spWaylandOp
Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/wayland"), m("/run/user/1971/wayland-0"), 0).
- // spPipeWireOp
- Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/pipewire"), m("/run/user/1971/pipewire-0"), 0).
-
// spDBusOp
Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bus"), m("/run/user/1971/bus"), 0).
Bind(m("/tmp/hakurei.0/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/system_bus_socket"), m("/var/run/dbus/system_bus_socket"), 0).
@@ -174,7 +170,7 @@ func TestOutcomeRun(t *testing.T) {
Remount(fhs.AbsRoot, syscall.MS_RDONLY),
}},
- {"nixos permissive defaults no enablements", new(stubNixOS), &hst.Config{Container: &hst.ContainerConfig{
+ {"nixos permissive defaults no enablements", new(stubNixOS), &hst.Config{DirectPipeWire: true, Container: &hst.ContainerConfig{
Filesystem: []hst.FilesystemConfigJSON{
{FilesystemConfig: &hst.FSBind{
Target: fhs.AbsRoot,
@@ -256,6 +252,8 @@ func TestOutcomeRun(t *testing.T) {
}},
{"nixos permissive defaults chromium", new(stubNixOS), &hst.Config{
+ DirectPipeWire: true,
+
ID: "org.chromium.Chromium",
Identity: 9,
Groups: []string{"video"},
@@ -426,6 +424,8 @@ func TestOutcomeRun(t *testing.T) {
}},
{"nixos chromium direct wayland", new(stubNixOS), &hst.Config{
+ DirectPipeWire: true,
+
ID: "org.chromium.Chromium",
Enablements: hst.NewEnablements(hst.EWayland | hst.EDBus | hst.EPipeWire | hst.EPulse),
Container: &hst.ContainerConfig{
diff --git a/internal/outcome/shim.go b/internal/outcome/shim.go
index 59b1236c..a569e7a6 100644
--- a/internal/outcome/shim.go
+++ b/internal/outcome/shim.go
@@ -15,9 +15,11 @@ import (
"hakurei.app/container"
"hakurei.app/container/check"
+ "hakurei.app/container/fhs"
"hakurei.app/container/seccomp"
"hakurei.app/container/std"
"hakurei.app/hst"
+ "hakurei.app/internal/pipewire"
"hakurei.app/message"
)
@@ -266,6 +268,79 @@ func shimEntrypoint(k syscallDispatcher) {
// bounds and default enforced in finalise.go
z.WaitDelay = state.Shim.WaitDelay
+ if stateParams.pipewirePulsePath != nil {
+ zpw := container.NewCommand(ctx, msg, stateParams.pipewirePulsePath, pipewirePulseName)
+ zpw.Hostname = "hakurei-" + pipewirePulseName
+ zpw.SeccompFlags |= seccomp.AllowMultiarch
+ zpw.SeccompPresets |= std.PresetStrict
+ zpw.Env = []string{
+ // pipewire SecurityContext socket path
+ pipewire.Remote + "=" + stateParams.instancePath().Append("pipewire").String(),
+ // pipewire-pulse socket directory path
+ envXDGRuntimeDir + "=" + sp.String(),
+ }
+ if msg.IsVerbose() {
+ zpw.Stdin, zpw.Stdout, zpw.Stderr = os.Stdin, os.Stdout, os.Stderr
+ }
+ zpw.
+ Bind(fhs.AbsRoot, fhs.AbsRoot, 0).
+ Bind(sp.unwrap(), sp.unwrap(), std.BindWritable).
+ Proc(fhs.AbsProc).Dev(fhs.AbsDev, true)
+ socketPath := sp.unwrap().Append("pulse", "native")
+ innerSocketPath := stateParams.runtimeDir.Append("pulse", "native")
+
+ if err := k.containerStart(zpw); err != nil {
+ sp.destroy()
+ printMessageError(func(v ...any) { k.fatal(fmt.Sprintln(v...)) },
+ "cannot start "+pipewirePulseName+" container:", err)
+ }
+ if err := k.containerServe(zpw); err != nil {
+ sp.destroy()
+ printMessageError(func(v ...any) { k.fatal(fmt.Sprintln(v...)) },
+ "cannot configure "+pipewirePulseName+" container:", err)
+ }
+
+ done := make(chan error, 1)
+ k.new(func(k syscallDispatcher, msg message.Msg) { done <- k.containerWait(zpw) })
+
+ socketTimer := time.NewTimer(shimPipeWireTimeout)
+ for {
+ select {
+ case <-socketTimer.C:
+ sp.destroy()
+ k.fatal(pipewirePulseName + " exceeded deadline before socket appeared")
+ break
+
+ case err := <-done:
+ var exitError *exec.ExitError
+ if !errors.As(err, &exitError) {
+ msg.Verbosef("cannot wait: %v", err)
+ k.exit(127)
+ }
+ sp.destroy()
+ k.fatal(pipewirePulseName + " " + exitError.ProcessState.String())
+ break
+
+ default:
+ if _, err := k.stat(socketPath.String()); err != nil {
+ if !errors.Is(err, os.ErrNotExist) {
+ sp.destroy()
+ k.fatal(err)
+ break
+ }
+
+ time.Sleep(500 * time.Microsecond)
+ continue
+ }
+ }
+
+ break
+ }
+
+ z.Bind(socketPath, innerSocketPath, 0)
+ z.Env = append(z.Env, "PULSE_SERVER=unix:"+innerSocketPath.String())
+ }
+
if err := k.containerStart(z); err != nil {
var f func(v ...any)
if logger := msg.GetLogger(); logger != nil {
diff --git a/internal/outcome/sppipewire.go b/internal/outcome/sppipewire.go
index fd99d514..8c5760bd 100644
--- a/internal/outcome/sppipewire.go
+++ b/internal/outcome/sppipewire.go
@@ -41,9 +41,13 @@ func (s *spPipeWireOp) toSystem(state *outcomeStateSys) error {
}
func (s *spPipeWireOp) toContainer(state *outcomeStateParams) error {
+ if s.CompatServerPath == nil {
innerPath := state.runtimeDir.Append(pipewire.PW_DEFAULT_REMOTE)
state.env[pipewire.Remote] = innerPath.String()
state.params.Bind(state.instancePath().Append("pipewire"), innerPath, 0)
+ }
+ // pipewire-pulse behaviour implemented in shim.go
+ state.pipewirePulsePath = s.CompatServerPath
return nil
}