aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorPaul Adenot <[email protected]>2023-04-24 14:14:29 +0200
committerPaul Adenot <[email protected]>2023-04-26 14:28:46 +0200
commit64422167605935bc6b3457d577340b0ab41f5121 (patch)
tree45e31711dc8c63c8719e40ba8e33a8e9f400eebd /src
parent3981f4a7ec477fd5cb02f0ef3e8dcaa55da24071 (diff)
downloadcubeb-64422167605935bc6b3457d577340b0ab41f5121.tar.gz
cubeb-64422167605935bc6b3457d577340b0ab41f5121.zip
Change the WinMM backend so that it doesn't call the user callback during initialization
Diffstat (limited to 'src')
-rw-r--r--src/cubeb_winmm.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/src/cubeb_winmm.c b/src/cubeb_winmm.c
index 44aec86..dc1db9c 100644
--- a/src/cubeb_winmm.c
+++ b/src/cubeb_winmm.c
@@ -109,6 +109,8 @@ struct cubeb_stream {
HWAVEOUT waveout;
CRITICAL_SECTION lock;
uint64_t written;
+ /* number of frames written during preroll */
+ uint64_t position_base;
float soft_volume;
/* For position wrap-around handling: */
size_t frame_size;
@@ -150,6 +152,13 @@ winmm_get_next_buffer(cubeb_stream * stm)
return hdr;
}
+static long
+preroll_callback(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
+{
+ memset((uint8_t*)outputbuffer, 0, nframes * bytes_per_frame(stream->params));
+ return nframes;
+}
+
static void
winmm_refill_stream(cubeb_stream * stm)
{
@@ -486,7 +495,11 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream,
stm->params = *output_stream_params;
- stm->data_callback = data_callback;
+ // Data callback is set to the user-provided data callback after
+ // the initialization and potential preroll callback calls are done, because
+ // cubeb users don't expect the data callback to be called during
+ // initialization.
+ stm->data_callback = preroll_callback;
stm->state_callback = state_callback;
stm->user_ptr = user_ptr;
stm->written = 0;
@@ -553,6 +566,13 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream,
stm->frame_size = bytes_per_frame(stm->params);
stm->prev_pos_lo_dword = 0;
stm->pos_hi_dword = 0;
+ // Set the user data callback now that preroll has finished.
+ stm->data_callback = data_callback;
+ stm->position_base = 0;
+
+ // Offset the position by the number of frames written during preroll.
+ stm->position_base = stm->written;
+ stm->written = 0;
*stream = stm;
@@ -774,7 +794,15 @@ winmm_stream_get_position(cubeb_stream * stm, uint64_t * position)
return CUBEB_ERROR;
}
- *position = update_64bit_position(stm, time.u.cb) / stm->frame_size;
+ uint64_t position_not_adjusted = update_64bit_position(stm, time.u.cb) / stm->frame_size;
+
+ // Subtract the number of frames that were written while prerolling, during initialization.
+ if (position_not_adjusted < stm->position_base) {
+ *position = 0;
+ } else {
+ *position = position_not_adjusted - stm->position_base;
+ }
+
LeaveCriticalSection(&stm->lock);
return CUBEB_OK;
@@ -787,17 +815,12 @@ winmm_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
MMTIME time;
uint64_t written, position;
- EnterCriticalSection(&stm->lock);
- /* See the long comment above for why not just use TIME_SAMPLES here. */
- time.wType = TIME_BYTES;
- r = waveOutGetPosition(stm->waveout, &time, sizeof(time));
-
- if (r != MMSYSERR_NOERROR || time.wType != TIME_BYTES) {
- LeaveCriticalSection(&stm->lock);
- return CUBEB_ERROR;
+ int rv = winmm_stream_get_position(stm, &position);
+ if (rv != CUBEB_OK) {
+ return rv;
}
- position = update_64bit_position(stm, time.u.cb);
+ EnterCriticalSection(&stm->lock);
written = stm->written;
LeaveCriticalSection(&stm->lock);