From c245e2d1678c3f7b15e96382f36075b9a92ec031 Mon Sep 17 00:00:00 2001 From: Mark-Willem Jansen Date: Mon, 28 Feb 2011 16:10:51 +0100 Subject: [PATCH] PulseAudio: Fix multi speakers configuration. - The PulseAudio profile for the speakers is now used in mumble. - This also fixed the problem of mumble crashing when using a 7.1 setup. - Cleared some additional QHash's and remove one that was unused. - Assigned the pa_sample_spec in order with the structure(format,rate,channels) - Added multi channel support for echo cancellation. --- src/mumble/PulseAudio.cpp | 35 +++++++++++++++++++++++------------ src/mumble/PulseAudio.h | 3 ++- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/mumble/PulseAudio.cpp b/src/mumble/PulseAudio.cpp index f5fec60999..82e21ce530 100644 --- a/src/mumble/PulseAudio.cpp +++ b/src/mumble/PulseAudio.cpp @@ -162,14 +162,17 @@ void PulseAudioSystem::eventCallback(pa_mainloop_api *api, pa_defer_event *) { case PA_STREAM_TERMINATED: { if (pasOutput) pa_stream_unref(pasOutput); + pa_sample_spec pss = qhSpecMap.value(odev); + pa_channel_map pcm = qhChanMap.value(odev); + if ((pss.format != PA_SAMPLE_FLOAT32NE) && (pss.format != PA_SAMPLE_S16NE)) + pss.format = PA_SAMPLE_FLOAT32NE; if (pss.rate == 0) pss.rate = SAMPLE_RATE; if ((pss.channels == 0) || (! g.s.doPositionalAudio())) pss.channels = 1; - if ((pss.format != PA_SAMPLE_FLOAT32NE) && (pss.format != PA_SAMPLE_S16NE)) - pss.format = PA_SAMPLE_FLOAT32NE; - pasOutput = pa_stream_new(pacContext, "Mumble Speakers", &pss, NULL); + + pasOutput = pa_stream_new(pacContext, "Mumble Speakers", &pss, (pss.channels == 1) ? NULL : &pcm); pa_stream_set_state_callback(pasOutput, stream_callback, this); pa_stream_set_write_callback(pasOutput, write_callback, this); } @@ -227,11 +230,11 @@ void PulseAudioSystem::eventCallback(pa_mainloop_api *api, pa_defer_event *) { pa_stream_unref(pasInput); pa_sample_spec pss = qhSpecMap.value(idev); + if ((pss.format != PA_SAMPLE_FLOAT32NE) && (pss.format != PA_SAMPLE_S16NE)) + pss.format = PA_SAMPLE_FLOAT32NE; if (pss.rate == 0) pss.rate = SAMPLE_RATE; pss.channels = 1; - if ((pss.format != PA_SAMPLE_FLOAT32NE) && (pss.format != PA_SAMPLE_S16NE)) - pss.format = PA_SAMPLE_FLOAT32NE; pasInput = pa_stream_new(pacContext, "Microphone", &pss, NULL); pa_stream_set_state_callback(pasInput, stream_callback, this); @@ -286,12 +289,15 @@ void PulseAudioSystem::eventCallback(pa_mainloop_api *api, pa_defer_event *) { pa_stream_unref(pasSpeaker); pa_sample_spec pss = qhSpecMap.value(edev); - if (pss.rate == 0) - pss.rate = SAMPLE_RATE; - pss.channels = 1; + pa_channel_map pcm = qhChanMap.value(edev); if ((pss.format != PA_SAMPLE_FLOAT32NE) && (pss.format != PA_SAMPLE_S16NE)) pss.format = PA_SAMPLE_FLOAT32NE; - pasSpeaker = pa_stream_new(pacContext, "Mumble Speakers (Echo)", &pss, NULL); + if (pss.rate == 0) + pss.rate = SAMPLE_RATE; + if ((pss.channels == 0) || (! g.s.bEchoMulti)) + pss.channels = 1; + + pasSpeaker = pa_stream_new(pacContext, "Mumble Speakers (Echo)", &pss, (pss.channels == 1) ? NULL : &pcm); pa_stream_set_state_callback(pasSpeaker, stream_callback, this); pa_stream_set_read_callback(pasSpeaker, read_callback, this); } @@ -299,7 +305,9 @@ void PulseAudioSystem::eventCallback(pa_mainloop_api *api, pa_defer_event *) { do_start = true; break; case PA_STREAM_READY: { - if (edev != qsEchoCache) { + if (g.s.bEchoMulti != bEchoMultiCache) { + do_stop = true; + } else if (edev != qsEchoCache) { do_stop = true; } break; @@ -322,6 +330,7 @@ void PulseAudioSystem::eventCallback(pa_mainloop_api *api, pa_defer_event *) { buff.prebuf = -1; buff.fragsize = iBlockLen; + bEchoMultiCache = g.s.bEchoMulti; qsEchoCache = edev; pa_stream_connect_record(pasSpeaker, qPrintable(edev), &buff, PA_STREAM_ADJUST_LATENCY); @@ -364,8 +373,8 @@ void PulseAudioSystem::sink_callback(pa_context *, const pa_sink_info *i, int eo const QString name = QLatin1String(i->name); - pas->qhIndexMap.insert(name, i->index); pas->qhSpecMap.insert(name, i->sample_spec); + pas->qhChanMap.insert(name, i->channel_map); pas->qhOutput.insert(name, QLatin1String(i->description)); pas->qhEchoMap.insert(name, QLatin1String(i->monitor_source_name)); } @@ -380,8 +389,8 @@ void PulseAudioSystem::source_callback(pa_context *, const pa_source_info *i, in const QString name = QLatin1String(i->name); - pas->qhIndexMap.insert(name, i->index); pas->qhSpecMap.insert(name, i->sample_spec); + pas->qhChanMap.insert(name, i->channel_map); if (i->monitor_of_sink == PA_INVALID_INDEX) pas->qhInput.insert(QLatin1String(i->name), QLatin1String(i->description)); @@ -542,6 +551,8 @@ void PulseAudioSystem::query() { qhInput.clear(); qhOutput.clear(); qhEchoMap.clear(); + qhSpecMap.clear(); + qhChanMap.clear(); qhInput.insert(QString(), tr("Default Input")); qhOutput.insert(QString(), tr("Default Output")); pa_operation_unref(pa_context_get_server_info(pacContext, server_callback, this)); diff --git a/src/mumble/PulseAudio.h b/src/mumble/PulseAudio.h index b9493b9c3a..0d53a84955 100644 --- a/src/mumble/PulseAudio.h +++ b/src/mumble/PulseAudio.h @@ -56,9 +56,10 @@ class PulseAudioSystem : public QObject { int iDelayCache; QString qsOutputCache, qsInputCache, qsEchoCache; bool bPositionalCache; + bool bEchoMultiCache; QHash qhEchoMap; QHash qhSpecMap; - QHash qhIndexMap; + QHash qhChanMap; static void defer_event_callback(pa_mainloop_api *a, pa_defer_event *e, void *userdata); static void context_state_callback(pa_context *c, void *userdata);