aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMatthew Gregan <[email protected]>2012-11-01 16:28:57 +1300
committerMatthew Gregan <[email protected]>2012-11-01 16:28:57 +1300
commit8b971e00efee022f4248b3a8ed4e4a8600f2a429 (patch)
treebc9159bdb4a70f5d66a7feb27178c4f57d62d4b7
parentdfdf4a3c0f813717819f633f8bd3099c3e58ee8a (diff)
downloadcubeb-8b971e00efee022f4248b3a8ed4e4a8600f2a429.tar.gz
cubeb-8b971e00efee022f4248b3a8ed4e4a8600f2a429.zip
winmm: detect situations where winmm needs higher latency (Vista, RDP) and force a minimum latency value.
-rw-r--r--src/cubeb_winmm.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/cubeb_winmm.c b/src/cubeb_winmm.c
index 01e0fb0..49c6127 100644
--- a/src/cubeb_winmm.c
+++ b/src/cubeb_winmm.c
@@ -33,6 +33,7 @@ struct cubeb {
PSLIST_HEADER work;
CRITICAL_SECTION lock;
unsigned int active_streams;
+ int high_latency;
};
struct cubeb_stream {
@@ -190,6 +191,34 @@ cubeb_buffer_callback(HWAVEOUT waveout, UINT msg, DWORD_PTR user_ptr, DWORD_PTR
SetEvent(stm->context->event);
}
+static int
+high_latency_winmm(void)
+{
+ OSVERSIONINFOEX osvi;
+ DWORDLONG mask;
+
+ /* Vista's WinMM implementation underruns when less than 150ms of audio is buffered. */
+ memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ osvi.dwMajorVersion = 6;
+ osvi.dwMinorVersion = 0;
+
+ mask = 0;
+ VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_EQUAL);
+ VER_SET_CONDITION(mask, VER_MINORVERSION, VER_EQUAL);
+
+ if (VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) != 0) {
+ return 1;
+ }
+
+ /* Running under Terminal Services results in underruns with low latency. */
+ if (GetSystemMetrics(SM_REMOTESESSION) == TRUE) {
+ return 1;
+ }
+
+ return 0;
+}
+
int
cubeb_init(cubeb ** context, char const * context_name)
{
@@ -222,6 +251,8 @@ cubeb_init(cubeb ** context, char const * context_name)
InitializeCriticalSection(&ctx->lock);
ctx->active_streams = 0;
+ ctx->high_latency = high_latency_winmm();
+
*context = ctx;
return CUBEB_OK;
@@ -342,6 +373,10 @@ cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
stm->state_callback = state_callback;
stm->user_ptr = user_ptr;
+ if (context->high_latency) {
+ latency = latency < 200 ? 200 : latency;
+ }
+
bufsz = (size_t) (stm->params.rate / 1000.0 * latency * bytes_per_frame(stm->params) / NBUFS);
if (bufsz % bytes_per_frame(stm->params) != 0) {
bufsz += bytes_per_frame(stm->params) - (bufsz % bytes_per_frame(stm->params));