detached 7618928

fix: wire player cleanup through stream ops

commit
7618928a869eb695a145faf26ad4a929059e0e11
author
brice · · 2026-04-10 03:40 UTC
parent
2e65b39
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
6 files · +828 -35
M .mockery.yml +1 -0
@@ -15,6 +15,7 @@ packages:
1515 CAPI:
1616 InitAPI:
1717 LoopAPI:
18+ StreamOps:
1819 github.com/bnema/purego-pipewire/pipewire:
1920 config:
2021 all: false
@@ -15,6 +15,7 @@ packages:
15 CAPI:15 CAPI:
16 InitAPI:16 InitAPI:
17 LoopAPI:17 LoopAPI:
18+ StreamOps:
18 github.com/bnema/purego-pipewire/pipewire:19 github.com/bnema/purego-pipewire/pipewire:
19 config:20 config:
20 all: false21 all: false
M internal/capi/stream_ops.go +4 -8
@@ -118,9 +118,8 @@ func (s *streamOpsImpl) DestroyStream(streamPtr unsafe.Pointer) {
118118 delete(s.pinned, streamPtr)
119119 s.mu.Unlock()
120120
121- // pw_stream_destroy is not in the generated bindings yet;
122- // disconnect is the safe fallback to release the stream.
123- pw_stream_disconnect(streamPtr)
121+ // Use the generated pw_stream_destroy binding for proper cleanup.
122+ pw_stream_destroy(streamPtr)
124123 }
125124
126125 func (s *streamOpsImpl) CreateMainLoop() (unsafe.Pointer, error) {
@@ -136,11 +135,8 @@ func (s *streamOpsImpl) RunMainLoop(loopPtr unsafe.Pointer) {
136135 }
137136
138137 func (s *streamOpsImpl) QuitMainLoop(loopPtr unsafe.Pointer) {
139- // pw_main_loop_quit is not in the generated bindings yet.
140- // This is a placeholder — the main loop will exit when the
141- // stream is disconnected or the process is terminated.
142- //
143- // TODO: Add pw_main_loop_quit to gen/pipewire.json and regenerate.
138+ // Use the generated pw_main_loop_quit binding to signal loop exit.
139+ pw_main_loop_quit(loopPtr)
144140 }
145141
146142 func (s *streamOpsImpl) DestroyMainLoop(loopPtr unsafe.Pointer) {
@@ -118,9 +118,8 @@ func (s *streamOpsImpl) DestroyStream(streamPtr unsafe.Pointer) {
118 delete(s.pinned, streamPtr)118 delete(s.pinned, streamPtr)
119 s.mu.Unlock()119 s.mu.Unlock()
120 120
121- // pw_stream_destroy is not in the generated bindings yet;121+ // Use the generated pw_stream_destroy binding for proper cleanup.
122- // disconnect is the safe fallback to release the stream.122+ pw_stream_destroy(streamPtr)
123- pw_stream_disconnect(streamPtr)
124 }123 }
125 124
126 func (s *streamOpsImpl) CreateMainLoop() (unsafe.Pointer, error) {125 func (s *streamOpsImpl) CreateMainLoop() (unsafe.Pointer, error) {
@@ -136,11 +135,8 @@ func (s *streamOpsImpl) RunMainLoop(loopPtr unsafe.Pointer) {
136 }135 }
137 136
138 func (s *streamOpsImpl) QuitMainLoop(loopPtr unsafe.Pointer) {137 func (s *streamOpsImpl) QuitMainLoop(loopPtr unsafe.Pointer) {
139- // pw_main_loop_quit is not in the generated bindings yet.138+ // Use the generated pw_main_loop_quit binding to signal loop exit.
140- // This is a placeholder — the main loop will exit when the139+ pw_main_loop_quit(loopPtr)
141- // stream is disconnected or the process is terminated.
142- //
143- // TODO: Add pw_main_loop_quit to gen/pipewire.json and regenerate.
144 }140 }
145 141
146 func (s *streamOpsImpl) DestroyMainLoop(loopPtr unsafe.Pointer) {142 func (s *streamOpsImpl) DestroyMainLoop(loopPtr unsafe.Pointer) {
A internal/capi/stream_ops_test.go +100 -0
@@ -0,0 +1,100 @@
1+package capi
2+
3+import (
4+ "testing"
5+ "unsafe"
6+)
7+
8+// TestDestroyStreamCallsPwStreamDestroy verifies that DestroyStream delegates
9+// to the generated pw_stream_destroy binding (not pw_stream_disconnect).
10+func TestDestroyStreamCallsPwStreamDestroy(t *testing.T) {
11+ // Save and restore the package-level function var.
12+ origDestroy := pw_stream_destroy
13+ t.Cleanup(func() { pw_stream_destroy = origDestroy })
14+
15+ var called bool
16+ var receivedPtr unsafe.Pointer
17+ pw_stream_destroy = func(stream unsafe.Pointer) {
18+ called = true
19+ receivedPtr = stream
20+ }
21+
22+ ops := &streamOpsImpl{
23+ pinned: make(map[unsafe.Pointer]*streamCallbackStorage),
24+ destroyed: make(map[unsafe.Pointer]bool),
25+ }
26+
27+ fakePtr := unsafe.Pointer(uintptr(0x1234))
28+ ops.pinned[fakePtr] = &streamCallbackStorage{}
29+
30+ ops.DestroyStream(fakePtr)
31+
32+ if !called {
33+ t.Fatal("expected pw_stream_destroy to be called")
34+ }
35+ if receivedPtr != fakePtr {
36+ t.Fatalf("pw_stream_destroy received %v, want %v", receivedPtr, fakePtr)
37+ }
38+
39+ // Verify internal bookkeeping.
40+ if !ops.destroyed[fakePtr] {
41+ t.Error("expected stream to be marked as destroyed")
42+ }
43+ if _, exists := ops.pinned[fakePtr]; exists {
44+ t.Error("expected callback storage to be unpinned after destroy")
45+ }
46+}
47+
48+// TestDestroyStreamDoubleDestroySkipsSecondCall verifies idempotency:
49+// a second DestroyStream on the same pointer does NOT call pw_stream_destroy again.
50+func TestDestroyStreamDoubleDestroySkipsSecondCall(t *testing.T) {
51+ origDestroy := pw_stream_destroy
52+ t.Cleanup(func() { pw_stream_destroy = origDestroy })
53+
54+ callCount := 0
55+ pw_stream_destroy = func(_ unsafe.Pointer) {
56+ callCount++
57+ }
58+
59+ ops := &streamOpsImpl{
60+ pinned: make(map[unsafe.Pointer]*streamCallbackStorage),
61+ destroyed: make(map[unsafe.Pointer]bool),
62+ }
63+
64+ fakePtr := unsafe.Pointer(uintptr(0xABCD))
65+ ops.pinned[fakePtr] = &streamCallbackStorage{}
66+
67+ ops.DestroyStream(fakePtr)
68+ ops.DestroyStream(fakePtr)
69+
70+ if callCount != 1 {
71+ t.Fatalf("pw_stream_destroy called %d times, want 1", callCount)
72+ }
73+}
74+
75+// TestQuitMainLoopCallsPwMainLoopQuit verifies that QuitMainLoop delegates
76+// to the generated pw_main_loop_quit binding.
77+func TestQuitMainLoopCallsPwMainLoopQuit(t *testing.T) {
78+ origQuit := pw_main_loop_quit
79+ t.Cleanup(func() { pw_main_loop_quit = origQuit })
80+
81+ var called bool
82+ var receivedPtr unsafe.Pointer
83+ pw_main_loop_quit = func(loop unsafe.Pointer) int32 {
84+ called = true
85+ receivedPtr = loop
86+ return 0
87+ }
88+
89+ ops := &streamOpsImpl{}
90+ fakeLoop := unsafe.Pointer(uintptr(0x5678))
91+
92+ ops.QuitMainLoop(fakeLoop)
93+
94+ if !called {
95+ t.Fatal("expected pw_main_loop_quit to be called")
96+ }
97+ if receivedPtr != fakeLoop {
98+ t.Fatalf("pw_main_loop_quit received %v, want %v", receivedPtr, fakeLoop)
99+ }
100+}
@@ -0,0 +1,100 @@
1+package capi
2+
3+import (
4+ "testing"
5+ "unsafe"
6+)
7+
8+// TestDestroyStreamCallsPwStreamDestroy verifies that DestroyStream delegates
9+// to the generated pw_stream_destroy binding (not pw_stream_disconnect).
10+func TestDestroyStreamCallsPwStreamDestroy(t *testing.T) {
11+ // Save and restore the package-level function var.
12+ origDestroy := pw_stream_destroy
13+ t.Cleanup(func() { pw_stream_destroy = origDestroy })
14+
15+ var called bool
16+ var receivedPtr unsafe.Pointer
17+ pw_stream_destroy = func(stream unsafe.Pointer) {
18+ called = true
19+ receivedPtr = stream
20+ }
21+
22+ ops := &streamOpsImpl{
23+ pinned: make(map[unsafe.Pointer]*streamCallbackStorage),
24+ destroyed: make(map[unsafe.Pointer]bool),
25+ }
26+
27+ fakePtr := unsafe.Pointer(uintptr(0x1234))
28+ ops.pinned[fakePtr] = &streamCallbackStorage{}
29+
30+ ops.DestroyStream(fakePtr)
31+
32+ if !called {
33+ t.Fatal("expected pw_stream_destroy to be called")
34+ }
35+ if receivedPtr != fakePtr {
36+ t.Fatalf("pw_stream_destroy received %v, want %v", receivedPtr, fakePtr)
37+ }
38+
39+ // Verify internal bookkeeping.
40+ if !ops.destroyed[fakePtr] {
41+ t.Error("expected stream to be marked as destroyed")
42+ }
43+ if _, exists := ops.pinned[fakePtr]; exists {
44+ t.Error("expected callback storage to be unpinned after destroy")
45+ }
46+}
47+
48+// TestDestroyStreamDoubleDestroySkipsSecondCall verifies idempotency:
49+// a second DestroyStream on the same pointer does NOT call pw_stream_destroy again.
50+func TestDestroyStreamDoubleDestroySkipsSecondCall(t *testing.T) {
51+ origDestroy := pw_stream_destroy
52+ t.Cleanup(func() { pw_stream_destroy = origDestroy })
53+
54+ callCount := 0
55+ pw_stream_destroy = func(_ unsafe.Pointer) {
56+ callCount++
57+ }
58+
59+ ops := &streamOpsImpl{
60+ pinned: make(map[unsafe.Pointer]*streamCallbackStorage),
61+ destroyed: make(map[unsafe.Pointer]bool),
62+ }
63+
64+ fakePtr := unsafe.Pointer(uintptr(0xABCD))
65+ ops.pinned[fakePtr] = &streamCallbackStorage{}
66+
67+ ops.DestroyStream(fakePtr)
68+ ops.DestroyStream(fakePtr)
69+
70+ if callCount != 1 {
71+ t.Fatalf("pw_stream_destroy called %d times, want 1", callCount)
72+ }
73+}
74+
75+// TestQuitMainLoopCallsPwMainLoopQuit verifies that QuitMainLoop delegates
76+// to the generated pw_main_loop_quit binding.
77+func TestQuitMainLoopCallsPwMainLoopQuit(t *testing.T) {
78+ origQuit := pw_main_loop_quit
79+ t.Cleanup(func() { pw_main_loop_quit = origQuit })
80+
81+ var called bool
82+ var receivedPtr unsafe.Pointer
83+ pw_main_loop_quit = func(loop unsafe.Pointer) int32 {
84+ called = true
85+ receivedPtr = loop
86+ return 0
87+ }
88+
89+ ops := &streamOpsImpl{}
90+ fakeLoop := unsafe.Pointer(uintptr(0x5678))
91+
92+ ops.QuitMainLoop(fakeLoop)
93+
94+ if !called {
95+ t.Fatal("expected pw_main_loop_quit to be called")
96+ }
97+ if receivedPtr != fakeLoop {
98+ t.Fatalf("pw_main_loop_quit received %v, want %v", receivedPtr, fakeLoop)
99+ }
100+}
M internal/core/player.go +22 -7
@@ -4,6 +4,9 @@ import (
44 "errors"
55 "sync"
66 "sync/atomic"
7+ "unsafe"
8+
9+ portout "github.com/bnema/purego-pipewire/internal/ports/out"
710 )
811
912 var (
@@ -18,6 +21,11 @@ type player struct {
1821 state atomic.Int32
1922 paused atomic.Bool
2023 mu sync.Mutex
24+
25+ // Stream cleanup fields — nil when no stream is active.
26+ streamOps portout.StreamOps
27+ streamPtr unsafe.Pointer
28+ loopPtr unsafe.Pointer
2129 }
2230
2331 // newPlayer creates a new player instance
@@ -139,6 +147,7 @@ func (p *player) Pause() error {
139147 }
140148
141149 // Stop stops playback but allows restart.
150+// Returns an error if stream deactivation fails, leaving the state unchanged.
142151 func (p *player) Stop() error {
143152 current := p.State()
144153 if current == PlayerStateClosed || current == PlayerStateClosing {
@@ -150,11 +159,13 @@ func (p *player) Stop() error {
150159 return ErrInvalidPlayerState
151160 }
152161
153- // Clear paused flag
154- p.setPaused(false)
162+ // Deactivate stream - if this fails, return the error and don't transition
163+ if err := p.deactivateStream(); err != nil {
164+ return err
165+ }
155166
156- // Deactivate stream (placeholder)
157- p.deactivateStream()
167+ // Clear paused flag only after successful deactivation
168+ p.setPaused(false)
158169
159170 return p.transition(PlayerStateStopped)
160171 }
@@ -193,9 +204,13 @@ func (p *player) setPaused(paused bool) {
193204 p.paused.Store(paused)
194205 }
195206
196-// deactivateStream deactivates the stream (placeholder)
197-func (p *player) deactivateStream() {
198- // Minimal placeholder - will be implemented in future tasks
207+// deactivateStream deactivates the stream via StreamOps.
208+// Returns an error if deactivation fails. No-op when streamOps is nil.
209+func (p *player) deactivateStream() error {
210+ if p.streamOps == nil || p.streamPtr == nil {
211+ return nil
212+ }
213+ return p.streamOps.SetStreamActive(p.streamPtr, false)
199214 }
200215
201216 // teardown performs cleanup (placeholder)
@@ -4,6 +4,9 @@ import (
4 "errors"4 "errors"
5 "sync"5 "sync"
6 "sync/atomic"6 "sync/atomic"
7+ "unsafe"
8+
9+ portout "github.com/bnema/purego-pipewire/internal/ports/out"
7 )10 )
8 11
9 var (12 var (
@@ -18,6 +21,11 @@ type player struct {
18 state atomic.Int3221 state atomic.Int32
19 paused atomic.Bool22 paused atomic.Bool
20 mu sync.Mutex23 mu sync.Mutex
24+
25+ // Stream cleanup fields — nil when no stream is active.
26+ streamOps portout.StreamOps
27+ streamPtr unsafe.Pointer
28+ loopPtr unsafe.Pointer
21 }29 }
22 30
23 // newPlayer creates a new player instance31 // newPlayer creates a new player instance
@@ -139,6 +147,7 @@ func (p *player) Pause() error {
139 }147 }
140 148
141 // Stop stops playback but allows restart.149 // Stop stops playback but allows restart.
150+// Returns an error if stream deactivation fails, leaving the state unchanged.
142 func (p *player) Stop() error {151 func (p *player) Stop() error {
143 current := p.State()152 current := p.State()
144 if current == PlayerStateClosed || current == PlayerStateClosing {153 if current == PlayerStateClosed || current == PlayerStateClosing {
@@ -150,11 +159,13 @@ func (p *player) Stop() error {
150 return ErrInvalidPlayerState159 return ErrInvalidPlayerState
151 }160 }
152 161
153- // Clear paused flag162+ // Deactivate stream - if this fails, return the error and don't transition
154- p.setPaused(false)163+ if err := p.deactivateStream(); err != nil {
164+ return err
165+ }
155 166
156- // Deactivate stream (placeholder)167+ // Clear paused flag only after successful deactivation
157- p.deactivateStream()168+ p.setPaused(false)
158 169
159 return p.transition(PlayerStateStopped)170 return p.transition(PlayerStateStopped)
160 }171 }
@@ -193,9 +204,13 @@ func (p *player) setPaused(paused bool) {
193 p.paused.Store(paused)204 p.paused.Store(paused)
194 }205 }
195 206
196-// deactivateStream deactivates the stream (placeholder)207+// deactivateStream deactivates the stream via StreamOps.
197-func (p *player) deactivateStream() {208+// Returns an error if deactivation fails. No-op when streamOps is nil.
198- // Minimal placeholder - will be implemented in future tasks209+func (p *player) deactivateStream() error {
210+ if p.streamOps == nil || p.streamPtr == nil {
211+ return nil
212+ }
213+ return p.streamOps.SetStreamActive(p.streamPtr, false)
199 }214 }
200 215
201 // teardown performs cleanup (placeholder)216 // teardown performs cleanup (placeholder)
M internal/core/player_test.go +110 -20
@@ -3,22 +3,26 @@ package core
33 import (
44 "errors"
55 "testing"
6+ "unsafe"
7+
8+ "github.com/bnema/purego-pipewire/internal/ports/out/mocks"
9+ "github.com/stretchr/testify/mock"
610 )
711
812 func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
913 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
10-
14+
1115 // Start from Stopped state should work
1216 p.setState(PlayerStateStopped)
1317 if err := p.Start(); err != nil {
1418 t.Fatalf("Start from Stopped failed: %v", err)
1519 }
16-
20+
1721 // Should be in Playing state after Start
1822 if p.State() != PlayerStatePlaying {
1923 t.Fatalf("expected Playing state after Start, got %v", p.State())
2024 }
21-
25+
2226 // Stop should transition to Stopped
2327 if err := p.Stop(); err != nil {
2428 t.Fatalf("Stop failed: %v", err)
@@ -26,7 +30,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
2630 if p.State() != PlayerStateStopped {
2731 t.Fatalf("expected Stopped state after Stop, got %v", p.State())
2832 }
29-
33+
3034 // Start from Stopped should work again (restartable)
3135 if err := p.Start(); err != nil {
3236 t.Fatalf("Start from Stopped (restart) failed: %v", err)
@@ -34,7 +38,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
3438 if p.State() != PlayerStatePlaying {
3539 t.Fatalf("expected Playing state after restart, got %v", p.State())
3640 }
37-
41+
3842 // Close should transition to Closed
3943 if err := p.Close(); err != nil {
4044 t.Fatalf("Close failed: %v", err)
@@ -42,7 +46,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
4246 if p.State() != PlayerStateClosed {
4347 t.Fatalf("expected Closed state after Close, got %v", p.State())
4448 }
45-
49+
4650 // Start from Closed should fail (terminal)
4751 if err := p.Start(); err == nil {
4852 t.Fatal("expected error starting from Closed state, got nil")
@@ -52,7 +56,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
5256 func TestPlayerStartFromClosedReturnsError(t *testing.T) {
5357 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
5458 p.setState(PlayerStateClosed)
55-
59+
5660 err := p.Start()
5761 if err == nil {
5862 t.Fatal("expected error starting from Closed state, got nil")
@@ -65,7 +69,7 @@ func TestPlayerStartFromClosedReturnsError(t *testing.T) {
6569 func TestPlayerStartFromClosingReturnsError(t *testing.T) {
6670 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
6771 p.setState(PlayerStateClosing)
68-
72+
6973 err := p.Start()
7074 if err == nil {
7175 t.Fatal("expected error starting from Closing state, got nil")
@@ -77,17 +81,17 @@ func TestPlayerStartFromClosingReturnsError(t *testing.T) {
7781
7882 func TestPlayerStartTransitionsThroughStartingToPlaying(t *testing.T) {
7983 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
80-
84+
8185 // Initial state should be Idle
8286 if p.State() != PlayerStateIdle {
8387 t.Fatalf("expected initial state Idle, got %v", p.State())
8488 }
85-
89+
8690 // Start should transition to Playing
8791 if err := p.Start(); err != nil {
8892 t.Fatalf("Start failed: %v", err)
8993 }
90-
94+
9195 if p.State() != PlayerStatePlaying {
9296 t.Fatalf("expected Playing state after Start, got %v", p.State())
9397 }
@@ -95,17 +99,17 @@ func TestPlayerStartTransitionsThroughStartingToPlaying(t *testing.T) {
9599
96100 func TestPlayerPauseTransitionsToPaused(t *testing.T) {
97101 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
98-
102+
99103 // Start first
100104 if err := p.Start(); err != nil {
101105 t.Fatalf("Start failed: %v", err)
102106 }
103-
107+
104108 // Pause should transition to Paused
105109 if err := p.Pause(); err != nil {
106110 t.Fatalf("Pause failed: %v", err)
107111 }
108-
112+
109113 if p.State() != PlayerStatePaused {
110114 t.Fatalf("expected Paused state after Pause, got %v", p.State())
111115 }
@@ -113,7 +117,7 @@ func TestPlayerPauseTransitionsToPaused(t *testing.T) {
113117
114118 func TestPlayerStopClearsPausedState(t *testing.T) {
115119 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
116-
120+
117121 // Start then pause
118122 if err := p.Start(); err != nil {
119123 t.Fatalf("Start failed: %v", err)
@@ -124,12 +128,12 @@ func TestPlayerStopClearsPausedState(t *testing.T) {
124128 if p.State() != PlayerStatePaused {
125129 t.Fatalf("expected Paused state, got %v", p.State())
126130 }
127-
131+
128132 // Stop should transition to Stopped (clearing paused state)
129133 if err := p.Stop(); err != nil {
130134 t.Fatalf("Stop failed: %v", err)
131135 }
132-
136+
133137 if p.State() != PlayerStateStopped {
134138 t.Fatalf("expected Stopped state after Stop, got %v", p.State())
135139 }
@@ -137,12 +141,12 @@ func TestPlayerStopClearsPausedState(t *testing.T) {
137141
138142 func TestPlayerCloseIsIdempotent(t *testing.T) {
139143 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
140-
144+
141145 // Start first
142146 if err := p.Start(); err != nil {
143147 t.Fatalf("Start failed: %v", err)
144148 }
145-
149+
146150 // Close should work
147151 if err := p.Close(); err != nil {
148152 t.Fatalf("first Close failed: %v", err)
@@ -150,7 +154,7 @@ func TestPlayerCloseIsIdempotent(t *testing.T) {
150154 if p.State() != PlayerStateClosed {
151155 t.Fatalf("expected Closed state, got %v", p.State())
152156 }
153-
157+
154158 // Second close should also succeed (idempotent)
155159 if err := p.Close(); err != nil {
156160 t.Fatalf("second Close failed: %v", err)
@@ -159,3 +163,89 @@ func TestPlayerCloseIsIdempotent(t *testing.T) {
159163 t.Fatalf("expected Closed state after second close, got %v", p.State())
160164 }
161165 }
166+
167+// TestPlayerStopDeactivatesStream verifies that Stop() calls
168+// SetStreamActive(false) via StreamOps and transitions to Stopped.
169+func TestPlayerStopDeactivatesStream(t *testing.T) {
170+ mockOps := mocks.NewMockStreamOps(t)
171+ fakeStream := unsafe.Pointer(uintptr(0x1234))
172+
173+ mockOps.EXPECT().SetStreamActive(fakeStream, false).Return(nil)
174+
175+ p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
176+ p.streamOps = mockOps
177+ p.streamPtr = fakeStream
178+
179+ // Start the player
180+ if err := p.Start(); err != nil {
181+ t.Fatalf("Start failed: %v", err)
182+ }
183+ if p.State() != PlayerStatePlaying {
184+ t.Fatalf("expected Playing state, got %v", p.State())
185+ }
186+
187+ // Stop should call SetStreamActive(false) and transition to Stopped
188+ if err := p.Stop(); err != nil {
189+ t.Fatalf("Stop failed: %v", err)
190+ }
191+ if p.State() != PlayerStateStopped {
192+ t.Fatalf("expected Stopped state after Stop, got %v", p.State())
193+ }
194+}
195+
196+// TestPlayerStopReturnsDeactivateError verifies that Stop() surfaces the
197+// SetStreamActive error and leaves the player in the pre-stop state.
198+func TestPlayerStopReturnsDeactivateError(t *testing.T) {
199+ mockOps := mocks.NewMockStreamOps(t)
200+ fakeStream := unsafe.Pointer(uintptr(0x5678))
201+ deactivateErr := errors.New("deactivate failed")
202+
203+ mockOps.EXPECT().SetStreamActive(fakeStream, false).Return(deactivateErr)
204+
205+ p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
206+ p.streamOps = mockOps
207+ p.streamPtr = fakeStream
208+
209+ // Start the player
210+ if err := p.Start(); err != nil {
211+ t.Fatalf("Start failed: %v", err)
212+ }
213+ if p.State() != PlayerStatePlaying {
214+ t.Fatalf("expected Playing state, got %v", p.State())
215+ }
216+
217+ // Stop should return the deactivation error
218+ err := p.Stop()
219+ if err == nil {
220+ t.Fatal("expected deactivation error, got nil")
221+ }
222+ if !errors.Is(err, deactivateErr) {
223+ t.Fatalf("expected %v, got %v", deactivateErr, err)
224+ }
225+
226+ // State should remain Playing (not transitioned to Stopped)
227+ if p.State() != PlayerStatePlaying {
228+ t.Fatalf("expected state to remain Playing after failed deactivation, got %v", p.State())
229+ }
230+}
231+
232+// TestPlayerStopWithoutStreamOpsIsNoop verifies that Stop() works
233+// when no StreamOps is configured (backward compat).
234+func TestPlayerStopWithoutStreamOpsIsNoop(t *testing.T) {
235+ p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
236+
237+ if err := p.Start(); err != nil {
238+ t.Fatalf("Start failed: %v", err)
239+ }
240+
241+ // Stop without StreamOps should succeed (deactivation is a no-op)
242+ if err := p.Stop(); err != nil {
243+ t.Fatalf("Stop failed: %v", err)
244+ }
245+ if p.State() != PlayerStateStopped {
246+ t.Fatalf("expected Stopped state, got %v", p.State())
247+ }
248+}
249+
250+// Ensure mock.Mock is referenced to satisfy the import.
251+var _ mock.TestingT = (*testing.T)(nil)
@@ -3,22 +3,26 @@ package core
3 import (3 import (
4 "errors"4 "errors"
5 "testing"5 "testing"
6+ "unsafe"
7+
8+ "github.com/bnema/purego-pipewire/internal/ports/out/mocks"
9+ "github.com/stretchr/testify/mock"
6 )10 )
7 11
8 func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {12 func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
9 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})13 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
10- 14+
11 // Start from Stopped state should work15 // Start from Stopped state should work
12 p.setState(PlayerStateStopped)16 p.setState(PlayerStateStopped)
13 if err := p.Start(); err != nil {17 if err := p.Start(); err != nil {
14 t.Fatalf("Start from Stopped failed: %v", err)18 t.Fatalf("Start from Stopped failed: %v", err)
15 }19 }
16- 20+
17 // Should be in Playing state after Start21 // Should be in Playing state after Start
18 if p.State() != PlayerStatePlaying {22 if p.State() != PlayerStatePlaying {
19 t.Fatalf("expected Playing state after Start, got %v", p.State())23 t.Fatalf("expected Playing state after Start, got %v", p.State())
20 }24 }
21- 25+
22 // Stop should transition to Stopped26 // Stop should transition to Stopped
23 if err := p.Stop(); err != nil {27 if err := p.Stop(); err != nil {
24 t.Fatalf("Stop failed: %v", err)28 t.Fatalf("Stop failed: %v", err)
@@ -26,7 +30,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
26 if p.State() != PlayerStateStopped {30 if p.State() != PlayerStateStopped {
27 t.Fatalf("expected Stopped state after Stop, got %v", p.State())31 t.Fatalf("expected Stopped state after Stop, got %v", p.State())
28 }32 }
29- 33+
30 // Start from Stopped should work again (restartable)34 // Start from Stopped should work again (restartable)
31 if err := p.Start(); err != nil {35 if err := p.Start(); err != nil {
32 t.Fatalf("Start from Stopped (restart) failed: %v", err)36 t.Fatalf("Start from Stopped (restart) failed: %v", err)
@@ -34,7 +38,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
34 if p.State() != PlayerStatePlaying {38 if p.State() != PlayerStatePlaying {
35 t.Fatalf("expected Playing state after restart, got %v", p.State())39 t.Fatalf("expected Playing state after restart, got %v", p.State())
36 }40 }
37- 41+
38 // Close should transition to Closed42 // Close should transition to Closed
39 if err := p.Close(); err != nil {43 if err := p.Close(); err != nil {
40 t.Fatalf("Close failed: %v", err)44 t.Fatalf("Close failed: %v", err)
@@ -42,7 +46,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
42 if p.State() != PlayerStateClosed {46 if p.State() != PlayerStateClosed {
43 t.Fatalf("expected Closed state after Close, got %v", p.State())47 t.Fatalf("expected Closed state after Close, got %v", p.State())
44 }48 }
45- 49+
46 // Start from Closed should fail (terminal)50 // Start from Closed should fail (terminal)
47 if err := p.Start(); err == nil {51 if err := p.Start(); err == nil {
48 t.Fatal("expected error starting from Closed state, got nil")52 t.Fatal("expected error starting from Closed state, got nil")
@@ -52,7 +56,7 @@ func TestPlayerStopIsRestartableButCloseIsTerminal(t *testing.T) {
52 func TestPlayerStartFromClosedReturnsError(t *testing.T) {56 func TestPlayerStartFromClosedReturnsError(t *testing.T) {
53 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})57 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
54 p.setState(PlayerStateClosed)58 p.setState(PlayerStateClosed)
55- 59+
56 err := p.Start()60 err := p.Start()
57 if err == nil {61 if err == nil {
58 t.Fatal("expected error starting from Closed state, got nil")62 t.Fatal("expected error starting from Closed state, got nil")
@@ -65,7 +69,7 @@ func TestPlayerStartFromClosedReturnsError(t *testing.T) {
65 func TestPlayerStartFromClosingReturnsError(t *testing.T) {69 func TestPlayerStartFromClosingReturnsError(t *testing.T) {
66 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})70 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
67 p.setState(PlayerStateClosing)71 p.setState(PlayerStateClosing)
68- 72+
69 err := p.Start()73 err := p.Start()
70 if err == nil {74 if err == nil {
71 t.Fatal("expected error starting from Closing state, got nil")75 t.Fatal("expected error starting from Closing state, got nil")
@@ -77,17 +81,17 @@ func TestPlayerStartFromClosingReturnsError(t *testing.T) {
77 81
78 func TestPlayerStartTransitionsThroughStartingToPlaying(t *testing.T) {82 func TestPlayerStartTransitionsThroughStartingToPlaying(t *testing.T) {
79 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})83 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
80- 84+
81 // Initial state should be Idle85 // Initial state should be Idle
82 if p.State() != PlayerStateIdle {86 if p.State() != PlayerStateIdle {
83 t.Fatalf("expected initial state Idle, got %v", p.State())87 t.Fatalf("expected initial state Idle, got %v", p.State())
84 }88 }
85- 89+
86 // Start should transition to Playing90 // Start should transition to Playing
87 if err := p.Start(); err != nil {91 if err := p.Start(); err != nil {
88 t.Fatalf("Start failed: %v", err)92 t.Fatalf("Start failed: %v", err)
89 }93 }
90- 94+
91 if p.State() != PlayerStatePlaying {95 if p.State() != PlayerStatePlaying {
92 t.Fatalf("expected Playing state after Start, got %v", p.State())96 t.Fatalf("expected Playing state after Start, got %v", p.State())
93 }97 }
@@ -95,17 +99,17 @@ func TestPlayerStartTransitionsThroughStartingToPlaying(t *testing.T) {
95 99
96 func TestPlayerPauseTransitionsToPaused(t *testing.T) {100 func TestPlayerPauseTransitionsToPaused(t *testing.T) {
97 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})101 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
98- 102+
99 // Start first103 // Start first
100 if err := p.Start(); err != nil {104 if err := p.Start(); err != nil {
101 t.Fatalf("Start failed: %v", err)105 t.Fatalf("Start failed: %v", err)
102 }106 }
103- 107+
104 // Pause should transition to Paused108 // Pause should transition to Paused
105 if err := p.Pause(); err != nil {109 if err := p.Pause(); err != nil {
106 t.Fatalf("Pause failed: %v", err)110 t.Fatalf("Pause failed: %v", err)
107 }111 }
108- 112+
109 if p.State() != PlayerStatePaused {113 if p.State() != PlayerStatePaused {
110 t.Fatalf("expected Paused state after Pause, got %v", p.State())114 t.Fatalf("expected Paused state after Pause, got %v", p.State())
111 }115 }
@@ -113,7 +117,7 @@ func TestPlayerPauseTransitionsToPaused(t *testing.T) {
113 117
114 func TestPlayerStopClearsPausedState(t *testing.T) {118 func TestPlayerStopClearsPausedState(t *testing.T) {
115 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})119 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
116- 120+
117 // Start then pause121 // Start then pause
118 if err := p.Start(); err != nil {122 if err := p.Start(); err != nil {
119 t.Fatalf("Start failed: %v", err)123 t.Fatalf("Start failed: %v", err)
@@ -124,12 +128,12 @@ func TestPlayerStopClearsPausedState(t *testing.T) {
124 if p.State() != PlayerStatePaused {128 if p.State() != PlayerStatePaused {
125 t.Fatalf("expected Paused state, got %v", p.State())129 t.Fatalf("expected Paused state, got %v", p.State())
126 }130 }
127- 131+
128 // Stop should transition to Stopped (clearing paused state)132 // Stop should transition to Stopped (clearing paused state)
129 if err := p.Stop(); err != nil {133 if err := p.Stop(); err != nil {
130 t.Fatalf("Stop failed: %v", err)134 t.Fatalf("Stop failed: %v", err)
131 }135 }
132- 136+
133 if p.State() != PlayerStateStopped {137 if p.State() != PlayerStateStopped {
134 t.Fatalf("expected Stopped state after Stop, got %v", p.State())138 t.Fatalf("expected Stopped state after Stop, got %v", p.State())
135 }139 }
@@ -137,12 +141,12 @@ func TestPlayerStopClearsPausedState(t *testing.T) {
137 141
138 func TestPlayerCloseIsIdempotent(t *testing.T) {142 func TestPlayerCloseIsIdempotent(t *testing.T) {
139 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})143 p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
140- 144+
141 // Start first145 // Start first
142 if err := p.Start(); err != nil {146 if err := p.Start(); err != nil {
143 t.Fatalf("Start failed: %v", err)147 t.Fatalf("Start failed: %v", err)
144 }148 }
145- 149+
146 // Close should work150 // Close should work
147 if err := p.Close(); err != nil {151 if err := p.Close(); err != nil {
148 t.Fatalf("first Close failed: %v", err)152 t.Fatalf("first Close failed: %v", err)
@@ -150,7 +154,7 @@ func TestPlayerCloseIsIdempotent(t *testing.T) {
150 if p.State() != PlayerStateClosed {154 if p.State() != PlayerStateClosed {
151 t.Fatalf("expected Closed state, got %v", p.State())155 t.Fatalf("expected Closed state, got %v", p.State())
152 }156 }
153- 157+
154 // Second close should also succeed (idempotent)158 // Second close should also succeed (idempotent)
155 if err := p.Close(); err != nil {159 if err := p.Close(); err != nil {
156 t.Fatalf("second Close failed: %v", err)160 t.Fatalf("second Close failed: %v", err)
@@ -159,3 +163,89 @@ func TestPlayerCloseIsIdempotent(t *testing.T) {
159 t.Fatalf("expected Closed state after second close, got %v", p.State())163 t.Fatalf("expected Closed state after second close, got %v", p.State())
160 }164 }
161 }165 }
166+
167+// TestPlayerStopDeactivatesStream verifies that Stop() calls
168+// SetStreamActive(false) via StreamOps and transitions to Stopped.
169+func TestPlayerStopDeactivatesStream(t *testing.T) {
170+ mockOps := mocks.NewMockStreamOps(t)
171+ fakeStream := unsafe.Pointer(uintptr(0x1234))
172+
173+ mockOps.EXPECT().SetStreamActive(fakeStream, false).Return(nil)
174+
175+ p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
176+ p.streamOps = mockOps
177+ p.streamPtr = fakeStream
178+
179+ // Start the player
180+ if err := p.Start(); err != nil {
181+ t.Fatalf("Start failed: %v", err)
182+ }
183+ if p.State() != PlayerStatePlaying {
184+ t.Fatalf("expected Playing state, got %v", p.State())
185+ }
186+
187+ // Stop should call SetStreamActive(false) and transition to Stopped
188+ if err := p.Stop(); err != nil {
189+ t.Fatalf("Stop failed: %v", err)
190+ }
191+ if p.State() != PlayerStateStopped {
192+ t.Fatalf("expected Stopped state after Stop, got %v", p.State())
193+ }
194+}
195+
196+// TestPlayerStopReturnsDeactivateError verifies that Stop() surfaces the
197+// SetStreamActive error and leaves the player in the pre-stop state.
198+func TestPlayerStopReturnsDeactivateError(t *testing.T) {
199+ mockOps := mocks.NewMockStreamOps(t)
200+ fakeStream := unsafe.Pointer(uintptr(0x5678))
201+ deactivateErr := errors.New("deactivate failed")
202+
203+ mockOps.EXPECT().SetStreamActive(fakeStream, false).Return(deactivateErr)
204+
205+ p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
206+ p.streamOps = mockOps
207+ p.streamPtr = fakeStream
208+
209+ // Start the player
210+ if err := p.Start(); err != nil {
211+ t.Fatalf("Start failed: %v", err)
212+ }
213+ if p.State() != PlayerStatePlaying {
214+ t.Fatalf("expected Playing state, got %v", p.State())
215+ }
216+
217+ // Stop should return the deactivation error
218+ err := p.Stop()
219+ if err == nil {
220+ t.Fatal("expected deactivation error, got nil")
221+ }
222+ if !errors.Is(err, deactivateErr) {
223+ t.Fatalf("expected %v, got %v", deactivateErr, err)
224+ }
225+
226+ // State should remain Playing (not transitioned to Stopped)
227+ if p.State() != PlayerStatePlaying {
228+ t.Fatalf("expected state to remain Playing after failed deactivation, got %v", p.State())
229+ }
230+}
231+
232+// TestPlayerStopWithoutStreamOpsIsNoop verifies that Stop() works
233+// when no StreamOps is configured (backward compat).
234+func TestPlayerStopWithoutStreamOpsIsNoop(t *testing.T) {
235+ p := newPlayer(PlayerConfig{}, PlayerCallbacks{})
236+
237+ if err := p.Start(); err != nil {
238+ t.Fatalf("Start failed: %v", err)
239+ }
240+
241+ // Stop without StreamOps should succeed (deactivation is a no-op)
242+ if err := p.Stop(); err != nil {
243+ t.Fatalf("Stop failed: %v", err)
244+ }
245+ if p.State() != PlayerStateStopped {
246+ t.Fatalf("expected Stopped state, got %v", p.State())
247+ }
248+}
249+
250+// Ensure mock.Mock is referenced to satisfy the import.
251+var _ mock.TestingT = (*testing.T)(nil)
A internal/ports/out/mocks/mock_StreamOps.go +591 -0
@@ -0,0 +1,591 @@
1+// Code generated by mockery; DO NOT EDIT.
2+// github.com/vektra/mockery
3+// template: testify
4+
5+package mocks
6+
7+import (
8+ "unsafe"
9+
10+ mock "github.com/stretchr/testify/mock"
11+)
12+
13+// NewMockStreamOps creates a new instance of MockStreamOps. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
14+// The first argument is typically a *testing.T value.
15+func NewMockStreamOps(t interface {
16+ mock.TestingT
17+ Cleanup(func())
18+}) *MockStreamOps {
19+ mock := &MockStreamOps{}
20+ mock.Mock.Test(t)
21+
22+ t.Cleanup(func() { mock.AssertExpectations(t) })
23+
24+ return mock
25+}
26+
27+// MockStreamOps is an autogenerated mock type for the StreamOps type
28+type MockStreamOps struct {
29+ mock.Mock
30+}
31+
32+type MockStreamOps_Expecter struct {
33+ mock *mock.Mock
34+}
35+
36+func (_m *MockStreamOps) EXPECT() *MockStreamOps_Expecter {
37+ return &MockStreamOps_Expecter{mock: &_m.Mock}
38+}
39+
40+// ConnectPlaybackStream provides a mock function for the type MockStreamOps
41+func (_mock *MockStreamOps) ConnectPlaybackStream(streamPtr unsafe.Pointer) error {
42+ ret := _mock.Called(streamPtr)
43+
44+ if len(ret) == 0 {
45+ panic("no return value specified for ConnectPlaybackStream")
46+ }
47+
48+ var r0 error
49+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer) error); ok {
50+ r0 = returnFunc(streamPtr)
51+ } else {
52+ r0 = ret.Error(0)
53+ }
54+ return r0
55+}
56+
57+// MockStreamOps_ConnectPlaybackStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConnectPlaybackStream'
58+type MockStreamOps_ConnectPlaybackStream_Call struct {
59+ *mock.Call
60+}
61+
62+// ConnectPlaybackStream is a helper method to define mock.On call
63+// - streamPtr unsafe.Pointer
64+func (_e *MockStreamOps_Expecter) ConnectPlaybackStream(streamPtr interface{}) *MockStreamOps_ConnectPlaybackStream_Call {
65+ return &MockStreamOps_ConnectPlaybackStream_Call{Call: _e.mock.On("ConnectPlaybackStream", streamPtr)}
66+}
67+
68+func (_c *MockStreamOps_ConnectPlaybackStream_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_ConnectPlaybackStream_Call {
69+ _c.Call.Run(func(args mock.Arguments) {
70+ var arg0 unsafe.Pointer
71+ if args[0] != nil {
72+ arg0 = args[0].(unsafe.Pointer)
73+ }
74+ run(
75+ arg0,
76+ )
77+ })
78+ return _c
79+}
80+
81+func (_c *MockStreamOps_ConnectPlaybackStream_Call) Return(err error) *MockStreamOps_ConnectPlaybackStream_Call {
82+ _c.Call.Return(err)
83+ return _c
84+}
85+
86+func (_c *MockStreamOps_ConnectPlaybackStream_Call) RunAndReturn(run func(streamPtr unsafe.Pointer) error) *MockStreamOps_ConnectPlaybackStream_Call {
87+ _c.Call.Return(run)
88+ return _c
89+}
90+
91+// CreateMainLoop provides a mock function for the type MockStreamOps
92+func (_mock *MockStreamOps) CreateMainLoop() (unsafe.Pointer, error) {
93+ ret := _mock.Called()
94+
95+ if len(ret) == 0 {
96+ panic("no return value specified for CreateMainLoop")
97+ }
98+
99+ var r0 unsafe.Pointer
100+ var r1 error
101+ if returnFunc, ok := ret.Get(0).(func() (unsafe.Pointer, error)); ok {
102+ return returnFunc()
103+ }
104+ if returnFunc, ok := ret.Get(0).(func() unsafe.Pointer); ok {
105+ r0 = returnFunc()
106+ } else {
107+ r0 = ret.Get(0).(unsafe.Pointer)
108+ }
109+ if returnFunc, ok := ret.Get(1).(func() error); ok {
110+ r1 = returnFunc()
111+ } else {
112+ r1 = ret.Error(1)
113+ }
114+ return r0, r1
115+}
116+
117+// MockStreamOps_CreateMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateMainLoop'
118+type MockStreamOps_CreateMainLoop_Call struct {
119+ *mock.Call
120+}
121+
122+// CreateMainLoop is a helper method to define mock.On call
123+func (_e *MockStreamOps_Expecter) CreateMainLoop() *MockStreamOps_CreateMainLoop_Call {
124+ return &MockStreamOps_CreateMainLoop_Call{Call: _e.mock.On("CreateMainLoop")}
125+}
126+
127+func (_c *MockStreamOps_CreateMainLoop_Call) Run(run func()) *MockStreamOps_CreateMainLoop_Call {
128+ _c.Call.Run(func(args mock.Arguments) {
129+ run()
130+ })
131+ return _c
132+}
133+
134+func (_c *MockStreamOps_CreateMainLoop_Call) Return(loopPtr unsafe.Pointer, err error) *MockStreamOps_CreateMainLoop_Call {
135+ _c.Call.Return(loopPtr, err)
136+ return _c
137+}
138+
139+func (_c *MockStreamOps_CreateMainLoop_Call) RunAndReturn(run func() (unsafe.Pointer, error)) *MockStreamOps_CreateMainLoop_Call {
140+ _c.Call.Return(run)
141+ return _c
142+}
143+
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)
147+
148+ if len(ret) == 0 {
149+ panic("no return value specified for CreatePlaybackStream")
150+ }
151+
152+ var r0 unsafe.Pointer
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)
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)
159+ } else {
160+ r0 = ret.Get(0).(unsafe.Pointer)
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)
164+ } else {
165+ r1 = ret.Error(1)
166+ }
167+ return r0, r1
168+}
169+
170+// MockStreamOps_CreatePlaybackStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePlaybackStream'
171+type MockStreamOps_CreatePlaybackStream_Call struct {
172+ *mock.Call
173+}
174+
175+// CreatePlaybackStream is a helper method to define mock.On call
176+// - loopPtr unsafe.Pointer
177+// - name string
178+// - sampleRate int
179+// - channels int
180+// - 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)}
183+}
184+
185+func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func())) *MockStreamOps_CreatePlaybackStream_Call {
186+ _c.Call.Run(func(args mock.Arguments) {
187+ var arg0 unsafe.Pointer
188+ if args[0] != nil {
189+ arg0 = args[0].(unsafe.Pointer)
190+ }
191+ var arg1 string
192+ if args[1] != nil {
193+ arg1 = args[1].(string)
194+ }
195+ var arg2 int
196+ 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())
206+ }
207+ run(
208+ arg0,
209+ arg1,
210+ arg2,
211+ arg3,
212+ arg4,
213+ )
214+ })
215+ return _c
216+}
217+
218+func (_c *MockStreamOps_CreatePlaybackStream_Call) Return(streamPtr unsafe.Pointer, err error) *MockStreamOps_CreatePlaybackStream_Call {
219+ _c.Call.Return(streamPtr, err)
220+ return _c
221+}
222+
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 {
224+ _c.Call.Return(run)
225+ return _c
226+}
227+
228+// DequeueBuffer provides a mock function for the type MockStreamOps
229+func (_mock *MockStreamOps) DequeueBuffer(streamPtr unsafe.Pointer) unsafe.Pointer {
230+ ret := _mock.Called(streamPtr)
231+
232+ if len(ret) == 0 {
233+ panic("no return value specified for DequeueBuffer")
234+ }
235+
236+ var r0 unsafe.Pointer
237+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer) unsafe.Pointer); ok {
238+ r0 = returnFunc(streamPtr)
239+ } else {
240+ r0 = ret.Get(0).(unsafe.Pointer)
241+ }
242+ return r0
243+}
244+
245+// MockStreamOps_DequeueBuffer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DequeueBuffer'
246+type MockStreamOps_DequeueBuffer_Call struct {
247+ *mock.Call
248+}
249+
250+// DequeueBuffer is a helper method to define mock.On call
251+// - streamPtr unsafe.Pointer
252+func (_e *MockStreamOps_Expecter) DequeueBuffer(streamPtr interface{}) *MockStreamOps_DequeueBuffer_Call {
253+ return &MockStreamOps_DequeueBuffer_Call{Call: _e.mock.On("DequeueBuffer", streamPtr)}
254+}
255+
256+func (_c *MockStreamOps_DequeueBuffer_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DequeueBuffer_Call {
257+ _c.Call.Run(func(args mock.Arguments) {
258+ var arg0 unsafe.Pointer
259+ if args[0] != nil {
260+ arg0 = args[0].(unsafe.Pointer)
261+ }
262+ run(
263+ arg0,
264+ )
265+ })
266+ return _c
267+}
268+
269+func (_c *MockStreamOps_DequeueBuffer_Call) Return(v unsafe.Pointer) *MockStreamOps_DequeueBuffer_Call {
270+ _c.Call.Return(v)
271+ return _c
272+}
273+
274+func (_c *MockStreamOps_DequeueBuffer_Call) RunAndReturn(run func(streamPtr unsafe.Pointer) unsafe.Pointer) *MockStreamOps_DequeueBuffer_Call {
275+ _c.Call.Return(run)
276+ return _c
277+}
278+
279+// DestroyMainLoop provides a mock function for the type MockStreamOps
280+func (_mock *MockStreamOps) DestroyMainLoop(loopPtr unsafe.Pointer) {
281+ _mock.Called(loopPtr)
282+ return
283+}
284+
285+// MockStreamOps_DestroyMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DestroyMainLoop'
286+type MockStreamOps_DestroyMainLoop_Call struct {
287+ *mock.Call
288+}
289+
290+// DestroyMainLoop is a helper method to define mock.On call
291+// - loopPtr unsafe.Pointer
292+func (_e *MockStreamOps_Expecter) DestroyMainLoop(loopPtr interface{}) *MockStreamOps_DestroyMainLoop_Call {
293+ return &MockStreamOps_DestroyMainLoop_Call{Call: _e.mock.On("DestroyMainLoop", loopPtr)}
294+}
295+
296+func (_c *MockStreamOps_DestroyMainLoop_Call) Run(run func(loopPtr unsafe.Pointer)) *MockStreamOps_DestroyMainLoop_Call {
297+ _c.Call.Run(func(args mock.Arguments) {
298+ var arg0 unsafe.Pointer
299+ if args[0] != nil {
300+ arg0 = args[0].(unsafe.Pointer)
301+ }
302+ run(
303+ arg0,
304+ )
305+ })
306+ return _c
307+}
308+
309+func (_c *MockStreamOps_DestroyMainLoop_Call) Return() *MockStreamOps_DestroyMainLoop_Call {
310+ _c.Call.Return()
311+ return _c
312+}
313+
314+func (_c *MockStreamOps_DestroyMainLoop_Call) RunAndReturn(run func(loopPtr unsafe.Pointer)) *MockStreamOps_DestroyMainLoop_Call {
315+ _c.Run(run)
316+ return _c
317+}
318+
319+// DestroyStream provides a mock function for the type MockStreamOps
320+func (_mock *MockStreamOps) DestroyStream(streamPtr unsafe.Pointer) {
321+ _mock.Called(streamPtr)
322+ return
323+}
324+
325+// MockStreamOps_DestroyStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DestroyStream'
326+type MockStreamOps_DestroyStream_Call struct {
327+ *mock.Call
328+}
329+
330+// DestroyStream is a helper method to define mock.On call
331+// - streamPtr unsafe.Pointer
332+func (_e *MockStreamOps_Expecter) DestroyStream(streamPtr interface{}) *MockStreamOps_DestroyStream_Call {
333+ return &MockStreamOps_DestroyStream_Call{Call: _e.mock.On("DestroyStream", streamPtr)}
334+}
335+
336+func (_c *MockStreamOps_DestroyStream_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DestroyStream_Call {
337+ _c.Call.Run(func(args mock.Arguments) {
338+ var arg0 unsafe.Pointer
339+ if args[0] != nil {
340+ arg0 = args[0].(unsafe.Pointer)
341+ }
342+ run(
343+ arg0,
344+ )
345+ })
346+ return _c
347+}
348+
349+func (_c *MockStreamOps_DestroyStream_Call) Return() *MockStreamOps_DestroyStream_Call {
350+ _c.Call.Return()
351+ return _c
352+}
353+
354+func (_c *MockStreamOps_DestroyStream_Call) RunAndReturn(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DestroyStream_Call {
355+ _c.Run(run)
356+ return _c
357+}
358+
359+// DisconnectStream provides a mock function for the type MockStreamOps
360+func (_mock *MockStreamOps) DisconnectStream(streamPtr unsafe.Pointer) {
361+ _mock.Called(streamPtr)
362+ return
363+}
364+
365+// MockStreamOps_DisconnectStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisconnectStream'
366+type MockStreamOps_DisconnectStream_Call struct {
367+ *mock.Call
368+}
369+
370+// DisconnectStream is a helper method to define mock.On call
371+// - streamPtr unsafe.Pointer
372+func (_e *MockStreamOps_Expecter) DisconnectStream(streamPtr interface{}) *MockStreamOps_DisconnectStream_Call {
373+ return &MockStreamOps_DisconnectStream_Call{Call: _e.mock.On("DisconnectStream", streamPtr)}
374+}
375+
376+func (_c *MockStreamOps_DisconnectStream_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DisconnectStream_Call {
377+ _c.Call.Run(func(args mock.Arguments) {
378+ var arg0 unsafe.Pointer
379+ if args[0] != nil {
380+ arg0 = args[0].(unsafe.Pointer)
381+ }
382+ run(
383+ arg0,
384+ )
385+ })
386+ return _c
387+}
388+
389+func (_c *MockStreamOps_DisconnectStream_Call) Return() *MockStreamOps_DisconnectStream_Call {
390+ _c.Call.Return()
391+ return _c
392+}
393+
394+func (_c *MockStreamOps_DisconnectStream_Call) RunAndReturn(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DisconnectStream_Call {
395+ _c.Run(run)
396+ return _c
397+}
398+
399+// QueueBuffer provides a mock function for the type MockStreamOps
400+func (_mock *MockStreamOps) QueueBuffer(streamPtr unsafe.Pointer, bufPtr unsafe.Pointer) error {
401+ ret := _mock.Called(streamPtr, bufPtr)
402+
403+ if len(ret) == 0 {
404+ panic("no return value specified for QueueBuffer")
405+ }
406+
407+ var r0 error
408+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, unsafe.Pointer) error); ok {
409+ r0 = returnFunc(streamPtr, bufPtr)
410+ } else {
411+ r0 = ret.Error(0)
412+ }
413+ return r0
414+}
415+
416+// MockStreamOps_QueueBuffer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueueBuffer'
417+type MockStreamOps_QueueBuffer_Call struct {
418+ *mock.Call
419+}
420+
421+// QueueBuffer is a helper method to define mock.On call
422+// - streamPtr unsafe.Pointer
423+// - bufPtr unsafe.Pointer
424+func (_e *MockStreamOps_Expecter) QueueBuffer(streamPtr interface{}, bufPtr interface{}) *MockStreamOps_QueueBuffer_Call {
425+ return &MockStreamOps_QueueBuffer_Call{Call: _e.mock.On("QueueBuffer", streamPtr, bufPtr)}
426+}
427+
428+func (_c *MockStreamOps_QueueBuffer_Call) Run(run func(streamPtr unsafe.Pointer, bufPtr unsafe.Pointer)) *MockStreamOps_QueueBuffer_Call {
429+ _c.Call.Run(func(args mock.Arguments) {
430+ var arg0 unsafe.Pointer
431+ if args[0] != nil {
432+ arg0 = args[0].(unsafe.Pointer)
433+ }
434+ var arg1 unsafe.Pointer
435+ if args[1] != nil {
436+ arg1 = args[1].(unsafe.Pointer)
437+ }
438+ run(
439+ arg0,
440+ arg1,
441+ )
442+ })
443+ return _c
444+}
445+
446+func (_c *MockStreamOps_QueueBuffer_Call) Return(err error) *MockStreamOps_QueueBuffer_Call {
447+ _c.Call.Return(err)
448+ return _c
449+}
450+
451+func (_c *MockStreamOps_QueueBuffer_Call) RunAndReturn(run func(streamPtr unsafe.Pointer, bufPtr unsafe.Pointer) error) *MockStreamOps_QueueBuffer_Call {
452+ _c.Call.Return(run)
453+ return _c
454+}
455+
456+// QuitMainLoop provides a mock function for the type MockStreamOps
457+func (_mock *MockStreamOps) QuitMainLoop(loopPtr unsafe.Pointer) {
458+ _mock.Called(loopPtr)
459+ return
460+}
461+
462+// MockStreamOps_QuitMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QuitMainLoop'
463+type MockStreamOps_QuitMainLoop_Call struct {
464+ *mock.Call
465+}
466+
467+// QuitMainLoop is a helper method to define mock.On call
468+// - loopPtr unsafe.Pointer
469+func (_e *MockStreamOps_Expecter) QuitMainLoop(loopPtr interface{}) *MockStreamOps_QuitMainLoop_Call {
470+ return &MockStreamOps_QuitMainLoop_Call{Call: _e.mock.On("QuitMainLoop", loopPtr)}
471+}
472+
473+func (_c *MockStreamOps_QuitMainLoop_Call) Run(run func(loopPtr unsafe.Pointer)) *MockStreamOps_QuitMainLoop_Call {
474+ _c.Call.Run(func(args mock.Arguments) {
475+ var arg0 unsafe.Pointer
476+ if args[0] != nil {
477+ arg0 = args[0].(unsafe.Pointer)
478+ }
479+ run(
480+ arg0,
481+ )
482+ })
483+ return _c
484+}
485+
486+func (_c *MockStreamOps_QuitMainLoop_Call) Return() *MockStreamOps_QuitMainLoop_Call {
487+ _c.Call.Return()
488+ return _c
489+}
490+
491+func (_c *MockStreamOps_QuitMainLoop_Call) RunAndReturn(run func(loopPtr unsafe.Pointer)) *MockStreamOps_QuitMainLoop_Call {
492+ _c.Run(run)
493+ return _c
494+}
495+
496+// RunMainLoop provides a mock function for the type MockStreamOps
497+func (_mock *MockStreamOps) RunMainLoop(loopPtr unsafe.Pointer) {
498+ _mock.Called(loopPtr)
499+ return
500+}
501+
502+// MockStreamOps_RunMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RunMainLoop'
503+type MockStreamOps_RunMainLoop_Call struct {
504+ *mock.Call
505+}
506+
507+// RunMainLoop is a helper method to define mock.On call
508+// - loopPtr unsafe.Pointer
509+func (_e *MockStreamOps_Expecter) RunMainLoop(loopPtr interface{}) *MockStreamOps_RunMainLoop_Call {
510+ return &MockStreamOps_RunMainLoop_Call{Call: _e.mock.On("RunMainLoop", loopPtr)}
511+}
512+
513+func (_c *MockStreamOps_RunMainLoop_Call) Run(run func(loopPtr unsafe.Pointer)) *MockStreamOps_RunMainLoop_Call {
514+ _c.Call.Run(func(args mock.Arguments) {
515+ var arg0 unsafe.Pointer
516+ if args[0] != nil {
517+ arg0 = args[0].(unsafe.Pointer)
518+ }
519+ run(
520+ arg0,
521+ )
522+ })
523+ return _c
524+}
525+
526+func (_c *MockStreamOps_RunMainLoop_Call) Return() *MockStreamOps_RunMainLoop_Call {
527+ _c.Call.Return()
528+ return _c
529+}
530+
531+func (_c *MockStreamOps_RunMainLoop_Call) RunAndReturn(run func(loopPtr unsafe.Pointer)) *MockStreamOps_RunMainLoop_Call {
532+ _c.Run(run)
533+ return _c
534+}
535+
536+// SetStreamActive provides a mock function for the type MockStreamOps
537+func (_mock *MockStreamOps) SetStreamActive(streamPtr unsafe.Pointer, active bool) error {
538+ ret := _mock.Called(streamPtr, active)
539+
540+ if len(ret) == 0 {
541+ panic("no return value specified for SetStreamActive")
542+ }
543+
544+ var r0 error
545+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, bool) error); ok {
546+ r0 = returnFunc(streamPtr, active)
547+ } else {
548+ r0 = ret.Error(0)
549+ }
550+ return r0
551+}
552+
553+// MockStreamOps_SetStreamActive_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetStreamActive'
554+type MockStreamOps_SetStreamActive_Call struct {
555+ *mock.Call
556+}
557+
558+// SetStreamActive is a helper method to define mock.On call
559+// - streamPtr unsafe.Pointer
560+// - active bool
561+func (_e *MockStreamOps_Expecter) SetStreamActive(streamPtr interface{}, active interface{}) *MockStreamOps_SetStreamActive_Call {
562+ return &MockStreamOps_SetStreamActive_Call{Call: _e.mock.On("SetStreamActive", streamPtr, active)}
563+}
564+
565+func (_c *MockStreamOps_SetStreamActive_Call) Run(run func(streamPtr unsafe.Pointer, active bool)) *MockStreamOps_SetStreamActive_Call {
566+ _c.Call.Run(func(args mock.Arguments) {
567+ var arg0 unsafe.Pointer
568+ if args[0] != nil {
569+ arg0 = args[0].(unsafe.Pointer)
570+ }
571+ var arg1 bool
572+ if args[1] != nil {
573+ arg1 = args[1].(bool)
574+ }
575+ run(
576+ arg0,
577+ arg1,
578+ )
579+ })
580+ return _c
581+}
582+
583+func (_c *MockStreamOps_SetStreamActive_Call) Return(err error) *MockStreamOps_SetStreamActive_Call {
584+ _c.Call.Return(err)
585+ return _c
586+}
587+
588+func (_c *MockStreamOps_SetStreamActive_Call) RunAndReturn(run func(streamPtr unsafe.Pointer, active bool) error) *MockStreamOps_SetStreamActive_Call {
589+ _c.Call.Return(run)
590+ return _c
591+}
@@ -0,0 +1,591 @@
1+// Code generated by mockery; DO NOT EDIT.
2+// github.com/vektra/mockery
3+// template: testify
4+
5+package mocks
6+
7+import (
8+ "unsafe"
9+
10+ mock "github.com/stretchr/testify/mock"
11+)
12+
13+// NewMockStreamOps creates a new instance of MockStreamOps. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
14+// The first argument is typically a *testing.T value.
15+func NewMockStreamOps(t interface {
16+ mock.TestingT
17+ Cleanup(func())
18+}) *MockStreamOps {
19+ mock := &MockStreamOps{}
20+ mock.Mock.Test(t)
21+
22+ t.Cleanup(func() { mock.AssertExpectations(t) })
23+
24+ return mock
25+}
26+
27+// MockStreamOps is an autogenerated mock type for the StreamOps type
28+type MockStreamOps struct {
29+ mock.Mock
30+}
31+
32+type MockStreamOps_Expecter struct {
33+ mock *mock.Mock
34+}
35+
36+func (_m *MockStreamOps) EXPECT() *MockStreamOps_Expecter {
37+ return &MockStreamOps_Expecter{mock: &_m.Mock}
38+}
39+
40+// ConnectPlaybackStream provides a mock function for the type MockStreamOps
41+func (_mock *MockStreamOps) ConnectPlaybackStream(streamPtr unsafe.Pointer) error {
42+ ret := _mock.Called(streamPtr)
43+
44+ if len(ret) == 0 {
45+ panic("no return value specified for ConnectPlaybackStream")
46+ }
47+
48+ var r0 error
49+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer) error); ok {
50+ r0 = returnFunc(streamPtr)
51+ } else {
52+ r0 = ret.Error(0)
53+ }
54+ return r0
55+}
56+
57+// MockStreamOps_ConnectPlaybackStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConnectPlaybackStream'
58+type MockStreamOps_ConnectPlaybackStream_Call struct {
59+ *mock.Call
60+}
61+
62+// ConnectPlaybackStream is a helper method to define mock.On call
63+// - streamPtr unsafe.Pointer
64+func (_e *MockStreamOps_Expecter) ConnectPlaybackStream(streamPtr interface{}) *MockStreamOps_ConnectPlaybackStream_Call {
65+ return &MockStreamOps_ConnectPlaybackStream_Call{Call: _e.mock.On("ConnectPlaybackStream", streamPtr)}
66+}
67+
68+func (_c *MockStreamOps_ConnectPlaybackStream_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_ConnectPlaybackStream_Call {
69+ _c.Call.Run(func(args mock.Arguments) {
70+ var arg0 unsafe.Pointer
71+ if args[0] != nil {
72+ arg0 = args[0].(unsafe.Pointer)
73+ }
74+ run(
75+ arg0,
76+ )
77+ })
78+ return _c
79+}
80+
81+func (_c *MockStreamOps_ConnectPlaybackStream_Call) Return(err error) *MockStreamOps_ConnectPlaybackStream_Call {
82+ _c.Call.Return(err)
83+ return _c
84+}
85+
86+func (_c *MockStreamOps_ConnectPlaybackStream_Call) RunAndReturn(run func(streamPtr unsafe.Pointer) error) *MockStreamOps_ConnectPlaybackStream_Call {
87+ _c.Call.Return(run)
88+ return _c
89+}
90+
91+// CreateMainLoop provides a mock function for the type MockStreamOps
92+func (_mock *MockStreamOps) CreateMainLoop() (unsafe.Pointer, error) {
93+ ret := _mock.Called()
94+
95+ if len(ret) == 0 {
96+ panic("no return value specified for CreateMainLoop")
97+ }
98+
99+ var r0 unsafe.Pointer
100+ var r1 error
101+ if returnFunc, ok := ret.Get(0).(func() (unsafe.Pointer, error)); ok {
102+ return returnFunc()
103+ }
104+ if returnFunc, ok := ret.Get(0).(func() unsafe.Pointer); ok {
105+ r0 = returnFunc()
106+ } else {
107+ r0 = ret.Get(0).(unsafe.Pointer)
108+ }
109+ if returnFunc, ok := ret.Get(1).(func() error); ok {
110+ r1 = returnFunc()
111+ } else {
112+ r1 = ret.Error(1)
113+ }
114+ return r0, r1
115+}
116+
117+// MockStreamOps_CreateMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateMainLoop'
118+type MockStreamOps_CreateMainLoop_Call struct {
119+ *mock.Call
120+}
121+
122+// CreateMainLoop is a helper method to define mock.On call
123+func (_e *MockStreamOps_Expecter) CreateMainLoop() *MockStreamOps_CreateMainLoop_Call {
124+ return &MockStreamOps_CreateMainLoop_Call{Call: _e.mock.On("CreateMainLoop")}
125+}
126+
127+func (_c *MockStreamOps_CreateMainLoop_Call) Run(run func()) *MockStreamOps_CreateMainLoop_Call {
128+ _c.Call.Run(func(args mock.Arguments) {
129+ run()
130+ })
131+ return _c
132+}
133+
134+func (_c *MockStreamOps_CreateMainLoop_Call) Return(loopPtr unsafe.Pointer, err error) *MockStreamOps_CreateMainLoop_Call {
135+ _c.Call.Return(loopPtr, err)
136+ return _c
137+}
138+
139+func (_c *MockStreamOps_CreateMainLoop_Call) RunAndReturn(run func() (unsafe.Pointer, error)) *MockStreamOps_CreateMainLoop_Call {
140+ _c.Call.Return(run)
141+ return _c
142+}
143+
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)
147+
148+ if len(ret) == 0 {
149+ panic("no return value specified for CreatePlaybackStream")
150+ }
151+
152+ var r0 unsafe.Pointer
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)
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)
159+ } else {
160+ r0 = ret.Get(0).(unsafe.Pointer)
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)
164+ } else {
165+ r1 = ret.Error(1)
166+ }
167+ return r0, r1
168+}
169+
170+// MockStreamOps_CreatePlaybackStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePlaybackStream'
171+type MockStreamOps_CreatePlaybackStream_Call struct {
172+ *mock.Call
173+}
174+
175+// CreatePlaybackStream is a helper method to define mock.On call
176+// - loopPtr unsafe.Pointer
177+// - name string
178+// - sampleRate int
179+// - channels int
180+// - 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)}
183+}
184+
185+func (_c *MockStreamOps_CreatePlaybackStream_Call) Run(run func(loopPtr unsafe.Pointer, name string, sampleRate int, channels int, onProcess func())) *MockStreamOps_CreatePlaybackStream_Call {
186+ _c.Call.Run(func(args mock.Arguments) {
187+ var arg0 unsafe.Pointer
188+ if args[0] != nil {
189+ arg0 = args[0].(unsafe.Pointer)
190+ }
191+ var arg1 string
192+ if args[1] != nil {
193+ arg1 = args[1].(string)
194+ }
195+ var arg2 int
196+ 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())
206+ }
207+ run(
208+ arg0,
209+ arg1,
210+ arg2,
211+ arg3,
212+ arg4,
213+ )
214+ })
215+ return _c
216+}
217+
218+func (_c *MockStreamOps_CreatePlaybackStream_Call) Return(streamPtr unsafe.Pointer, err error) *MockStreamOps_CreatePlaybackStream_Call {
219+ _c.Call.Return(streamPtr, err)
220+ return _c
221+}
222+
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 {
224+ _c.Call.Return(run)
225+ return _c
226+}
227+
228+// DequeueBuffer provides a mock function for the type MockStreamOps
229+func (_mock *MockStreamOps) DequeueBuffer(streamPtr unsafe.Pointer) unsafe.Pointer {
230+ ret := _mock.Called(streamPtr)
231+
232+ if len(ret) == 0 {
233+ panic("no return value specified for DequeueBuffer")
234+ }
235+
236+ var r0 unsafe.Pointer
237+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer) unsafe.Pointer); ok {
238+ r0 = returnFunc(streamPtr)
239+ } else {
240+ r0 = ret.Get(0).(unsafe.Pointer)
241+ }
242+ return r0
243+}
244+
245+// MockStreamOps_DequeueBuffer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DequeueBuffer'
246+type MockStreamOps_DequeueBuffer_Call struct {
247+ *mock.Call
248+}
249+
250+// DequeueBuffer is a helper method to define mock.On call
251+// - streamPtr unsafe.Pointer
252+func (_e *MockStreamOps_Expecter) DequeueBuffer(streamPtr interface{}) *MockStreamOps_DequeueBuffer_Call {
253+ return &MockStreamOps_DequeueBuffer_Call{Call: _e.mock.On("DequeueBuffer", streamPtr)}
254+}
255+
256+func (_c *MockStreamOps_DequeueBuffer_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DequeueBuffer_Call {
257+ _c.Call.Run(func(args mock.Arguments) {
258+ var arg0 unsafe.Pointer
259+ if args[0] != nil {
260+ arg0 = args[0].(unsafe.Pointer)
261+ }
262+ run(
263+ arg0,
264+ )
265+ })
266+ return _c
267+}
268+
269+func (_c *MockStreamOps_DequeueBuffer_Call) Return(v unsafe.Pointer) *MockStreamOps_DequeueBuffer_Call {
270+ _c.Call.Return(v)
271+ return _c
272+}
273+
274+func (_c *MockStreamOps_DequeueBuffer_Call) RunAndReturn(run func(streamPtr unsafe.Pointer) unsafe.Pointer) *MockStreamOps_DequeueBuffer_Call {
275+ _c.Call.Return(run)
276+ return _c
277+}
278+
279+// DestroyMainLoop provides a mock function for the type MockStreamOps
280+func (_mock *MockStreamOps) DestroyMainLoop(loopPtr unsafe.Pointer) {
281+ _mock.Called(loopPtr)
282+ return
283+}
284+
285+// MockStreamOps_DestroyMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DestroyMainLoop'
286+type MockStreamOps_DestroyMainLoop_Call struct {
287+ *mock.Call
288+}
289+
290+// DestroyMainLoop is a helper method to define mock.On call
291+// - loopPtr unsafe.Pointer
292+func (_e *MockStreamOps_Expecter) DestroyMainLoop(loopPtr interface{}) *MockStreamOps_DestroyMainLoop_Call {
293+ return &MockStreamOps_DestroyMainLoop_Call{Call: _e.mock.On("DestroyMainLoop", loopPtr)}
294+}
295+
296+func (_c *MockStreamOps_DestroyMainLoop_Call) Run(run func(loopPtr unsafe.Pointer)) *MockStreamOps_DestroyMainLoop_Call {
297+ _c.Call.Run(func(args mock.Arguments) {
298+ var arg0 unsafe.Pointer
299+ if args[0] != nil {
300+ arg0 = args[0].(unsafe.Pointer)
301+ }
302+ run(
303+ arg0,
304+ )
305+ })
306+ return _c
307+}
308+
309+func (_c *MockStreamOps_DestroyMainLoop_Call) Return() *MockStreamOps_DestroyMainLoop_Call {
310+ _c.Call.Return()
311+ return _c
312+}
313+
314+func (_c *MockStreamOps_DestroyMainLoop_Call) RunAndReturn(run func(loopPtr unsafe.Pointer)) *MockStreamOps_DestroyMainLoop_Call {
315+ _c.Run(run)
316+ return _c
317+}
318+
319+// DestroyStream provides a mock function for the type MockStreamOps
320+func (_mock *MockStreamOps) DestroyStream(streamPtr unsafe.Pointer) {
321+ _mock.Called(streamPtr)
322+ return
323+}
324+
325+// MockStreamOps_DestroyStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DestroyStream'
326+type MockStreamOps_DestroyStream_Call struct {
327+ *mock.Call
328+}
329+
330+// DestroyStream is a helper method to define mock.On call
331+// - streamPtr unsafe.Pointer
332+func (_e *MockStreamOps_Expecter) DestroyStream(streamPtr interface{}) *MockStreamOps_DestroyStream_Call {
333+ return &MockStreamOps_DestroyStream_Call{Call: _e.mock.On("DestroyStream", streamPtr)}
334+}
335+
336+func (_c *MockStreamOps_DestroyStream_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DestroyStream_Call {
337+ _c.Call.Run(func(args mock.Arguments) {
338+ var arg0 unsafe.Pointer
339+ if args[0] != nil {
340+ arg0 = args[0].(unsafe.Pointer)
341+ }
342+ run(
343+ arg0,
344+ )
345+ })
346+ return _c
347+}
348+
349+func (_c *MockStreamOps_DestroyStream_Call) Return() *MockStreamOps_DestroyStream_Call {
350+ _c.Call.Return()
351+ return _c
352+}
353+
354+func (_c *MockStreamOps_DestroyStream_Call) RunAndReturn(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DestroyStream_Call {
355+ _c.Run(run)
356+ return _c
357+}
358+
359+// DisconnectStream provides a mock function for the type MockStreamOps
360+func (_mock *MockStreamOps) DisconnectStream(streamPtr unsafe.Pointer) {
361+ _mock.Called(streamPtr)
362+ return
363+}
364+
365+// MockStreamOps_DisconnectStream_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisconnectStream'
366+type MockStreamOps_DisconnectStream_Call struct {
367+ *mock.Call
368+}
369+
370+// DisconnectStream is a helper method to define mock.On call
371+// - streamPtr unsafe.Pointer
372+func (_e *MockStreamOps_Expecter) DisconnectStream(streamPtr interface{}) *MockStreamOps_DisconnectStream_Call {
373+ return &MockStreamOps_DisconnectStream_Call{Call: _e.mock.On("DisconnectStream", streamPtr)}
374+}
375+
376+func (_c *MockStreamOps_DisconnectStream_Call) Run(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DisconnectStream_Call {
377+ _c.Call.Run(func(args mock.Arguments) {
378+ var arg0 unsafe.Pointer
379+ if args[0] != nil {
380+ arg0 = args[0].(unsafe.Pointer)
381+ }
382+ run(
383+ arg0,
384+ )
385+ })
386+ return _c
387+}
388+
389+func (_c *MockStreamOps_DisconnectStream_Call) Return() *MockStreamOps_DisconnectStream_Call {
390+ _c.Call.Return()
391+ return _c
392+}
393+
394+func (_c *MockStreamOps_DisconnectStream_Call) RunAndReturn(run func(streamPtr unsafe.Pointer)) *MockStreamOps_DisconnectStream_Call {
395+ _c.Run(run)
396+ return _c
397+}
398+
399+// QueueBuffer provides a mock function for the type MockStreamOps
400+func (_mock *MockStreamOps) QueueBuffer(streamPtr unsafe.Pointer, bufPtr unsafe.Pointer) error {
401+ ret := _mock.Called(streamPtr, bufPtr)
402+
403+ if len(ret) == 0 {
404+ panic("no return value specified for QueueBuffer")
405+ }
406+
407+ var r0 error
408+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, unsafe.Pointer) error); ok {
409+ r0 = returnFunc(streamPtr, bufPtr)
410+ } else {
411+ r0 = ret.Error(0)
412+ }
413+ return r0
414+}
415+
416+// MockStreamOps_QueueBuffer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueueBuffer'
417+type MockStreamOps_QueueBuffer_Call struct {
418+ *mock.Call
419+}
420+
421+// QueueBuffer is a helper method to define mock.On call
422+// - streamPtr unsafe.Pointer
423+// - bufPtr unsafe.Pointer
424+func (_e *MockStreamOps_Expecter) QueueBuffer(streamPtr interface{}, bufPtr interface{}) *MockStreamOps_QueueBuffer_Call {
425+ return &MockStreamOps_QueueBuffer_Call{Call: _e.mock.On("QueueBuffer", streamPtr, bufPtr)}
426+}
427+
428+func (_c *MockStreamOps_QueueBuffer_Call) Run(run func(streamPtr unsafe.Pointer, bufPtr unsafe.Pointer)) *MockStreamOps_QueueBuffer_Call {
429+ _c.Call.Run(func(args mock.Arguments) {
430+ var arg0 unsafe.Pointer
431+ if args[0] != nil {
432+ arg0 = args[0].(unsafe.Pointer)
433+ }
434+ var arg1 unsafe.Pointer
435+ if args[1] != nil {
436+ arg1 = args[1].(unsafe.Pointer)
437+ }
438+ run(
439+ arg0,
440+ arg1,
441+ )
442+ })
443+ return _c
444+}
445+
446+func (_c *MockStreamOps_QueueBuffer_Call) Return(err error) *MockStreamOps_QueueBuffer_Call {
447+ _c.Call.Return(err)
448+ return _c
449+}
450+
451+func (_c *MockStreamOps_QueueBuffer_Call) RunAndReturn(run func(streamPtr unsafe.Pointer, bufPtr unsafe.Pointer) error) *MockStreamOps_QueueBuffer_Call {
452+ _c.Call.Return(run)
453+ return _c
454+}
455+
456+// QuitMainLoop provides a mock function for the type MockStreamOps
457+func (_mock *MockStreamOps) QuitMainLoop(loopPtr unsafe.Pointer) {
458+ _mock.Called(loopPtr)
459+ return
460+}
461+
462+// MockStreamOps_QuitMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QuitMainLoop'
463+type MockStreamOps_QuitMainLoop_Call struct {
464+ *mock.Call
465+}
466+
467+// QuitMainLoop is a helper method to define mock.On call
468+// - loopPtr unsafe.Pointer
469+func (_e *MockStreamOps_Expecter) QuitMainLoop(loopPtr interface{}) *MockStreamOps_QuitMainLoop_Call {
470+ return &MockStreamOps_QuitMainLoop_Call{Call: _e.mock.On("QuitMainLoop", loopPtr)}
471+}
472+
473+func (_c *MockStreamOps_QuitMainLoop_Call) Run(run func(loopPtr unsafe.Pointer)) *MockStreamOps_QuitMainLoop_Call {
474+ _c.Call.Run(func(args mock.Arguments) {
475+ var arg0 unsafe.Pointer
476+ if args[0] != nil {
477+ arg0 = args[0].(unsafe.Pointer)
478+ }
479+ run(
480+ arg0,
481+ )
482+ })
483+ return _c
484+}
485+
486+func (_c *MockStreamOps_QuitMainLoop_Call) Return() *MockStreamOps_QuitMainLoop_Call {
487+ _c.Call.Return()
488+ return _c
489+}
490+
491+func (_c *MockStreamOps_QuitMainLoop_Call) RunAndReturn(run func(loopPtr unsafe.Pointer)) *MockStreamOps_QuitMainLoop_Call {
492+ _c.Run(run)
493+ return _c
494+}
495+
496+// RunMainLoop provides a mock function for the type MockStreamOps
497+func (_mock *MockStreamOps) RunMainLoop(loopPtr unsafe.Pointer) {
498+ _mock.Called(loopPtr)
499+ return
500+}
501+
502+// MockStreamOps_RunMainLoop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RunMainLoop'
503+type MockStreamOps_RunMainLoop_Call struct {
504+ *mock.Call
505+}
506+
507+// RunMainLoop is a helper method to define mock.On call
508+// - loopPtr unsafe.Pointer
509+func (_e *MockStreamOps_Expecter) RunMainLoop(loopPtr interface{}) *MockStreamOps_RunMainLoop_Call {
510+ return &MockStreamOps_RunMainLoop_Call{Call: _e.mock.On("RunMainLoop", loopPtr)}
511+}
512+
513+func (_c *MockStreamOps_RunMainLoop_Call) Run(run func(loopPtr unsafe.Pointer)) *MockStreamOps_RunMainLoop_Call {
514+ _c.Call.Run(func(args mock.Arguments) {
515+ var arg0 unsafe.Pointer
516+ if args[0] != nil {
517+ arg0 = args[0].(unsafe.Pointer)
518+ }
519+ run(
520+ arg0,
521+ )
522+ })
523+ return _c
524+}
525+
526+func (_c *MockStreamOps_RunMainLoop_Call) Return() *MockStreamOps_RunMainLoop_Call {
527+ _c.Call.Return()
528+ return _c
529+}
530+
531+func (_c *MockStreamOps_RunMainLoop_Call) RunAndReturn(run func(loopPtr unsafe.Pointer)) *MockStreamOps_RunMainLoop_Call {
532+ _c.Run(run)
533+ return _c
534+}
535+
536+// SetStreamActive provides a mock function for the type MockStreamOps
537+func (_mock *MockStreamOps) SetStreamActive(streamPtr unsafe.Pointer, active bool) error {
538+ ret := _mock.Called(streamPtr, active)
539+
540+ if len(ret) == 0 {
541+ panic("no return value specified for SetStreamActive")
542+ }
543+
544+ var r0 error
545+ if returnFunc, ok := ret.Get(0).(func(unsafe.Pointer, bool) error); ok {
546+ r0 = returnFunc(streamPtr, active)
547+ } else {
548+ r0 = ret.Error(0)
549+ }
550+ return r0
551+}
552+
553+// MockStreamOps_SetStreamActive_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetStreamActive'
554+type MockStreamOps_SetStreamActive_Call struct {
555+ *mock.Call
556+}
557+
558+// SetStreamActive is a helper method to define mock.On call
559+// - streamPtr unsafe.Pointer
560+// - active bool
561+func (_e *MockStreamOps_Expecter) SetStreamActive(streamPtr interface{}, active interface{}) *MockStreamOps_SetStreamActive_Call {
562+ return &MockStreamOps_SetStreamActive_Call{Call: _e.mock.On("SetStreamActive", streamPtr, active)}
563+}
564+
565+func (_c *MockStreamOps_SetStreamActive_Call) Run(run func(streamPtr unsafe.Pointer, active bool)) *MockStreamOps_SetStreamActive_Call {
566+ _c.Call.Run(func(args mock.Arguments) {
567+ var arg0 unsafe.Pointer
568+ if args[0] != nil {
569+ arg0 = args[0].(unsafe.Pointer)
570+ }
571+ var arg1 bool
572+ if args[1] != nil {
573+ arg1 = args[1].(bool)
574+ }
575+ run(
576+ arg0,
577+ arg1,
578+ )
579+ })
580+ return _c
581+}
582+
583+func (_c *MockStreamOps_SetStreamActive_Call) Return(err error) *MockStreamOps_SetStreamActive_Call {
584+ _c.Call.Return(err)
585+ return _c
586+}
587+
588+func (_c *MockStreamOps_SetStreamActive_Call) RunAndReturn(run func(streamPtr unsafe.Pointer, active bool) error) *MockStreamOps_SetStreamActive_Call {
589+ _c.Call.Return(run)
590+ return _c
591+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 8

↑↓ moveenter openesc close