[PATCH 7/9] module-waveout: Query device for supported samplerate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Instead of using a fixed list list of supported rates,
ask the wave subsystem whether the rate can be used.
---
 src/modules/module-waveout.c |   59 +++++++++++++++++++++++++----------------
 1 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/src/modules/module-waveout.c b/src/modules/module-waveout.c
index 05bc306..44b15da 100644
--- a/src/modules/module-waveout.c
+++ b/src/modules/module-waveout.c
@@ -159,12 +159,11 @@ static void do_write(struct userdata *u) {
             memchunk.memblock = NULL;
         }
 
-        /* Insufficient data in sink buffer? */
+        /* Underflow detection */
         if (hdr->dwBufferLength == 0) {
             u->sink_underflow = 1;
             break;
         }
-
         u->sink_underflow = 0;
 
         res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
@@ -292,8 +291,12 @@ finish:
 }
 
 static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
-    struct userdata *u = (struct userdata *)inst;
+    struct userdata *u = (struct userdata*) inst;
 
+    if (msg == WOM_OPEN)
+        pa_log_debug("WaveOut subsystem opened.");
+    if (msg == WOM_CLOSE)
+        pa_log_debug("WaveOut subsystem closed.");
     if (msg != WOM_DONE)
         return;
 
@@ -304,8 +307,12 @@ static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD
 }
 
 static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
-    struct userdata *u = (struct userdata *)inst;
+    struct userdata *u = (struct userdata*) inst;
 
+    if (msg == WIM_OPEN)
+        pa_log_debug("WaveIn subsystem opened.");
+    if (msg == WIM_CLOSE)
+        pa_log_debug("WaveIn subsystem closed.");
     if (msg != WIM_DATA)
         return;
 
@@ -433,17 +440,6 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) {
 
     wf->nChannels = ss->channels;
 
-    switch (ss->rate) {
-    case 8000:
-    case 11025:
-    case 22005:
-    case 44100:
-        break;
-    default:
-        pa_log_error("Unsupported sample rate.");
-        return -1;
-    }
-
     wf->nSamplesPerSec = ss->rate;
 
     if (ss->format == PA_SAMPLE_U8)
@@ -451,7 +447,7 @@ static int ss_to_waveformat(pa_sample_spec *ss, LPWAVEFORMATEX wf) {
     else if (ss->format == PA_SAMPLE_S16NE)
         wf->wBitsPerSample = 16;
     else {
-        pa_log_error("Unsupported sample format.");
+        pa_log_error("Unsupported sample format, only u8 and s16 are supported.");
         return -1;
     }
 
@@ -467,7 +463,7 @@ int pa__get_n_used(pa_module *m) {
     struct userdata *u;
     pa_assert(m);
     pa_assert(m->userdata);
-    u = (struct userdata *)m->userdata;
+    u = (struct userdata*) m->userdata;
 
     return (u->sink ? pa_sink_used_by(u->sink) : 0) +
            (u->source ? pa_source_used_by(u->source) : 0);
@@ -479,6 +475,7 @@ int pa__init(pa_module *m) {
     HWAVEIN hwi = INVALID_HANDLE_VALUE;
     WAVEFORMATEX wf;
     WAVEOUTCAPS pwoc;
+    MMRESULT result;
     int nfrags, frag_size;
     pa_bool_t record = TRUE, playback = TRUE;
     unsigned int device;
@@ -551,23 +548,39 @@ int pa__init(pa_module *m) {
     u = pa_xmalloc(sizeof(struct userdata));
 
     if (record) {
-        if (waveInOpen(&hwi, device, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
-            pa_log("failed to open waveIn");
+        result = waveInOpen(&hwi, device, &wf, 0, 0, WAVE_FORMAT_DIRECT | WAVE_FORMAT_QUERY);
+        if (result != MMSYSERR_NOERROR) {
+            pa_log_warn("Sample spec not supported by WaveIn, falling back to default sample rate.");
+            ss.rate = wf.nSamplesPerSec = m->core->default_sample_spec.rate;
+        }
+        result = waveInOpen(&hwi, device, &wf, (DWORD_PTR) chunk_ready_cb, (DWORD_PTR) u, CALLBACK_FUNCTION);
+        if (result != MMSYSERR_NOERROR) {
+            char errortext[MAXERRORLENGTH];
+            pa_log("Failed to open WaveIn.");
+            if (waveInGetErrorText(result, errortext, sizeof(errortext)) == MMSYSERR_NOERROR)
+                pa_log("Error: %s", errortext);
             goto fail;
         }
         if (waveInStart(hwi) != MMSYSERR_NOERROR) {
             pa_log("failed to start waveIn");
             goto fail;
         }
-        pa_log_debug("Opened waveIn subsystem.");
     }
 
     if (playback) {
-        if (waveOutOpen(&hwo, device, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
-            pa_log("failed to open waveOut");
+        result = waveOutOpen(&hwo, device, &wf, 0, 0, WAVE_FORMAT_DIRECT | WAVE_FORMAT_QUERY);
+        if (result != MMSYSERR_NOERROR) {
+            pa_log_warn("Sample spec not supported by WaveOut, falling back to default sample rate.");
+            ss.rate = wf.nSamplesPerSec = m->core->default_sample_spec.rate;
+        }
+        result = waveOutOpen(&hwo, device, &wf, (DWORD_PTR) chunk_done_cb, (DWORD_PTR) u, CALLBACK_FUNCTION);
+        if (result != MMSYSERR_NOERROR) {
+            char errortext[MAXERRORLENGTH];
+            pa_log("Failed to open WaveOut.");
+            if (waveOutGetErrorText(result, errortext, sizeof(errortext)) == MMSYSERR_NOERROR)
+                pa_log("Error: %s", errortext);
             goto fail;
         }
-        pa_log_debug("Opened waveOut subsystem.");
     }
 
     InitializeCriticalSection(&u->crit);
-- 
1.7.1




[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux