Bug 848954 - Part 22 - Port the osx panning code to live in the AudioCallbackDriver. r=jesup

This commit is contained in:
Paul Adenot 2014-08-26 17:02:31 +02:00
parent 6628654530
commit 0b444838eb
2 changed files with 84 additions and 0 deletions

View File

@ -6,6 +6,10 @@
#include <MediaStreamGraphImpl.h>
#include "CubebUtils.h"
#ifdef XP_MACOSX
#include <sys/sysctl.h>
#endif
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaStreamGraphLog;
#define STREAM_LOG(type, msg) PR_LOG(gMediaStreamGraphLog, type, msg)
@ -515,6 +519,9 @@ AudioCallbackDriver::Init()
return;
}
cubeb_stream_register_device_changed_callback(mAudioStream,
AudioCallbackDriver::DeviceChangedCallback_s);
StartStream();
STREAM_LOG(PR_LOG_DEBUG, ("AudioCallbackDriver started."));
@ -659,6 +666,13 @@ AudioCallbackDriver::StateCallback_s(cubeb_stream* aStream, void * aUser,
driver->StateCallback(aState);
}
/* static */ void
AudioCallbackDriver::DeviceChangedCallback_s(void* aUser)
{
AudioCallbackDriver* driver = reinterpret_cast<AudioCallbackDriver*>(aUser);
driver->DeviceChangedCallback();
}
bool AudioCallbackDriver::InCallback() {
MonitorAutoLock mon(mGraphImpl->GetMonitor());
return mInCallback;
@ -813,6 +827,59 @@ AudioCallbackDriver::MixerCallback(AudioDataValue* aMixedBuffer,
NS_WARN_IF_FALSE(written == aFrames - toWrite, "Dropping frames.");
};
void AudioCallbackDriver::PanOutputIfNeeded(bool aMicrophoneActive)
{
#ifdef XP_MACOSX
cubeb_device* out;
int rv;
char name[128];
size_t length = sizeof(name);
rv = sysctlbyname("hw.model", name, &length, NULL, 0);
if (rv) {
return;
}
if (!strncmp(name, "MacBookPro", 10)) {
if (cubeb_stream_get_current_device(mAudioStream, &out) == CUBEB_OK) {
// Check if we are currently outputing sound on external speakers.
if (!strcmp(out->output_name, "ispk")) {
// Pan everything to the right speaker.
if (aMicrophoneActive) {
if (cubeb_stream_set_panning(mAudioStream, 1.0) != CUBEB_OK) {
NS_WARNING("Could not pan audio output to the right.");
}
} else {
if (cubeb_stream_set_panning(mAudioStream, 0.0) != CUBEB_OK) {
NS_WARNING("Could not pan audio output to the center.");
}
}
} else {
if (cubeb_stream_set_panning(mAudioStream, 0.0) != CUBEB_OK) {
NS_WARNING("Could not pan audio output to the center.");
}
}
cubeb_stream_device_destroy(mAudioStream, out);
}
}
#endif
}
void
AudioCallbackDriver::DeviceChangedCallback() {
MonitorAutoLock mon(mGraphImpl->GetMonitor());
PanOutputIfNeeded(mMicrophoneActive);
}
void
AudioCallbackDriver::SetMicrophoneActive(bool aActive)
{
MonitorAutoLock mon(mGraphImpl->GetMonitor());
mMicrophoneActive = aActive;
PanOutputIfNeeded(mMicrophoneActive);
}
uint32_t
AudioCallbackDriver::IterationDuration()

View File

@ -342,6 +342,7 @@ public:
long aFrames);
static void StateCallback_s(cubeb_stream* aStream, void * aUser,
cubeb_state aState);
static void DeviceChangedCallback_s(void * aUser);
/* This function is called by the underlying audio backend when a refill is
* needed. This is what drives the whole graph when it is used to output
* audio. If the return value is exactly aFrames, this function will get
@ -370,7 +371,19 @@ public:
bool InCallback();
bool IsStarted();
/* Tell the driver whether this process is using a microphone or not. This is
* thread safe. */
void SetMicrophoneActive(bool aActive);
private:
/**
* On certain MacBookPro, the microphone is located near the left speaker.
* We need to pan the sound output to the right speaker if we are using the
* mic and the built-in speaker, or we will have terrible echo. */
void PanOutputIfNeeded(bool aMicrophoneActive);
/**
* This is called when the output device used by the cubeb stream changes. */
void DeviceChangedCallback();
/* Start the cubeb stream */
void StartStream();
friend class AsyncCubebTask;
@ -426,6 +439,10 @@ private:
* but has not done so yet. This indicates tha the callback should return
* early */
bool mPauseRequested;
/**
* True if microphone is being used by this process. This is synchronized by
* the graph's monitor. */
bool mMicrophoneActive;
};
class AsyncCubebTask : public nsRunnable