Skip to content

Commit b7f51af

Browse files
committed
fixes #24 by checking pw-cat version first
uses --raw arg if at or above pipewire 1.4.0
1 parent 7063b21 commit b7f51af

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

input/pipewire/pipewire.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"fmt"
99
"log"
1010
"os"
11+
"os/exec"
12+
"strconv"
1113
"strings"
1214
"sync"
1315
"sync/atomic"
@@ -114,9 +116,22 @@ func NewSession(cfg input.SessionConfig) (*Session, error) {
114116
"--media-category", "Capture",
115117
"--media-role", "DSP",
116118
"--properties", string(propsJSON),
117-
"-",
118119
}
119120

121+
// pw-cat 1.4.0 introduces explicit stdout support, needs --raw arg
122+
// see https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4629#top
123+
useRawArg, err := checkNeedRawArg()
124+
if err != nil {
125+
return nil, errors.Wrap(err, "failed to check need of pipewire '--raw' arg")
126+
}
127+
128+
if useRawArg {
129+
args = append(args, "--raw")
130+
}
131+
132+
// output to STDOUT
133+
args = append(args, "-")
134+
120135
return &Session{
121136
session: *execread.NewSession(args, true, cfg),
122137
props: currentProps,
@@ -166,7 +181,6 @@ func (s *Session) Start(ctx context.Context, dst [][]input.Sample, kickChan chan
166181
//
167182
// - https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/2731
168183
// - https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/358
169-
//
170184
func (s *Session) startRelinker(ctx context.Context) error {
171185
var catnipPorts map[string]pwObjectID
172186
var err error
@@ -296,3 +310,52 @@ func shortEpoch() string {
296310
binary.LittleEndian.PutUint64(buf[:], uint64(now))
297311
return base64.RawURLEncoding.EncodeToString(buf[:])
298312
}
313+
314+
func getPipewireVersion() (string, error) {
315+
cmd := exec.Command("pw-cat", "--version")
316+
317+
out, err := cmd.Output()
318+
319+
if err != nil {
320+
return "", err
321+
}
322+
323+
lines := strings.Split(string(out), "\n")
324+
325+
for _, line := range lines {
326+
if version, ok := strings.CutPrefix(line, "Compiled with libpipewire "); ok {
327+
return version, nil
328+
}
329+
}
330+
331+
return "unknown", nil
332+
}
333+
334+
func checkNeedRawArg() (bool, error) {
335+
versionCheck := []int{1, 4, 0}
336+
337+
version, err := getPipewireVersion()
338+
if err != nil {
339+
return false, errors.Wrap(err, "failed to get pipewire version")
340+
}
341+
342+
// only need the first three parts. the last bin can contain waste
343+
versionSplit := strings.SplitN(version, ".", 4)
344+
345+
if len(versionSplit) < len(versionCheck) {
346+
return false, errors.New("bad version string length")
347+
}
348+
349+
for i := range versionCheck {
350+
num, err := strconv.Atoi(versionSplit[i])
351+
if err != nil {
352+
return false, err
353+
}
354+
355+
if num < versionCheck[i] {
356+
return false, nil
357+
}
358+
}
359+
360+
return true, nil
361+
}

0 commit comments

Comments
 (0)