diff --git a/webrtc/modules/audio_device/audio_device.gypi b/webrtc/modules/audio_device/audio_device.gypi index f9cb95a7fa..6ee3c8d986 100644 --- a/webrtc/modules/audio_device/audio_device.gypi +++ b/webrtc/modules/audio_device/audio_device.gypi @@ -138,7 +138,7 @@ ], 'link_settings': { 'libraries': [ - '-ldl', + '-ldl','-lX11', ], }, 'conditions': [ diff --git a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc index 2b7ed2e0bd..ca45a755e1 100644 --- a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc +++ b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc @@ -19,7 +19,6 @@ #include "trace.h" #include "thread_wrapper.h" - webrtc_adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable; // Accesses ALSA functions through our late-binding symbol table instead of @@ -110,6 +109,7 @@ AudioDeviceLinuxALSA::AudioDeviceLinuxALSA(const int32_t id) : _playBufDelay(80), _playBufDelayFixed(80) { + memset(_oldKeyState, 0, sizeof(_oldKeyState)); WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__); } @@ -182,6 +182,14 @@ int32_t AudioDeviceLinuxALSA::Init() return 0; } + //Get X display handle for typing detection + _XDisplay = XOpenDisplay(NULL); + if (!_XDisplay) + { + WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, + " failed to open X display, typing detection will not work"); + } + _playWarning = 0; _playError = 0; _recWarning = 0; @@ -248,6 +256,12 @@ int32_t AudioDeviceLinuxALSA::Terminate() _critSect.Enter(); } + if (_XDisplay) + { + XCloseDisplay(_XDisplay); + _XDisplay = NULL; + } + _initialized = false; _outputDeviceIsSpecified = false; _inputDeviceIsSpecified = false; @@ -2290,6 +2304,8 @@ bool AudioDeviceLinuxALSA::RecThreadProcess() _playoutDelay * 1000 / _playoutFreq, _recordingDelay * 1000 / _recordingFreq, 0); + _ptrAudioBuffer->SetTypingStatus(KeyPressed()); + // Deliver recorded samples at specified sample rate, mic level etc. // to the observer using callback. UnLock(); @@ -2317,4 +2333,25 @@ bool AudioDeviceLinuxALSA::RecThreadProcess() return true; } + +bool AudioDeviceLinuxALSA::KeyPressed() const{ + + char szKey[32]; + unsigned int i = 0; + char state = 0; + + if (!_XDisplay) + return false; + + // Check key map status + XQueryKeymap(_XDisplay, szKey); + + // A bit change in keymap means a key is pressed + for (i = 0; i < sizeof(szKey); i++) + state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; + + // Save old state + memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); + return (state != 0); +} } // namespace webrtc diff --git a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h index dd94e34dfd..de6deb2eea 100644 --- a/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h +++ b/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h @@ -12,13 +12,15 @@ #define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ALSA_LINUX_H #include "audio_device_generic.h" -#include "critical_section_wrapper.h" #include "audio_mixer_manager_alsa_linux.h" +#include "critical_section_wrapper.h" -#include -#include #include +#include +#include +#include + namespace webrtc { @@ -167,6 +169,9 @@ private: const int32_t ednLen = 0) const; int32_t ErrorRecovery(int32_t error, snd_pcm_t* deviceHandle); +private: + bool KeyPressed() const; + private: void Lock() { _critSect.Enter(); }; void UnLock() { _critSect.Leave(); }; @@ -242,6 +247,9 @@ private: uint16_t _playBufDelay; // playback delay uint16_t _playBufDelayFixed; // fixed playback delay + + char _oldKeyState[32]; + Display* _XDisplay; }; } diff --git a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc index 0c6635f5b1..56329a371e 100644 --- a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc +++ b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc @@ -136,6 +136,7 @@ AudioDeviceLinuxPulse::AudioDeviceLinuxPulse(const int32_t id) : memset(_paServerVersion, 0, sizeof(_paServerVersion)); memset(&_playBufferAttr, 0, sizeof(_playBufferAttr)); memset(&_recBufferAttr, 0, sizeof(_recBufferAttr)); + memset(_oldKeyState, 0, sizeof(_oldKeyState)); } AudioDeviceLinuxPulse::~AudioDeviceLinuxPulse() @@ -230,6 +231,14 @@ int32_t AudioDeviceLinuxPulse::Init() _recWarning = 0; _recError = 0; + //Get X display handle for typing detection + _XDisplay = XOpenDisplay(NULL); + if (!_XDisplay) + { + WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, + " failed to open X display, typing detection will not work"); + } + // RECORDING const char* threadName = "webrtc_audio_module_rec_thread"; _ptrThreadRec = ThreadWrapper::CreateThread(RecThreadFunc, this, @@ -343,6 +352,12 @@ int32_t AudioDeviceLinuxPulse::Terminate() return -1; } + if (_XDisplay) + { + XCloseDisplay(_XDisplay); + _XDisplay = NULL; + } + _initialized = false; _outputDeviceIsSpecified = false; _inputDeviceIsSpecified = false; @@ -2655,7 +2670,7 @@ int32_t AudioDeviceLinuxPulse::ProcessRecordedData( else recDelay = 0; _ptrAudioBuffer->SetVQEData(_sndCardPlayDelay, recDelay, clockDrift); - + _ptrAudioBuffer->SetTypingStatus(KeyPressed()); // Deliver recorded samples at specified sample rate, // mic level etc. to the observer using callback UnLock(); @@ -3094,4 +3109,24 @@ bool AudioDeviceLinuxPulse::RecThreadProcess() return true; } +bool AudioDeviceLinuxPulse::KeyPressed() const{ + + char szKey[32]; + unsigned int i = 0; + char state = 0; + + if (!_XDisplay) + return false; + + // Check key map status + XQueryKeymap(_XDisplay, szKey); + + // A bit change in keymap means a key is pressed + for (i = 0; i < sizeof(szKey); i++) + state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i]; + + // Save old state + memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState)); + return (state != 0); +} } diff --git a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h index 64e25ffdca..3b8a181f07 100644 --- a/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h +++ b/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h @@ -16,6 +16,7 @@ #include "critical_section_wrapper.h" #include +#include // We define this flag if it's missing from our headers, because we want to be // able to compile against old headers but still use PA_STREAM_ADJUST_LATENCY @@ -237,6 +238,9 @@ private: void WaitForOperationCompletion(pa_operation* paOperation) const; void WaitForSuccess(pa_operation* paOperation) const; +private: + bool KeyPressed() const; + private: static void PaContextStateCallback(pa_context *c, void *pThis); static void PaSinkInfoCallback(pa_context *c, const pa_sink_info *i, @@ -374,6 +378,9 @@ private: uint32_t _playStreamFlags; pa_buffer_attr _playBufferAttr; pa_buffer_attr _recBufferAttr; + + char _oldKeyState[32]; + Display* _XDisplay; }; }