| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include <assert.h> | 11 #include <assert.h> |
| 12 | 12 |
| 13 #include "webrtc/modules/audio_device/linux/audio_mixer_manager_alsa_linux.h" | 13 #include "webrtc/modules/audio_device/linux/audio_mixer_manager_alsa_linux.h" |
| 14 #include "webrtc/system_wrappers/include/trace.h" | 14 #include "webrtc/system_wrappers/include/trace.h" |
| 15 | 15 |
| 16 extern webrtc_adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable; | 16 extern webrtc_adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable; |
| 17 | 17 |
| 18 // Accesses ALSA functions through our late-binding symbol table instead of | 18 // Accesses ALSA functions through our late-binding symbol table instead of |
| 19 // directly. This way we don't have to link to libalsa, which means our binary | 19 // directly. This way we don't have to link to libalsa, which means our binary |
| 20 // will work on systems that don't have it. | 20 // will work on systems that don't have it. |
| 21 #define LATE(sym) \ | 21 #define LATE(sym) \ |
| 22 LATESYM_GET(webrtc_adm_linux_alsa::AlsaSymbolTable, &AlsaSymbolTable, sym) | 22 LATESYM_GET(webrtc_adm_linux_alsa::AlsaSymbolTable, &AlsaSymbolTable, sym) |
| 23 | 23 |
| 24 namespace webrtc | 24 namespace webrtc |
| 25 { | 25 { |
| 26 | 26 |
| 27 AudioMixerManagerLinuxALSA::AudioMixerManagerLinuxALSA(const int32_t id) : | 27 AudioMixerManagerLinuxALSA::AudioMixerManagerLinuxALSA(const int32_t id) : |
| 28 _critSect(*CriticalSectionWrapper::CreateCriticalSection()), | |
| 29 _id(id), | 28 _id(id), |
| 30 _outputMixerHandle(NULL), | 29 _outputMixerHandle(NULL), |
| 31 _inputMixerHandle(NULL), | 30 _inputMixerHandle(NULL), |
| 32 _outputMixerElement(NULL), | 31 _outputMixerElement(NULL), |
| 33 _inputMixerElement(NULL) | 32 _inputMixerElement(NULL) |
| 34 { | 33 { |
| 35 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, | 34 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, |
| 36 "%s constructed", __FUNCTION__); | 35 "%s constructed", __FUNCTION__); |
| 37 | 36 |
| 38 memset(_outputMixerStr, 0, kAdmMaxDeviceNameSize); | 37 memset(_outputMixerStr, 0, kAdmMaxDeviceNameSize); |
| 39 memset(_inputMixerStr, 0, kAdmMaxDeviceNameSize); | 38 memset(_inputMixerStr, 0, kAdmMaxDeviceNameSize); |
| 40 } | 39 } |
| 41 | 40 |
| 42 AudioMixerManagerLinuxALSA::~AudioMixerManagerLinuxALSA() | 41 AudioMixerManagerLinuxALSA::~AudioMixerManagerLinuxALSA() |
| 43 { | 42 { |
| 44 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, | 43 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, |
| 45 "%s destructed", __FUNCTION__); | 44 "%s destructed", __FUNCTION__); |
| 46 | |
| 47 Close(); | 45 Close(); |
| 48 | |
| 49 delete &_critSect; | |
| 50 } | 46 } |
| 51 | 47 |
| 52 // ============================================================================ | 48 // ============================================================================ |
| 53 // PUBLIC METHODS | 49 // PUBLIC METHODS |
| 54 // ============================================================================ | 50 // ============================================================================ |
| 55 | 51 |
| 56 int32_t AudioMixerManagerLinuxALSA::Close() | 52 int32_t AudioMixerManagerLinuxALSA::Close() |
| 57 { | 53 { |
| 58 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", | 54 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", |
| 59 __FUNCTION__); | 55 __FUNCTION__); |
| 60 | 56 |
| 61 CriticalSectionScoped lock(&_critSect); | 57 rtc::CritScope lock(&_critSect); |
| 62 | 58 |
| 63 CloseSpeaker(); | 59 CloseSpeaker(); |
| 64 CloseMicrophone(); | 60 CloseMicrophone(); |
| 65 | 61 |
| 66 return 0; | 62 return 0; |
| 67 | 63 |
| 68 } | 64 } |
| 69 | 65 |
| 70 int32_t AudioMixerManagerLinuxALSA::CloseSpeaker() | 66 int32_t AudioMixerManagerLinuxALSA::CloseSpeaker() |
| 71 { | 67 { |
| 72 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", | 68 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", |
| 73 __FUNCTION__); | 69 __FUNCTION__); |
| 74 | 70 |
| 75 CriticalSectionScoped lock(&_critSect); | 71 rtc::CritScope lock(&_critSect); |
| 76 | 72 |
| 77 int errVal = 0; | 73 int errVal = 0; |
| 78 | 74 |
| 79 if (_outputMixerHandle != NULL) | 75 if (_outputMixerHandle != NULL) |
| 80 { | 76 { |
| 81 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 77 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 82 "Closing playout mixer"); | 78 "Closing playout mixer"); |
| 83 LATE(snd_mixer_free)(_outputMixerHandle); | 79 LATE(snd_mixer_free)(_outputMixerHandle); |
| 84 if (errVal < 0) | 80 if (errVal < 0) |
| 85 { | 81 { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 106 } | 102 } |
| 107 memset(_outputMixerStr, 0, kAdmMaxDeviceNameSize); | 103 memset(_outputMixerStr, 0, kAdmMaxDeviceNameSize); |
| 108 | 104 |
| 109 return 0; | 105 return 0; |
| 110 } | 106 } |
| 111 | 107 |
| 112 int32_t AudioMixerManagerLinuxALSA::CloseMicrophone() | 108 int32_t AudioMixerManagerLinuxALSA::CloseMicrophone() |
| 113 { | 109 { |
| 114 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); | 110 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__); |
| 115 | 111 |
| 116 CriticalSectionScoped lock(&_critSect); | 112 rtc::CritScope lock(&_critSect); |
| 117 | 113 |
| 118 int errVal = 0; | 114 int errVal = 0; |
| 119 | 115 |
| 120 if (_inputMixerHandle != NULL) | 116 if (_inputMixerHandle != NULL) |
| 121 { | 117 { |
| 122 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 118 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 123 "Closing record mixer"); | 119 "Closing record mixer"); |
| 124 | 120 |
| 125 LATE(snd_mixer_free)(_inputMixerHandle); | 121 LATE(snd_mixer_free)(_inputMixerHandle); |
| 126 if (errVal < 0) | 122 if (errVal < 0) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 memset(_inputMixerStr, 0, kAdmMaxDeviceNameSize); | 154 memset(_inputMixerStr, 0, kAdmMaxDeviceNameSize); |
| 159 | 155 |
| 160 return 0; | 156 return 0; |
| 161 } | 157 } |
| 162 | 158 |
| 163 int32_t AudioMixerManagerLinuxALSA::OpenSpeaker(char* deviceName) | 159 int32_t AudioMixerManagerLinuxALSA::OpenSpeaker(char* deviceName) |
| 164 { | 160 { |
| 165 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 161 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 166 "AudioMixerManagerLinuxALSA::OpenSpeaker(name=%s)", deviceName)
; | 162 "AudioMixerManagerLinuxALSA::OpenSpeaker(name=%s)", deviceName)
; |
| 167 | 163 |
| 168 CriticalSectionScoped lock(&_critSect); | 164 rtc::CritScope lock(&_critSect); |
| 169 | 165 |
| 170 int errVal = 0; | 166 int errVal = 0; |
| 171 | 167 |
| 172 // Close any existing output mixer handle | 168 // Close any existing output mixer handle |
| 173 // | 169 // |
| 174 if (_outputMixerHandle != NULL) | 170 if (_outputMixerHandle != NULL) |
| 175 { | 171 { |
| 176 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 172 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 177 "Closing playout mixer"); | 173 "Closing playout mixer"); |
| 178 | 174 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 | 248 |
| 253 return 0; | 249 return 0; |
| 254 } | 250 } |
| 255 | 251 |
| 256 int32_t AudioMixerManagerLinuxALSA::OpenMicrophone(char *deviceName) | 252 int32_t AudioMixerManagerLinuxALSA::OpenMicrophone(char *deviceName) |
| 257 { | 253 { |
| 258 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 254 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 259 "AudioMixerManagerLinuxALSA::OpenMicrophone(name=%s)", | 255 "AudioMixerManagerLinuxALSA::OpenMicrophone(name=%s)", |
| 260 deviceName); | 256 deviceName); |
| 261 | 257 |
| 262 CriticalSectionScoped lock(&_critSect); | 258 rtc::CritScope lock(&_critSect); |
| 263 | 259 |
| 264 int errVal = 0; | 260 int errVal = 0; |
| 265 | 261 |
| 266 // Close any existing input mixer handle | 262 // Close any existing input mixer handle |
| 267 // | 263 // |
| 268 if (_inputMixerHandle != NULL) | 264 if (_inputMixerHandle != NULL) |
| 269 { | 265 { |
| 270 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 266 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 271 "Closing record mixer"); | 267 "Closing record mixer"); |
| 272 | 268 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 return (_inputMixerHandle != NULL); | 367 return (_inputMixerHandle != NULL); |
| 372 } | 368 } |
| 373 | 369 |
| 374 int32_t AudioMixerManagerLinuxALSA::SetSpeakerVolume( | 370 int32_t AudioMixerManagerLinuxALSA::SetSpeakerVolume( |
| 375 uint32_t volume) | 371 uint32_t volume) |
| 376 { | 372 { |
| 377 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 373 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 378 "AudioMixerManagerLinuxALSA::SetSpeakerVolume(volume=%u)", | 374 "AudioMixerManagerLinuxALSA::SetSpeakerVolume(volume=%u)", |
| 379 volume); | 375 volume); |
| 380 | 376 |
| 381 CriticalSectionScoped lock(&_critSect); | 377 rtc::CritScope lock(&_critSect); |
| 382 | 378 |
| 383 if (_outputMixerElement == NULL) | 379 if (_outputMixerElement == NULL) |
| 384 { | 380 { |
| 385 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 381 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 386 " no avaliable output mixer element exists"); | 382 " no avaliable output mixer element exists"); |
| 387 return -1; | 383 return -1; |
| 388 } | 384 } |
| 389 | 385 |
| 390 int errVal = | 386 int errVal = |
| 391 LATE(snd_mixer_selem_set_playback_volume_all)(_outputMixerElement, | 387 LATE(snd_mixer_selem_set_playback_volume_all)(_outputMixerElement, |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 | 631 |
| 636 return 0; | 632 return 0; |
| 637 } | 633 } |
| 638 | 634 |
| 639 int32_t AudioMixerManagerLinuxALSA::SetSpeakerMute(bool enable) | 635 int32_t AudioMixerManagerLinuxALSA::SetSpeakerMute(bool enable) |
| 640 { | 636 { |
| 641 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 637 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 642 "AudioMixerManagerLinuxALSA::SetSpeakerMute(enable=%u)", | 638 "AudioMixerManagerLinuxALSA::SetSpeakerMute(enable=%u)", |
| 643 enable); | 639 enable); |
| 644 | 640 |
| 645 CriticalSectionScoped lock(&_critSect); | 641 rtc::CritScope lock(&_critSect); |
| 646 | 642 |
| 647 if (_outputMixerElement == NULL) | 643 if (_outputMixerElement == NULL) |
| 648 { | 644 { |
| 649 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 645 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 650 " no avaliable output mixer element exists"); | 646 " no avaliable output mixer element exists"); |
| 651 return -1; | 647 return -1; |
| 652 } | 648 } |
| 653 | 649 |
| 654 // Ensure that the selected speaker destination has a valid mute control. | 650 // Ensure that the selected speaker destination has a valid mute control. |
| 655 bool available(false); | 651 bool available(false); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 available = LATE(snd_mixer_selem_has_capture_switch)(_inputMixerElement); | 728 available = LATE(snd_mixer_selem_has_capture_switch)(_inputMixerElement); |
| 733 return 0; | 729 return 0; |
| 734 } | 730 } |
| 735 | 731 |
| 736 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneMute(bool enable) | 732 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneMute(bool enable) |
| 737 { | 733 { |
| 738 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 734 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 739 "AudioMixerManagerLinuxALSA::SetMicrophoneMute(enable=%u)", | 735 "AudioMixerManagerLinuxALSA::SetMicrophoneMute(enable=%u)", |
| 740 enable); | 736 enable); |
| 741 | 737 |
| 742 CriticalSectionScoped lock(&_critSect); | 738 rtc::CritScope lock(&_critSect); |
| 743 | 739 |
| 744 if (_inputMixerElement == NULL) | 740 if (_inputMixerElement == NULL) |
| 745 { | 741 { |
| 746 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 742 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 747 " no avaliable input mixer element exists"); | 743 " no avaliable input mixer element exists"); |
| 748 return -1; | 744 return -1; |
| 749 } | 745 } |
| 750 | 746 |
| 751 // Ensure that the selected microphone destination has a valid mute control. | 747 // Ensure that the selected microphone destination has a valid mute control. |
| 752 bool available(false); | 748 bool available(false); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 | 827 |
| 832 return 0; | 828 return 0; |
| 833 } | 829 } |
| 834 | 830 |
| 835 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneBoost(bool enable) | 831 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneBoost(bool enable) |
| 836 { | 832 { |
| 837 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 833 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 838 "AudioMixerManagerLinuxALSA::SetMicrophoneBoost(enable=%u)", | 834 "AudioMixerManagerLinuxALSA::SetMicrophoneBoost(enable=%u)", |
| 839 enable); | 835 enable); |
| 840 | 836 |
| 841 CriticalSectionScoped lock(&_critSect); | 837 rtc::CritScope lock(&_critSect); |
| 842 | 838 |
| 843 if (_inputMixerHandle == NULL) | 839 if (_inputMixerHandle == NULL) |
| 844 { | 840 { |
| 845 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 841 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 846 " no avaliable input mixer exists"); | 842 " no avaliable input mixer exists"); |
| 847 return -1; | 843 return -1; |
| 848 } | 844 } |
| 849 | 845 |
| 850 // Ensure that the selected microphone destination has a valid mute control. | 846 // Ensure that the selected microphone destination has a valid mute control. |
| 851 bool available(false); | 847 bool available(false); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 return 0; | 889 return 0; |
| 894 } | 890 } |
| 895 | 891 |
| 896 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneVolume( | 892 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneVolume( |
| 897 uint32_t volume) | 893 uint32_t volume) |
| 898 { | 894 { |
| 899 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 895 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 900 "AudioMixerManagerLinuxALSA::SetMicrophoneVolume(volume=%u)", | 896 "AudioMixerManagerLinuxALSA::SetMicrophoneVolume(volume=%u)", |
| 901 volume); | 897 volume); |
| 902 | 898 |
| 903 CriticalSectionScoped lock(&_critSect); | 899 rtc::CritScope lock(&_critSect); |
| 904 | 900 |
| 905 if (_inputMixerElement == NULL) | 901 if (_inputMixerElement == NULL) |
| 906 { | 902 { |
| 907 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 903 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, |
| 908 " no avaliable input mixer element exists"); | 904 " no avaliable input mixer element exists"); |
| 909 return -1; | 905 return -1; |
| 910 } | 906 } |
| 911 | 907 |
| 912 int | 908 int |
| 913 errVal = | 909 errVal = |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 } | 1285 } |
| 1290 | 1286 |
| 1291 void AudioMixerManagerLinuxALSA::GetControlName(char* controlName, | 1287 void AudioMixerManagerLinuxALSA::GetControlName(char* controlName, |
| 1292 char* deviceName) const | 1288 char* deviceName) const |
| 1293 { | 1289 { |
| 1294 // Example | 1290 // Example |
| 1295 // deviceName: "front:CARD=Intel,DEV=0" | 1291 // deviceName: "front:CARD=Intel,DEV=0" |
| 1296 // controlName: "hw:CARD=Intel" | 1292 // controlName: "hw:CARD=Intel" |
| 1297 char* pos1 = strchr(deviceName, ':'); | 1293 char* pos1 = strchr(deviceName, ':'); |
| 1298 char* pos2 = strchr(deviceName, ','); | 1294 char* pos2 = strchr(deviceName, ','); |
| 1299 if (!pos2) | 1295 if (!pos2) { |
| 1300 { | |
| 1301 // Can also be default:CARD=Intel | 1296 // Can also be default:CARD=Intel |
| 1302 pos2 = &deviceName[strlen(deviceName)]; | 1297 pos2 = &deviceName[strlen(deviceName)]; |
| 1303 } | 1298 } |
| 1304 if (pos1 && pos2) | 1299 if (pos1 && pos2) { |
| 1305 { | |
| 1306 strcpy(controlName, "hw"); | 1300 strcpy(controlName, "hw"); |
| 1307 int nChar = (int) (pos2 - pos1); | 1301 int nChar = (int) (pos2 - pos1); |
| 1308 strncpy(&controlName[2], pos1, nChar); | 1302 strncpy(&controlName[2], pos1, nChar); |
| 1309 controlName[2 + nChar] = '\0'; | 1303 controlName[2 + nChar] = '\0'; |
| 1310 } else | 1304 } else { |
| 1311 { | |
| 1312 strcpy(controlName, deviceName); | 1305 strcpy(controlName, deviceName); |
| 1313 } | 1306 } |
| 1314 | 1307 |
| 1315 } | 1308 } |
| 1316 | 1309 |
| 1317 } | 1310 } |
| OLD | NEW |