summaryrefslogtreecommitdiff
path: root/soundbox/pipewire.go
diff options
context:
space:
mode:
authorxegineering <me@xegineering.eu>2024-11-17 12:51:15 +0100
committerxegineering <me@xegineering.eu>2024-12-08 18:22:10 +0100
commit06c4f8b0120f5598f9d179b8c0fea33df35659a8 (patch)
treecd29e3526c5394cd5daeb8da889c9b56ad2873f3 /soundbox/pipewire.go
parent4513eb614707d129824e60270bd45cdee9f04d06 (diff)
downloadsoundbox-go-06c4f8b0120f5598f9d179b8c0fea33df35659a8.tar
soundbox-go-06c4f8b0120f5598f9d179b8c0fea33df35659a8.tar.zst
soundbox-go-06c4f8b0120f5598f9d179b8c0fea33df35659a8.zip
pipewire: Add experimental PipeWire support
This implements a PipeWire capture device which can be used as an input source instead of the already available URL input. Known issues with the current PipeWire support are: - user has to connect the monitor of the default audio sink to the capture device manually - correct shutdown has to be tested - multiple instances do not work - medium code quality requires refactoring Since this is nevertheless usable and possible unknown bugs should be figured out in practise soon this implementation is already added. Bugfixes and refactoring might follow.
Diffstat (limited to 'soundbox/pipewire.go')
-rw-r--r--soundbox/pipewire.go80
1 files changed, 80 insertions, 0 deletions
diff --git a/soundbox/pipewire.go b/soundbox/pipewire.go
new file mode 100644
index 0000000..fbae73b
--- /dev/null
+++ b/soundbox/pipewire.go
@@ -0,0 +1,80 @@
+package soundbox
+
+/*
+#cgo pkg-config: libpipewire-0.3
+#include "pipewire-binding.h"
+*/
+import "C"
+
+import (
+ "bytes"
+ "context"
+ "io"
+ "net"
+ "log"
+ "os/exec"
+ "unsafe"
+)
+
+var pipewireAudio = make(chan []byte, 5)
+
+func StreamPipewireContext(ctx context.Context, targets []net.HardwareAddr) error {
+ cmd := exec.CommandContext(
+ ctx,
+ "ffmpeg",
+ "-ac",
+ "2",
+ "-ar",
+ "48000",
+ "-f",
+ "s16le",
+ "-channel_layout",
+ "stereo",
+ "-i",
+ "-",
+ "-acodec",
+ "flac",
+ "-f",
+ "ogg",
+ "-",
+ )
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ return err
+ }
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ return err
+ }
+
+ go C.pw_stdout()
+
+ go func() {
+ for buffer := range pipewireAudio {
+ tempReader := bytes.NewReader(buffer)
+ _, err := io.Copy(stdin, tempReader)
+ if err != nil {
+ log.Println("Failed to copy from PipeWire to ffmpeg.")
+ break
+ }
+ }
+ }()
+
+ err = cmd.Start()
+ if err != nil {
+ return err
+ }
+
+ err = streamContext(ctx, stdout, targets)
+ if err != nil {
+ return err
+ }
+
+ return cmd.Wait()
+}
+
+//export goHandleData
+func goHandleData(data *C.int16_t, size C.size_t) {
+ buf := C.GoBytes(unsafe.Pointer(data), C.int(size))
+ pipewireAudio <- buf
+}