|
8 | 8 | "fmt" |
9 | 9 | "log" |
10 | 10 | "os" |
| 11 | + "os/exec" |
| 12 | + "strconv" |
11 | 13 | "strings" |
12 | 14 | "sync" |
13 | 15 | "sync/atomic" |
@@ -114,9 +116,22 @@ func NewSession(cfg input.SessionConfig) (*Session, error) { |
114 | 116 | "--media-category", "Capture", |
115 | 117 | "--media-role", "DSP", |
116 | 118 | "--properties", string(propsJSON), |
117 | | - "-", |
118 | 119 | } |
119 | 120 |
|
| 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 | + |
120 | 135 | return &Session{ |
121 | 136 | session: *execread.NewSession(args, true, cfg), |
122 | 137 | props: currentProps, |
@@ -166,7 +181,6 @@ func (s *Session) Start(ctx context.Context, dst [][]input.Sample, kickChan chan |
166 | 181 | // |
167 | 182 | // - https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/2731 |
168 | 183 | // - https://gitlab.freedesktop.org/pipewire/wireplumber/-/issues/358 |
169 | | -// |
170 | 184 | func (s *Session) startRelinker(ctx context.Context) error { |
171 | 185 | var catnipPorts map[string]pwObjectID |
172 | 186 | var err error |
@@ -296,3 +310,52 @@ func shortEpoch() string { |
296 | 310 | binary.LittleEndian.PutUint64(buf[:], uint64(now)) |
297 | 311 | return base64.RawURLEncoding.EncodeToString(buf[:]) |
298 | 312 | } |
| 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