fix: finalize player cleanup follow-ups
- commit
- c41bf8c3e15fab59f0da8d4c84fe73a642fb19fa
- author
- brice · · 2026-04-10 04:07 UTC
- parent
- 8a75379
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
6 files · +80 -58
M cmd/pipewiregen/internal/emitter/emitter_test.go +31 -14
| @@ -157,21 +157,38 @@ func testCleanupModel() *model.Model { | |||
| 157 | 157 | // TestEmitGeneratesCleanupBindings verifies that cleanup bindings are generated. | |
| 158 | 158 | // This test ensures pw_main_loop_quit and pw_stream_destroy are present in generated files. | |
| 159 | 159 | func TestEmitGeneratesCleanupBindings(t *testing.T) { | |
| 160 | - | // Load the actual pipewire.json from the project root | |
| 161 | - | root, err := filepath.Abs("../../../..") | |
| 162 | - | if err != nil { | |
| 163 | - | t.Fatalf("failed to get project root: %v", err) | |
| 164 | - | } | |
| 165 | - | ||
| 166 | - | actualModel, err := parser.Load(filepath.Join(root, "gen", "pipewire.json")) | |
| 167 | - | if err != nil { | |
| 168 | - | t.Fatalf("failed to load pipewire.json: %v", err) | |
| 169 | - | } | |
| 160 | + | t.Run("unit model", func(t *testing.T) { | |
| 161 | + | paths, err := Emit(testCleanupModel(), t.TempDir()) | |
| 162 | + | if err != nil { | |
| 163 | + | t.Fatalf("Emit returned error: %v", err) | |
| 164 | + | } | |
| 165 | + | ||
| 166 | + | assertCleanupBindings(t, paths) | |
| 167 | + | }) | |
| 168 | + | ||
| 169 | + | t.Run("checked in model", func(t *testing.T) { | |
| 170 | + | // Load the actual pipewire.json from the project root | |
| 171 | + | root, err := filepath.Abs("../../../..") | |
| 172 | + | if err != nil { | |
| 173 | + | t.Fatalf("failed to get project root: %v", err) | |
| 174 | + | } | |
| 175 | + | ||
| 176 | + | actualModel, err := parser.Load(filepath.Join(root, "gen", "pipewire.json")) | |
| 177 | + | if err != nil { | |
| 178 | + | t.Fatalf("failed to load pipewire.json: %v", err) | |
| 179 | + | } | |
| 180 | + | ||
| 181 | + | paths, err := Emit(actualModel, t.TempDir()) | |
| 182 | + | if err != nil { | |
| 183 | + | t.Fatalf("Emit returned error: %v", err) | |
| 184 | + | } | |
| 185 | + | ||
| 186 | + | assertCleanupBindings(t, paths) | |
| 187 | + | }) | |
| 188 | + | } | |
| 170 | 189 | ||
| 171 | - | paths, err := Emit(actualModel, t.TempDir()) | |
| 172 | - | if err != nil { | |
| 173 | - | t.Fatalf("Emit returned error: %v", err) | |
| 174 | - | } | |
| 190 | + | func assertCleanupBindings(t *testing.T, paths map[string][]byte) { | |
| 191 | + | t.Helper() | |
| 175 | 192 | ||
| 176 | 193 | // Verify loop_gen.go contains pw_main_loop_quit | |
| 177 | 194 | loopCapiContent := string(paths["internal/capi/loop_gen.go"]) | |
| @@ -157,21 +157,38 @@ func testCleanupModel() *model.Model { | |||||
| 157 | // TestEmitGeneratesCleanupBindings verifies that cleanup bindings are generated. | 157 | // TestEmitGeneratesCleanupBindings verifies that cleanup bindings are generated. | ||
| 158 | // This test ensures pw_main_loop_quit and pw_stream_destroy are present in generated files. | 158 | // This test ensures pw_main_loop_quit and pw_stream_destroy are present in generated files. | ||
| 159 | func TestEmitGeneratesCleanupBindings(t *testing.T) { | 159 | func TestEmitGeneratesCleanupBindings(t *testing.T) { | ||
| 160 | - | // Load the actual pipewire.json from the project root | 160 | + | t.Run("unit model", func(t *testing.T) { |
| 161 | - | root, err := filepath.Abs("../../../..") | 161 | + | paths, err := Emit(testCleanupModel(), t.TempDir()) |
| 162 | - | if err != nil { | 162 | + | if err != nil { |
| 163 | - | t.Fatalf("failed to get project root: %v", err) | 163 | + | t.Fatalf("Emit returned error: %v", err) |
| 164 | - | } | 164 | + | } |
| 165 | - | 165 | + | ||
| 166 | - | actualModel, err := parser.Load(filepath.Join(root, "gen", "pipewire.json")) | 166 | + | assertCleanupBindings(t, paths) |
| 167 | - | if err != nil { | 167 | + | }) |
| 168 | - | t.Fatalf("failed to load pipewire.json: %v", err) | 168 | + | |
| 169 | - | } | 169 | + | t.Run("checked in model", func(t *testing.T) { |
| 170 | + | // Load the actual pipewire.json from the project root | |||
| 171 | + | root, err := filepath.Abs("../../../..") | |||
| 172 | + | if err != nil { | |||
| 173 | + | t.Fatalf("failed to get project root: %v", err) | |||
| 174 | + | } | |||
| 175 | + | ||||
| 176 | + | actualModel, err := parser.Load(filepath.Join(root, "gen", "pipewire.json")) | |||
| 177 | + | if err != nil { | |||
| 178 | + | t.Fatalf("failed to load pipewire.json: %v", err) | |||
| 179 | + | } | |||
| 180 | + | ||||
| 181 | + | paths, err := Emit(actualModel, t.TempDir()) | |||
| 182 | + | if err != nil { | |||
| 183 | + | t.Fatalf("Emit returned error: %v", err) | |||
| 184 | + | } | |||
| 185 | + | ||||
| 186 | + | assertCleanupBindings(t, paths) | |||
| 187 | + | }) | |||
| 188 | + | } | |||
| 170 | 189 | ||||
| 171 | - | paths, err := Emit(actualModel, t.TempDir()) | 190 | + | func assertCleanupBindings(t *testing.T, paths map[string][]byte) { |
| 172 | - | if err != nil { | 191 | + | t.Helper() |
| 173 | - | t.Fatalf("Emit returned error: %v", err) | |||
| 174 | - | } | |||
| 175 | 192 | ||||
| 176 | // Verify loop_gen.go contains pw_main_loop_quit | 193 | // Verify loop_gen.go contains pw_main_loop_quit | ||
| 177 | loopCapiContent := string(paths["internal/capi/loop_gen.go"]) | 194 | loopCapiContent := string(paths["internal/capi/loop_gen.go"]) | ||
M internal/capi/stream_ops.go +13 -3
| @@ -15,6 +15,14 @@ var ( | |||
| 15 | 15 | errMainLoopCreate = errors.New("pw_main_loop_new returned nil") | |
| 16 | 16 | ) | |
| 17 | 17 | ||
| 18 | + | const pwVersionStreamEvents = 2 | |
| 19 | + | ||
| 20 | + | const ( | |
| 21 | + | pwDirectionOutput = 1 | |
| 22 | + | pwIDAny = 0xffffffff | |
| 23 | + | pwStreamFlagAutoConnectMapBuffers = 0x05 | |
| 24 | + | ) | |
| 25 | + | ||
| 18 | 26 | // streamCallbackStorage keeps the pw_stream_events struct and its | |
| 19 | 27 | // associated Go callback alive for the lifetime of the stream. | |
| 20 | 28 | // Without this, the stack-allocated values in CreatePlaybackStream | |
| @@ -34,7 +42,7 @@ type streamOpsImpl struct { | |||
| 34 | 42 | // Verify interface compliance at compile time. | |
| 35 | 43 | var _ portout.StreamOps = (*streamOpsImpl)(nil) | |
| 36 | 44 | ||
| 37 | - | func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (unsafe.Pointer, error) { | |
| 45 | + | func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, onProcess func()) (unsafe.Pointer, error) { | |
| 38 | 46 | nameBytes := append([]byte(name), 0) | |
| 39 | 47 | ||
| 40 | 48 | // Build persistent callback storage that outlives this function. | |
| @@ -43,7 +51,7 @@ func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string | |||
| 43 | 51 | onProcess() | |
| 44 | 52 | } | |
| 45 | 53 | storage.events = pw_stream_events{ | |
| 46 | - | version: 0, // PW_VERSION_STREAM_EVENTS | |
| 54 | + | version: pwVersionStreamEvents, | |
| 47 | 55 | process: &storage.processCb, | |
| 48 | 56 | } | |
| 49 | 57 | ||
| @@ -72,7 +80,7 @@ func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string | |||
| 72 | 80 | func (s *streamOpsImpl) ConnectPlaybackStream(streamPtr unsafe.Pointer) error { | |
| 73 | 81 | // PW_DIRECTION_OUTPUT = 1, PW_ID_ANY = 0xffffffff | |
| 74 | 82 | // PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS = 0x01 | 0x04 | |
| 75 | - | ret := pw_stream_connect(streamPtr, 1, 0xffffffff, 0x05, nil, 0) | |
| 83 | + | ret := pw_stream_connect(streamPtr, pwDirectionOutput, pwIDAny, pwStreamFlagAutoConnectMapBuffers, nil, 0) | |
| 76 | 84 | if ret < 0 { | |
| 77 | 85 | return errStreamConnect | |
| 78 | 86 | } | |
| @@ -99,6 +107,8 @@ func (s *streamOpsImpl) QueueBuffer(streamPtr unsafe.Pointer, bufPtr unsafe.Poin | |||
| 99 | 107 | return nil | |
| 100 | 108 | } | |
| 101 | 109 | ||
| 110 | + | // DisconnectStream intentionally ignores the PipeWire return code. | |
| 111 | + | // Close-path cleanup is best-effort here, and destroy is the definitive release. | |
| 102 | 112 | func (s *streamOpsImpl) DisconnectStream(streamPtr unsafe.Pointer) { | |
| 103 | 113 | pw_stream_disconnect(streamPtr) | |
| 104 | 114 | } | |
| @@ -15,6 +15,14 @@ var ( | |||||
| 15 | errMainLoopCreate = errors.New("pw_main_loop_new returned nil") | 15 | errMainLoopCreate = errors.New("pw_main_loop_new returned nil") | ||
| 16 | ) | 16 | ) | ||
| 17 | 17 | ||||
| 18 | + | const pwVersionStreamEvents = 2 | |||
| 19 | + | ||||
| 20 | + | const ( | |||
| 21 | + | pwDirectionOutput = 1 | |||
| 22 | + | pwIDAny = 0xffffffff | |||
| 23 | + | pwStreamFlagAutoConnectMapBuffers = 0x05 | |||
| 24 | + | ) | |||
| 25 | + | ||||
| 18 | // streamCallbackStorage keeps the pw_stream_events struct and its | 26 | // streamCallbackStorage keeps the pw_stream_events struct and its | ||
| 19 | // associated Go callback alive for the lifetime of the stream. | 27 | // associated Go callback alive for the lifetime of the stream. | ||
| 20 | // Without this, the stack-allocated values in CreatePlaybackStream | 28 | // Without this, the stack-allocated values in CreatePlaybackStream | ||
| @@ -34,7 +42,7 @@ type streamOpsImpl struct { | |||||
| 34 | // Verify interface compliance at compile time. | 42 | // Verify interface compliance at compile time. | ||
| 35 | var _ portout.StreamOps = (*streamOpsImpl)(nil) | 43 | var _ portout.StreamOps = (*streamOpsImpl)(nil) | ||
| 36 | 44 | ||||
| 37 | - | func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (unsafe.Pointer, error) { | 45 | + | func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, onProcess func()) (unsafe.Pointer, error) { |
| 38 | nameBytes := append([]byte(name), 0) | 46 | nameBytes := append([]byte(name), 0) | ||
| 39 | 47 | ||||
| 40 | // Build persistent callback storage that outlives this function. | 48 | // Build persistent callback storage that outlives this function. | ||
| @@ -43,7 +51,7 @@ func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string | |||||
| 43 | onProcess() | 51 | onProcess() | ||
| 44 | } | 52 | } | ||
| 45 | storage.events = pw_stream_events{ | 53 | storage.events = pw_stream_events{ | ||
| 46 | - | version: 0, // PW_VERSION_STREAM_EVENTS | 54 | + | version: pwVersionStreamEvents, |
| 47 | process: &storage.processCb, | 55 | process: &storage.processCb, | ||
| 48 | } | 56 | } | ||
| 49 | 57 | ||||
| @@ -72,7 +80,7 @@ func (s *streamOpsImpl) CreatePlaybackStream(loopPtr unsafe.Pointer, name string | |||||
| 72 | func (s *streamOpsImpl) ConnectPlaybackStream(streamPtr unsafe.Pointer) error { | 80 | func (s *streamOpsImpl) ConnectPlaybackStream(streamPtr unsafe.Pointer) error { | ||
| 73 | // PW_DIRECTION_OUTPUT = 1, PW_ID_ANY = 0xffffffff | 81 | // PW_DIRECTION_OUTPUT = 1, PW_ID_ANY = 0xffffffff | ||
| 74 | // PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS = 0x01 | 0x04 | 82 | // PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS = 0x01 | 0x04 | ||
| 75 | - | ret := pw_stream_connect(streamPtr, 1, 0xffffffff, 0x05, nil, 0) | 83 | + | ret := pw_stream_connect(streamPtr, pwDirectionOutput, pwIDAny, pwStreamFlagAutoConnectMapBuffers, nil, 0) |
| 76 | if ret < 0 { | 84 | if ret < 0 { | ||
| 77 | return errStreamConnect | 85 | return errStreamConnect | ||
| 78 | } | 86 | } | ||
| @@ -99,6 +107,8 @@ func (s *streamOpsImpl) QueueBuffer(streamPtr unsafe.Pointer, bufPtr unsafe.Poin | |||||
| 99 | return nil | 107 | return nil | ||
| 100 | } | 108 | } | ||
| 101 | 109 | ||||
| 110 | + | // DisconnectStream intentionally ignores the PipeWire return code. | |||
| 111 | + | // Close-path cleanup is best-effort here, and destroy is the definitive release. | |||
| 102 | func (s *streamOpsImpl) DisconnectStream(streamPtr unsafe.Pointer) { | 112 | func (s *streamOpsImpl) DisconnectStream(streamPtr unsafe.Pointer) { | ||
| 103 | pw_stream_disconnect(streamPtr) | 113 | pw_stream_disconnect(streamPtr) | ||
| 104 | } | 114 | } | ||
M internal/core/player.go +21 -10
| @@ -207,30 +207,41 @@ func (p *player) setPaused(paused bool) { | |||
| 207 | 207 | // deactivateStream deactivates the stream via StreamOps. | |
| 208 | 208 | // Returns an error if deactivation fails. No-op when streamOps is nil. | |
| 209 | 209 | func (p *player) deactivateStream() error { | |
| 210 | - | if p.streamOps == nil || p.streamPtr == nil { | |
| 210 | + | p.mu.Lock() | |
| 211 | + | streamOps := p.streamOps | |
| 212 | + | streamPtr := p.streamPtr | |
| 213 | + | p.mu.Unlock() | |
| 214 | + | ||
| 215 | + | if streamOps == nil || streamPtr == nil { | |
| 211 | 216 | return nil | |
| 212 | 217 | } | |
| 213 | - | return p.streamOps.SetStreamActive(p.streamPtr, false) | |
| 218 | + | return streamOps.SetStreamActive(streamPtr, false) | |
| 214 | 219 | } | |
| 215 | 220 | ||
| 216 | 221 | // teardown releases player-owned stream and main-loop resources through | |
| 217 | 222 | // StreamOps. Safe to call when fields are nil or on repeated invocation. | |
| 218 | 223 | func (p *player) teardown() { | |
| 219 | - | if p.streamOps == nil { | |
| 224 | + | p.mu.Lock() | |
| 225 | + | streamOps := p.streamOps | |
| 226 | + | streamPtr := p.streamPtr | |
| 227 | + | loopPtr := p.loopPtr | |
| 228 | + | p.streamPtr = nil | |
| 229 | + | p.loopPtr = nil | |
| 230 | + | p.mu.Unlock() | |
| 231 | + | ||
| 232 | + | if streamOps == nil { | |
| 220 | 233 | return | |
| 221 | 234 | } | |
| 222 | 235 | ||
| 223 | 236 | // Destroy stream first (it depends on the loop). | |
| 224 | - | if p.streamPtr != nil { | |
| 225 | - | p.streamOps.DestroyStream(p.streamPtr) | |
| 226 | - | p.streamPtr = nil | |
| 237 | + | if streamPtr != nil { | |
| 238 | + | streamOps.DestroyStream(streamPtr) | |
| 227 | 239 | } | |
| 228 | 240 | ||
| 229 | 241 | // Quit then destroy the main loop. | |
| 230 | - | if p.loopPtr != nil { | |
| 231 | - | p.streamOps.QuitMainLoop(p.loopPtr) | |
| 232 | - | p.streamOps.DestroyMainLoop(p.loopPtr) | |
| 233 | - | p.loopPtr = nil | |
| 242 | + | if loopPtr != nil { | |
| 243 | + | streamOps.QuitMainLoop(loopPtr) | |
| 244 | + | streamOps.DestroyMainLoop(loopPtr) | |
| 234 | 245 | } | |
| 235 | 246 | } | |
| 236 | 247 | ||
| @@ -207,30 +207,41 @@ func (p *player) setPaused(paused bool) { | |||||
| 207 | // deactivateStream deactivates the stream via StreamOps. | 207 | // deactivateStream deactivates the stream via StreamOps. | ||
| 208 | // Returns an error if deactivation fails. No-op when streamOps is nil. | 208 | // Returns an error if deactivation fails. No-op when streamOps is nil. | ||
| 209 | func (p *player) deactivateStream() error { | 209 | func (p *player) deactivateStream() error { | ||
| 210 | - | if p.streamOps == nil || p.streamPtr == nil { | 210 | + | p.mu.Lock() |
| 211 | + | streamOps := p.streamOps | |||
| 212 | + | streamPtr := p.streamPtr | |||
| 213 | + | p.mu.Unlock() | |||
| 214 | + | ||||
| 215 | + | if streamOps == nil || streamPtr == nil { | |||
| 211 | return nil | 216 | return nil | ||
| 212 | } | 217 | } | ||
| 213 | - | return p.streamOps.SetStreamActive(p.streamPtr, false) | 218 | + | return streamOps.SetStreamActive(streamPtr, false) |
| 214 | } | 219 | } | ||
| 215 | 220 | ||||
| 216 | // teardown releases player-owned stream and main-loop resources through | 221 | // teardown releases player-owned stream and main-loop resources through | ||
| 217 | // StreamOps. Safe to call when fields are nil or on repeated invocation. | 222 | // StreamOps. Safe to call when fields are nil or on repeated invocation. | ||
| 218 | func (p *player) teardown() { | 223 | func (p *player) teardown() { | ||
| 219 | - | if p.streamOps == nil { | 224 | + | p.mu.Lock() |
| 225 | + | streamOps := p.streamOps | |||
| 226 | + | streamPtr := p.streamPtr | |||
| 227 | + | loopPtr := p.loopPtr | |||
| 228 | + | p.streamPtr = nil | |||
| 229 | + | p.loopPtr = nil | |||
| 230 | + | p.mu.Unlock() | |||
| 231 | + | ||||
| 232 | + | if streamOps == nil { | |||
| 220 | return | 233 | return | ||
| 221 | } | 234 | } | ||
| 222 | 235 | ||||
| 223 | // Destroy stream first (it depends on the loop). | 236 | // Destroy stream first (it depends on the loop). | ||
| 224 | - | if p.streamPtr != nil { | 237 | + | if streamPtr != nil { |
| 225 | - | p.streamOps.DestroyStream(p.streamPtr) | 238 | + | streamOps.DestroyStream(streamPtr) |
| 226 | - | p.streamPtr = nil | |||
| 227 | } | 239 | } | ||
| 228 | 240 | ||||
| 229 | // Quit then destroy the main loop. | 241 | // Quit then destroy the main loop. | ||
| 230 | - | if p.loopPtr != nil { | 242 | + | if loopPtr != nil { |
| 231 | - | p.streamOps.QuitMainLoop(p.loopPtr) | 243 | + | streamOps.QuitMainLoop(loopPtr) |
| 232 | - | p.streamOps.DestroyMainLoop(p.loopPtr) | 244 | + | streamOps.DestroyMainLoop(loopPtr) |
| 233 | - | p.loopPtr = nil | |||
| 234 | } | 245 | } | ||
| 235 | } | 246 | } | ||
| 236 | 247 | ||||
M internal/core/player_test.go +0 -4
| @@ -6,7 +6,6 @@ import ( | |||
| 6 | 6 | "unsafe" | |
| 7 | 7 | ||
| 8 | 8 | "github.com/bnema/purego-pipewire/internal/ports/out/mocks" | |
| 9 | - | "github.com/stretchr/testify/mock" | |
| 10 | 9 | ) | |
| 11 | 10 | ||
| 12 | 11 | func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) { | |
| @@ -369,6 +368,3 @@ func TestPlayerTeardownWithOnlyLoopPtr(t *testing.T) { | |||
| 369 | 368 | t.Error("expected loopPtr to be nil after teardown") | |
| 370 | 369 | } | |
| 371 | 370 | } | |
| 372 | - | ||
| 373 | - | // Ensure mock.Mock is referenced to satisfy the import. | |
| 374 | - | var _ mock.TestingT = (*testing.T)(nil) | |
| @@ -6,7 +6,6 @@ import ( | |||||
| 6 | "unsafe" | 6 | "unsafe" | ||
| 7 | 7 | ||||
| 8 | "github.com/bnema/purego-pipewire/internal/ports/out/mocks" | 8 | "github.com/bnema/purego-pipewire/internal/ports/out/mocks" | ||
| 9 | - | "github.com/stretchr/testify/mock" | |||
| 10 | ) | 9 | ) | ||
| 11 | 10 | ||||
| 12 | func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) { | 11 | func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) { | ||
| @@ -369,6 +368,3 @@ func TestPlayerTeardownWithOnlyLoopPtr(t *testing.T) { | |||||
| 369 | t.Error("expected loopPtr to be nil after teardown") | 368 | t.Error("expected loopPtr to be nil after teardown") | ||
| 370 | } | 369 | } | ||
| 371 | } | 370 | } | ||
| 372 | - | ||||
| 373 | - | // Ensure mock.Mock is referenced to satisfy the import. | |||
| 374 | - | var _ mock.TestingT = (*testing.T)(nil) | |||
M internal/ports/out/mocks/mock_StreamOps.go +14 -26
| @@ -142,8 +142,8 @@ func (_c *MockStreamOps_CreateMainLoop_Call) RunAndReturn(run func() (unsafe.Poi | |||
| 142 | 142 | } | |
| 143 | 143 | ||
| 144 | 144 | // CreatePlaybackStream provides a mock function for the type MockStreamOps | |
| 145 | - | func (_mock *MockStreamOps) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (unsafe.Pointer, error) { | |
| 146 | - | ret := _mock.Called(loopPtr, name, sampleRate, channels, onProcess) | |
| 145 | + | func (_mock *MockStreamOps) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, onProcess func()) (unsafe.Pointer, error) { | |
| 146 | + | ret := _mock.Called(loopPtr, name, onProcess) | |
| 147 | 147 | ||
| 148 | 148 | if len(ret) == 0 { | |
| 149 | 149 | panic("no return value specified for CreatePlaybackStream") | |
| @@ -151,16 +151,16 @@ func (_mock *MockStreamOps) CreatePlaybackStream(loopPtr unsafe.Pointer, name st | |||
| 151 | 151 | ||
| 152 | 152 | var r0 unsafe.Pointer | |
| 153 | 153 | var r1 error | |
| 154 | - | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, int, int, func()) (unsafe.Pointer, error)); ok { | |
| 155 | - | return returnFunc(loopPtr, name, sampleRate, channels, onProcess) | |
| 154 | + | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, func()) (unsafe.Pointer, error)); ok { | |
| 155 | + | return returnFunc(loopPtr, name, onProcess) | |
| 156 | 156 | } | |
| 157 | - | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, int, int, func()) unsafe.Pointer); ok { | |
| 158 | - | r0 = returnFunc(loopPtr, name, sampleRate, channels, onProcess) | |
| 157 | + | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, func()) unsafe.Pointer); ok { | |
| 158 | + | r0 = returnFunc(loopPtr, name, onProcess) | |
| 159 | 159 | } else { | |
| 160 | 160 | r0 = ret.Get(0).(unsafe.Pointer) | |
| 161 | 161 | } | |
| 162 | - | if returnFunc, ok := ret.Get(1).(func(unsafe.Pointer, string, int, int, func()) error); ok { | |
| 163 | - | r1 = returnFunc(loopPtr, name, sampleRate, channels, onProcess) | |
| 162 | + | if returnFunc, ok := ret.Get(1).(func(unsafe.Pointer, string, func()) error); ok { | |
| 163 | + | r1 = returnFunc(loopPtr, name, onProcess) | |
| 164 | 164 | } else { | |
| 165 | 165 | r1 = ret.Error(1) | |
| 166 | 166 | } | |
| @@ -175,14 +175,12 @@ type MockStreamOps_CreatePlaybackStream_Call struct { | |||
| 175 | 175 | // CreatePlaybackStream is a helper method to define mock.On call | |
| 176 | 176 | // - loopPtr unsafe.Pointer | |
| 177 | 177 | // - name string | |
| 178 | - | // - sampleRate int | |
| 179 | - | // - channels int | |
| 180 | 178 | // - onProcess func() | |
| 181 | - | func (_e *MockStreamOps_Expecter) CreatePlaybackStream(loopPtr interface{}, name interface{}, sampleRate interface{}, channels interface{}, onProcess interface{}) *MockStreamOps_CreatePlaybackStream_Call { | |
| 182 | - | return &MockStreamOps_CreatePlaybackStream_Call{Call: _e.mock.On("CreatePlaybackStream", loopPtr, name, sampleRate, channels, onProcess)} | |
| 179 | + | func (_e *MockStreamOps_Expecter) CreatePlaybackStream(loopPtr interface{}, name interface{}, onProcess interface{}) *MockStreamOps_CreatePlaybackStream_Call { | |
| 180 | + | return &MockStreamOps_CreatePlaybackStream_Call{Call: _e.mock.On("CreatePlaybackStream", loopPtr, name, onProcess)} | |
| 183 | 181 | } | |
| 184 | 182 | ||
| 185 | - | func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func())) *MockStreamOps_CreatePlaybackStream_Call { | |
| 183 | + | func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.Pointer, name string, onProcess func())) *MockStreamOps_CreatePlaybackStream_Call { | |
| 186 | 184 | _c.Call.Run(func(args mock.Arguments) { | |
| 187 | 185 | var arg0 unsafe.Pointer | |
| 188 | 186 | if args[0] != nil { | |
| @@ -192,24 +190,14 @@ func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.P | |||
| 192 | 190 | if args[1] != nil { | |
| 193 | 191 | arg1 = args[1].(string) | |
| 194 | 192 | } | |
| 195 | - | var arg2 int | |
| 193 | + | var arg2 func() | |
| 196 | 194 | if args[2] != nil { | |
| 197 | - | arg2 = args[2].(int) | |
| 198 | - | } | |
| 199 | - | var arg3 int | |
| 200 | - | if args[3] != nil { | |
| 201 | - | arg3 = args[3].(int) | |
| 202 | - | } | |
| 203 | - | var arg4 func() | |
| 204 | - | if args[4] != nil { | |
| 205 | - | arg4 = args[4].(func()) | |
| 195 | + | arg2 = args[2].(func()) | |
| 206 | 196 | } | |
| 207 | 197 | run( | |
| 208 | 198 | arg0, | |
| 209 | 199 | arg1, | |
| 210 | 200 | arg2, | |
| 211 | - | arg3, | |
| 212 | - | arg4, | |
| 213 | 201 | ) | |
| 214 | 202 | }) | |
| 215 | 203 | return _c | |
| @@ -220,7 +208,7 @@ func (_c *MockStreamOps_CreatePlaybackStream_Call) Return(streamPtr unsafe.Point | |||
| 220 | 208 | return _c | |
| 221 | 209 | } | |
| 222 | 210 | ||
| 223 | - | func (_c *MockStreamOps_CreatePlaybackStream_Call) RunAndReturn(run func(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (unsafe.Pointer, error)) *MockStreamOps_CreatePlaybackStream_Call { | |
| 211 | + | func (_c *MockStreamOps_CreatePlaybackStream_Call) RunAndReturn(run func(loopPtr unsafe.Pointer, name string, onProcess func()) (unsafe.Pointer, error)) *MockStreamOps_CreatePlaybackStream_Call { | |
| 224 | 212 | _c.Call.Return(run) | |
| 225 | 213 | return _c | |
| 226 | 214 | } | |
| @@ -142,8 +142,8 @@ func (_c *MockStreamOps_CreateMainLoop_Call) RunAndReturn(run func() (unsafe.Poi | |||||
| 142 | } | 142 | } | ||
| 143 | 143 | ||||
| 144 | // CreatePlaybackStream provides a mock function for the type MockStreamOps | 144 | // CreatePlaybackStream provides a mock function for the type MockStreamOps | ||
| 145 | - | func (_mock *MockStreamOps) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (unsafe.Pointer, error) { | 145 | + | func (_mock *MockStreamOps) CreatePlaybackStream(loopPtr unsafe.Pointer, name string, onProcess func()) (unsafe.Pointer, error) { |
| 146 | - | ret := _mock.Called(loopPtr, name, sampleRate, channels, onProcess) | 146 | + | ret := _mock.Called(loopPtr, name, onProcess) |
| 147 | 147 | ||||
| 148 | if len(ret) == 0 { | 148 | if len(ret) == 0 { | ||
| 149 | panic("no return value specified for CreatePlaybackStream") | 149 | panic("no return value specified for CreatePlaybackStream") | ||
| @@ -151,16 +151,16 @@ func (_mock *MockStreamOps) CreatePlaybackStream(loopPtr unsafe.Pointer, name st | |||||
| 151 | 151 | ||||
| 152 | var r0 unsafe.Pointer | 152 | var r0 unsafe.Pointer | ||
| 153 | var r1 error | 153 | var r1 error | ||
| 154 | - | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, int, int, func()) (unsafe.Pointer, error)); ok { | 154 | + | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, func()) (unsafe.Pointer, error)); ok { |
| 155 | - | return returnFunc(loopPtr, name, sampleRate, channels, onProcess) | 155 | + | return returnFunc(loopPtr, name, onProcess) |
| 156 | } | 156 | } | ||
| 157 | - | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, int, int, func()) unsafe.Pointer); ok { | 157 | + | if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, string, func()) unsafe.Pointer); ok { |
| 158 | - | r0 = returnFunc(loopPtr, name, sampleRate, channels, onProcess) | 158 | + | r0 = returnFunc(loopPtr, name, onProcess) |
| 159 | } else { | 159 | } else { | ||
| 160 | r0 = ret.Get(0).(unsafe.Pointer) | 160 | r0 = ret.Get(0).(unsafe.Pointer) | ||
| 161 | } | 161 | } | ||
| 162 | - | if returnFunc, ok := ret.Get(1).(func(unsafe.Pointer, string, int, int, func()) error); ok { | 162 | + | if returnFunc, ok := ret.Get(1).(func(unsafe.Pointer, string, func()) error); ok { |
| 163 | - | r1 = returnFunc(loopPtr, name, sampleRate, channels, onProcess) | 163 | + | r1 = returnFunc(loopPtr, name, onProcess) |
| 164 | } else { | 164 | } else { | ||
| 165 | r1 = ret.Error(1) | 165 | r1 = ret.Error(1) | ||
| 166 | } | 166 | } | ||
| @@ -175,14 +175,12 @@ type MockStreamOps_CreatePlaybackStream_Call struct { | |||||
| 175 | // CreatePlaybackStream is a helper method to define mock.On call | 175 | // CreatePlaybackStream is a helper method to define mock.On call | ||
| 176 | // - loopPtr unsafe.Pointer | 176 | // - loopPtr unsafe.Pointer | ||
| 177 | // - name string | 177 | // - name string | ||
| 178 | - | // - sampleRate int | |||
| 179 | - | // - channels int | |||
| 180 | // - onProcess func() | 178 | // - onProcess func() | ||
| 181 | - | func (_e *MockStreamOps_Expecter) CreatePlaybackStream(loopPtr interface{}, name interface{}, sampleRate interface{}, channels interface{}, onProcess interface{}) *MockStreamOps_CreatePlaybackStream_Call { | 179 | + | func (_e *MockStreamOps_Expecter) CreatePlaybackStream(loopPtr interface{}, name interface{}, onProcess interface{}) *MockStreamOps_CreatePlaybackStream_Call { |
| 182 | - | return &MockStreamOps_CreatePlaybackStream_Call{Call: _e.mock.On("CreatePlaybackStream", loopPtr, name, sampleRate, channels, onProcess)} | 180 | + | return &MockStreamOps_CreatePlaybackStream_Call{Call: _e.mock.On("CreatePlaybackStream", loopPtr, name, onProcess)} |
| 183 | } | 181 | } | ||
| 184 | 182 | ||||
| 185 | - | func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func())) *MockStreamOps_CreatePlaybackStream_Call { | 183 | + | func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.Pointer, name string, onProcess func())) *MockStreamOps_CreatePlaybackStream_Call { |
| 186 | _c.Call.Run(func(args mock.Arguments) { | 184 | _c.Call.Run(func(args mock.Arguments) { | ||
| 187 | var arg0 unsafe.Pointer | 185 | var arg0 unsafe.Pointer | ||
| 188 | if args[0] != nil { | 186 | if args[0] != nil { | ||
| @@ -192,24 +190,14 @@ func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.P | |||||
| 192 | if args[1] != nil { | 190 | if args[1] != nil { | ||
| 193 | arg1 = args[1].(string) | 191 | arg1 = args[1].(string) | ||
| 194 | } | 192 | } | ||
| 195 | - | var arg2 int | 193 | + | var arg2 func() |
| 196 | if args[2] != nil { | 194 | if args[2] != nil { | ||
| 197 | - | arg2 = args[2].(int) | 195 | + | arg2 = args[2].(func()) |
| 198 | - | } | |||
| 199 | - | var arg3 int | |||
| 200 | - | if args[3] != nil { | |||
| 201 | - | arg3 = args[3].(int) | |||
| 202 | - | } | |||
| 203 | - | var arg4 func() | |||
| 204 | - | if args[4] != nil { | |||
| 205 | - | arg4 = args[4].(func()) | |||
| 206 | } | 196 | } | ||
| 207 | run( | 197 | run( | ||
| 208 | arg0, | 198 | arg0, | ||
| 209 | arg1, | 199 | arg1, | ||
| 210 | arg2, | 200 | arg2, | ||
| 211 | - | arg3, | |||
| 212 | - | arg4, | |||
| 213 | ) | 201 | ) | ||
| 214 | }) | 202 | }) | ||
| 215 | return _c | 203 | return _c | ||
| @@ -220,7 +208,7 @@ func (_c *MockStreamOps_CreatePlaybackStream_Call) Return(streamPtr unsafe.Point | |||||
| 220 | return _c | 208 | return _c | ||
| 221 | } | 209 | } | ||
| 222 | 210 | ||||
| 223 | - | func (_c *MockStreamOps_CreatePlaybackStream_Call) RunAndReturn(run func(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (unsafe.Pointer, error)) *MockStreamOps_CreatePlaybackStream_Call { | 211 | + | func (_c *MockStreamOps_CreatePlaybackStream_Call) RunAndReturn(run func(loopPtr unsafe.Pointer, name string, onProcess func()) (unsafe.Pointer, error)) *MockStreamOps_CreatePlaybackStream_Call { |
| 224 | _c.Call.Return(run) | 212 | _c.Call.Return(run) | ||
| 225 | return _c | 213 | return _c | ||
| 226 | } | 214 | } | ||
M internal/ports/out/stream_ops.go +1 -1
| @@ -9,7 +9,7 @@ type StreamOps interface { | |||
| 9 | 9 | // CreatePlaybackStream creates a new playback stream attached to the given | |
| 10 | 10 | // main loop. The onProcess callback is invoked by PipeWire each time the | |
| 11 | 11 | // stream needs more audio data. Returns the stream pointer or an error. | |
| 12 | - | CreatePlaybackStream(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (streamPtr unsafe.Pointer, err error) | |
| 12 | + | CreatePlaybackStream(loopPtr unsafe.Pointer, name string, onProcess func()) (streamPtr unsafe.Pointer, err error) | |
| 13 | 13 | ||
| 14 | 14 | // ConnectPlaybackStream connects the stream for playback output. | |
| 15 | 15 | ConnectPlaybackStream(streamPtr unsafe.Pointer) error | |
| @@ -9,7 +9,7 @@ type StreamOps interface { | |||||
| 9 | // CreatePlaybackStream creates a new playback stream attached to the given | 9 | // CreatePlaybackStream creates a new playback stream attached to the given | ||
| 10 | // main loop. The onProcess callback is invoked by PipeWire each time the | 10 | // main loop. The onProcess callback is invoked by PipeWire each time the | ||
| 11 | // stream needs more audio data. Returns the stream pointer or an error. | 11 | // stream needs more audio data. Returns the stream pointer or an error. | ||
| 12 | - | CreatePlaybackStream(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func()) (streamPtr unsafe.Pointer, err error) | 12 | + | CreatePlaybackStream(loopPtr unsafe.Pointer, name string, onProcess func()) (streamPtr unsafe.Pointer, err error) |
| 13 | 13 | ||||
| 14 | // ConnectPlaybackStream connects the stream for playback output. | 14 | // ConnectPlaybackStream connects the stream for playback output. | ||
| 15 | ConnectPlaybackStream(streamPtr unsafe.Pointer) error | 15 | ConnectPlaybackStream(streamPtr unsafe.Pointer) error | ||