Home | History | Annotate | Download | only in linux
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      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
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <assert.h>
     12 
     13 #include "webrtc/modules/audio_device/linux/audio_mixer_manager_alsa_linux.h"
     14 #include "webrtc/system_wrappers/include/trace.h"
     15 
     16 extern webrtc_adm_linux_alsa::AlsaSymbolTable AlsaSymbolTable;
     17 
     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
     20 // will work on systems that don't have it.
     21 #define LATE(sym) \
     22   LATESYM_GET(webrtc_adm_linux_alsa::AlsaSymbolTable, &AlsaSymbolTable, sym)
     23 
     24 namespace webrtc
     25 {
     26 
     27 AudioMixerManagerLinuxALSA::AudioMixerManagerLinuxALSA(const int32_t id) :
     28     _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
     29     _id(id),
     30     _outputMixerHandle(NULL),
     31     _inputMixerHandle(NULL),
     32     _outputMixerElement(NULL),
     33     _inputMixerElement(NULL)
     34 {
     35     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id,
     36                  "%s constructed", __FUNCTION__);
     37 
     38     memset(_outputMixerStr, 0, kAdmMaxDeviceNameSize);
     39     memset(_inputMixerStr, 0, kAdmMaxDeviceNameSize);
     40 }
     41 
     42 AudioMixerManagerLinuxALSA::~AudioMixerManagerLinuxALSA()
     43 {
     44     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id,
     45                  "%s destructed", __FUNCTION__);
     46 
     47     Close();
     48 
     49     delete &_critSect;
     50 }
     51 
     52 // ============================================================================
     53 //                                    PUBLIC METHODS
     54 // ============================================================================
     55 
     56 int32_t AudioMixerManagerLinuxALSA::Close()
     57 {
     58     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s",
     59                  __FUNCTION__);
     60 
     61     CriticalSectionScoped lock(&_critSect);
     62 
     63     CloseSpeaker();
     64     CloseMicrophone();
     65 
     66     return 0;
     67 
     68 }
     69 
     70 int32_t AudioMixerManagerLinuxALSA::CloseSpeaker()
     71 {
     72     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s",
     73                  __FUNCTION__);
     74 
     75     CriticalSectionScoped lock(&_critSect);
     76 
     77     int errVal = 0;
     78 
     79     if (_outputMixerHandle != NULL)
     80     {
     81         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
     82                      "Closing playout mixer");
     83         LATE(snd_mixer_free)(_outputMixerHandle);
     84         if (errVal < 0)
     85         {
     86             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
     87                          "     Error freeing playout mixer: %s",
     88                          LATE(snd_strerror)(errVal));
     89         }
     90         errVal = LATE(snd_mixer_detach)(_outputMixerHandle, _outputMixerStr);
     91         if (errVal < 0)
     92         {
     93             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
     94                          "     Error detachinging playout mixer: %s",
     95                          LATE(snd_strerror)(errVal));
     96         }
     97         errVal = LATE(snd_mixer_close)(_outputMixerHandle);
     98         if (errVal < 0)
     99         {
    100             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    101                          "     Error snd_mixer_close(handleMixer) errVal=%d",
    102                          errVal);
    103         }
    104         _outputMixerHandle = NULL;
    105         _outputMixerElement = NULL;
    106     }
    107     memset(_outputMixerStr, 0, kAdmMaxDeviceNameSize);
    108 
    109     return 0;
    110 }
    111 
    112 int32_t AudioMixerManagerLinuxALSA::CloseMicrophone()
    113 {
    114     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    115 
    116     CriticalSectionScoped lock(&_critSect);
    117 
    118     int errVal = 0;
    119 
    120     if (_inputMixerHandle != NULL)
    121     {
    122         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    123                      "Closing record mixer");
    124 
    125         LATE(snd_mixer_free)(_inputMixerHandle);
    126         if (errVal < 0)
    127         {
    128             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    129                          "     Error freeing record mixer: %s",
    130                          LATE(snd_strerror)(errVal));
    131         }
    132         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    133                      "Closing record mixer 2");
    134 
    135         errVal = LATE(snd_mixer_detach)(_inputMixerHandle, _inputMixerStr);
    136         if (errVal < 0)
    137         {
    138             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    139                          "     Error detachinging record mixer: %s",
    140                          LATE(snd_strerror)(errVal));
    141         }
    142         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    143                      "Closing record mixer 3");
    144 
    145         errVal = LATE(snd_mixer_close)(_inputMixerHandle);
    146         if (errVal < 0)
    147         {
    148             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    149                          "     Error snd_mixer_close(handleMixer) errVal=%d",
    150                          errVal);
    151         }
    152 
    153         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    154                      "Closing record mixer 4");
    155         _inputMixerHandle = NULL;
    156         _inputMixerElement = NULL;
    157     }
    158     memset(_inputMixerStr, 0, kAdmMaxDeviceNameSize);
    159 
    160     return 0;
    161 }
    162 
    163 int32_t AudioMixerManagerLinuxALSA::OpenSpeaker(char* deviceName)
    164 {
    165     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    166                  "AudioMixerManagerLinuxALSA::OpenSpeaker(name=%s)", deviceName);
    167 
    168     CriticalSectionScoped lock(&_critSect);
    169 
    170     int errVal = 0;
    171 
    172     // Close any existing output mixer handle
    173     //
    174     if (_outputMixerHandle != NULL)
    175     {
    176         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    177                      "Closing playout mixer");
    178 
    179         LATE(snd_mixer_free)(_outputMixerHandle);
    180         if (errVal < 0)
    181         {
    182             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    183                          "     Error freeing playout mixer: %s",
    184                          LATE(snd_strerror)(errVal));
    185         }
    186         errVal = LATE(snd_mixer_detach)(_outputMixerHandle, _outputMixerStr);
    187         if (errVal < 0)
    188         {
    189             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    190                          "     Error detachinging playout mixer: %s",
    191                          LATE(snd_strerror)(errVal));
    192         }
    193         errVal = LATE(snd_mixer_close)(_outputMixerHandle);
    194         if (errVal < 0)
    195         {
    196             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    197                          "     Error snd_mixer_close(handleMixer) errVal=%d",
    198                          errVal);
    199         }
    200     }
    201     _outputMixerHandle = NULL;
    202     _outputMixerElement = NULL;
    203 
    204     errVal = LATE(snd_mixer_open)(&_outputMixerHandle, 0);
    205     if (errVal < 0)
    206     {
    207         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    208                      "snd_mixer_open(&_outputMixerHandle, 0) - error");
    209         return -1;
    210     }
    211 
    212     char controlName[kAdmMaxDeviceNameSize] = { 0 };
    213     GetControlName(controlName, deviceName);
    214 
    215     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    216                  "     snd_mixer_attach(_outputMixerHandle, %s)", controlName);
    217 
    218     errVal = LATE(snd_mixer_attach)(_outputMixerHandle, controlName);
    219     if (errVal < 0)
    220     {
    221         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    222                      "     snd_mixer_attach(_outputMixerHandle, %s) error: %s",
    223                      controlName, LATE(snd_strerror)(errVal));
    224         _outputMixerHandle = NULL;
    225         return -1;
    226     }
    227     strcpy(_outputMixerStr, controlName);
    228 
    229     errVal = LATE(snd_mixer_selem_register)(_outputMixerHandle, NULL, NULL);
    230     if (errVal < 0)
    231     {
    232         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    233                      "     snd_mixer_selem_register(_outputMixerHandle,"
    234                      " NULL, NULL), error: %s",
    235                      LATE(snd_strerror)(errVal));
    236         _outputMixerHandle = NULL;
    237         return -1;
    238     }
    239 
    240     // Load and find the proper mixer element
    241     if (LoadSpeakerMixerElement() < 0)
    242     {
    243         return -1;
    244     }
    245 
    246     if (_outputMixerHandle != NULL)
    247     {
    248         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    249                      "  the output mixer device is now open (0x%x)",
    250                      _outputMixerHandle);
    251     }
    252 
    253     return 0;
    254 }
    255 
    256 int32_t AudioMixerManagerLinuxALSA::OpenMicrophone(char *deviceName)
    257 {
    258     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    259                  "AudioMixerManagerLinuxALSA::OpenMicrophone(name=%s)",
    260                  deviceName);
    261 
    262     CriticalSectionScoped lock(&_critSect);
    263 
    264     int errVal = 0;
    265 
    266     // Close any existing input mixer handle
    267     //
    268     if (_inputMixerHandle != NULL)
    269     {
    270         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    271                      "Closing record mixer");
    272 
    273         LATE(snd_mixer_free)(_inputMixerHandle);
    274         if (errVal < 0)
    275         {
    276             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    277                          "     Error freeing record mixer: %s",
    278                          LATE(snd_strerror)(errVal));
    279         }
    280         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    281                      "Closing record mixer");
    282 
    283         errVal = LATE(snd_mixer_detach)(_inputMixerHandle, _inputMixerStr);
    284         if (errVal < 0)
    285         {
    286             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    287                          "     Error detachinging record mixer: %s",
    288                          LATE(snd_strerror)(errVal));
    289         }
    290         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    291                      "Closing record mixer");
    292 
    293         errVal = LATE(snd_mixer_close)(_inputMixerHandle);
    294         if (errVal < 0)
    295         {
    296             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    297                          "     Error snd_mixer_close(handleMixer) errVal=%d",
    298                          errVal);
    299         }
    300         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    301                      "Closing record mixer");
    302     }
    303     _inputMixerHandle = NULL;
    304     _inputMixerElement = NULL;
    305 
    306     errVal = LATE(snd_mixer_open)(&_inputMixerHandle, 0);
    307     if (errVal < 0)
    308     {
    309         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    310                      "     snd_mixer_open(&_inputMixerHandle, 0) - error");
    311         return -1;
    312     }
    313 
    314     char controlName[kAdmMaxDeviceNameSize] = { 0 };
    315     GetControlName(controlName, deviceName);
    316 
    317     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    318                  "     snd_mixer_attach(_inputMixerHandle, %s)", controlName);
    319 
    320     errVal = LATE(snd_mixer_attach)(_inputMixerHandle, controlName);
    321     if (errVal < 0)
    322     {
    323         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    324                      "     snd_mixer_attach(_inputMixerHandle, %s) error: %s",
    325                      controlName, LATE(snd_strerror)(errVal));
    326 
    327         _inputMixerHandle = NULL;
    328         return -1;
    329     }
    330     strcpy(_inputMixerStr, controlName);
    331 
    332     errVal = LATE(snd_mixer_selem_register)(_inputMixerHandle, NULL, NULL);
    333     if (errVal < 0)
    334     {
    335         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    336                      "     snd_mixer_selem_register(_inputMixerHandle,"
    337                      " NULL, NULL), error: %s",
    338                      LATE(snd_strerror)(errVal));
    339 
    340         _inputMixerHandle = NULL;
    341         return -1;
    342     }
    343     // Load and find the proper mixer element
    344     if (LoadMicMixerElement() < 0)
    345     {
    346         return -1;
    347     }
    348 
    349     if (_inputMixerHandle != NULL)
    350     {
    351         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    352                      "  the input mixer device is now open (0x%x)",
    353                      _inputMixerHandle);
    354     }
    355 
    356     return 0;
    357 }
    358 
    359 bool AudioMixerManagerLinuxALSA::SpeakerIsInitialized() const
    360 {
    361     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
    362 
    363     return (_outputMixerHandle != NULL);
    364 }
    365 
    366 bool AudioMixerManagerLinuxALSA::MicrophoneIsInitialized() const
    367 {
    368     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s",
    369                  __FUNCTION__);
    370 
    371     return (_inputMixerHandle != NULL);
    372 }
    373 
    374 int32_t AudioMixerManagerLinuxALSA::SetSpeakerVolume(
    375     uint32_t volume)
    376 {
    377     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    378                  "AudioMixerManagerLinuxALSA::SetSpeakerVolume(volume=%u)",
    379                  volume);
    380 
    381     CriticalSectionScoped lock(&_critSect);
    382 
    383     if (_outputMixerElement == NULL)
    384     {
    385         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    386                      "  no avaliable output mixer element exists");
    387         return -1;
    388     }
    389 
    390     int errVal =
    391         LATE(snd_mixer_selem_set_playback_volume_all)(_outputMixerElement,
    392                                                       volume);
    393     if (errVal < 0)
    394     {
    395         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    396                      "     Error changing master volume: %s",
    397                      LATE(snd_strerror)(errVal));
    398         return -1;
    399     }
    400 
    401     return (0);
    402 }
    403 
    404 int32_t AudioMixerManagerLinuxALSA::SpeakerVolume(
    405     uint32_t& volume) const
    406 {
    407 
    408     if (_outputMixerElement == NULL)
    409     {
    410         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    411                      "  no avaliable output mixer element exists");
    412         return -1;
    413     }
    414 
    415     long int vol(0);
    416 
    417     int
    418         errVal = LATE(snd_mixer_selem_get_playback_volume)(
    419             _outputMixerElement,
    420             (snd_mixer_selem_channel_id_t) 0,
    421             &vol);
    422     if (errVal < 0)
    423     {
    424         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    425                      "Error getting outputvolume: %s",
    426                      LATE(snd_strerror)(errVal));
    427         return -1;
    428     }
    429     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    430                  "     AudioMixerManagerLinuxALSA::SpeakerVolume() => vol=%i",
    431                  vol);
    432 
    433     volume = static_cast<uint32_t> (vol);
    434 
    435     return 0;
    436 }
    437 
    438 int32_t AudioMixerManagerLinuxALSA::MaxSpeakerVolume(
    439     uint32_t& maxVolume) const
    440 {
    441 
    442     if (_outputMixerElement == NULL)
    443     {
    444         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    445                      "  no avilable output mixer element exists");
    446         return -1;
    447     }
    448 
    449     long int minVol(0);
    450     long int maxVol(0);
    451 
    452     int errVal =
    453         LATE(snd_mixer_selem_get_playback_volume_range)(_outputMixerElement,
    454                                                         &minVol, &maxVol);
    455 
    456     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    457                  "     Playout hardware volume range, min: %d, max: %d",
    458                  minVol, maxVol);
    459 
    460     if (maxVol <= minVol)
    461     {
    462         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    463                      "     Error getting get_playback_volume_range: %s",
    464                      LATE(snd_strerror)(errVal));
    465     }
    466 
    467     maxVolume = static_cast<uint32_t> (maxVol);
    468 
    469     return 0;
    470 }
    471 
    472 int32_t AudioMixerManagerLinuxALSA::MinSpeakerVolume(
    473     uint32_t& minVolume) const
    474 {
    475 
    476     if (_outputMixerElement == NULL)
    477     {
    478         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    479                      "  no avaliable output mixer element exists");
    480         return -1;
    481     }
    482 
    483     long int minVol(0);
    484     long int maxVol(0);
    485 
    486     int errVal =
    487         LATE(snd_mixer_selem_get_playback_volume_range)(_outputMixerElement,
    488                                                         &minVol, &maxVol);
    489 
    490     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    491                  "     Playout hardware volume range, min: %d, max: %d",
    492                  minVol, maxVol);
    493 
    494     if (maxVol <= minVol)
    495     {
    496         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    497                      "     Error getting get_playback_volume_range: %s",
    498                      LATE(snd_strerror)(errVal));
    499     }
    500 
    501     minVolume = static_cast<uint32_t> (minVol);
    502 
    503     return 0;
    504 }
    505 
    506 // TL: Have done testnig with these but they don't seem reliable and
    507 // they were therefore not added
    508 /*
    509  // ----------------------------------------------------------------------------
    510  //    SetMaxSpeakerVolume
    511  // ----------------------------------------------------------------------------
    512 
    513  int32_t AudioMixerManagerLinuxALSA::SetMaxSpeakerVolume(
    514      uint32_t maxVolume)
    515  {
    516 
    517  if (_outputMixerElement == NULL)
    518  {
    519  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    520  "  no avaliable output mixer element exists");
    521  return -1;
    522  }
    523 
    524  long int minVol(0);
    525  long int maxVol(0);
    526 
    527  int errVal = snd_mixer_selem_get_playback_volume_range(
    528  _outputMixerElement, &minVol, &maxVol);
    529  if ((maxVol <= minVol) || (errVal != 0))
    530  {
    531  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    532   "     Error getting playback volume range: %s", snd_strerror(errVal));
    533  }
    534 
    535  maxVol = maxVolume;
    536  errVal = snd_mixer_selem_set_playback_volume_range(
    537  _outputMixerElement, minVol, maxVol);
    538  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    539   "     Playout hardware volume range, min: %d, max: %d", minVol, maxVol);
    540  if (errVal != 0)
    541  {
    542  WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    543   "     Error setting playback volume range: %s", snd_strerror(errVal));
    544  return -1;
    545  }
    546 
    547  return 0;
    548  }
    549 
    550  // ----------------------------------------------------------------------------
    551  //    SetMinSpeakerVolume
    552  // ----------------------------------------------------------------------------
    553 
    554  int32_t AudioMixerManagerLinuxALSA::SetMinSpeakerVolume(
    555      uint32_t minVolume)
    556  {
    557 
    558  if (_outputMixerElement == NULL)
    559  {
    560  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    561  "  no avaliable output mixer element exists");
    562  return -1;
    563  }
    564 
    565  long int minVol(0);
    566  long int maxVol(0);
    567 
    568  int errVal = snd_mixer_selem_get_playback_volume_range(
    569  _outputMixerElement, &minVol, &maxVol);
    570  if ((maxVol <= minVol) || (errVal != 0))
    571  {
    572  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    573   "     Error getting playback volume range: %s", snd_strerror(errVal));
    574  }
    575 
    576  minVol = minVolume;
    577  errVal = snd_mixer_selem_set_playback_volume_range(
    578  _outputMixerElement, minVol, maxVol);
    579  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    580  "     Playout hardware volume range, min: %d, max: %d", minVol, maxVol);
    581  if (errVal != 0)
    582  {
    583  WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    584  "     Error setting playback volume range: %s", snd_strerror(errVal));
    585  return -1;
    586  }
    587 
    588  return 0;
    589  }
    590  */
    591 
    592 int32_t AudioMixerManagerLinuxALSA::SpeakerVolumeStepSize(
    593     uint16_t& stepSize) const
    594 {
    595 
    596     if (_outputMixerHandle == NULL)
    597     {
    598         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    599                      "  no avaliable output mixer exists");
    600         return -1;
    601     }
    602 
    603     // The step size is always 1 for ALSA
    604     stepSize = 1;
    605 
    606     return 0;
    607 }
    608 
    609 int32_t AudioMixerManagerLinuxALSA::SpeakerVolumeIsAvailable(
    610     bool& available)
    611 {
    612     if (_outputMixerElement == NULL)
    613     {
    614         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    615                      "  no avaliable output mixer element exists");
    616         return -1;
    617     }
    618 
    619     available = LATE(snd_mixer_selem_has_playback_volume)(_outputMixerElement);
    620 
    621     return 0;
    622 }
    623 
    624 int32_t AudioMixerManagerLinuxALSA::SpeakerMuteIsAvailable(
    625     bool& available)
    626 {
    627     if (_outputMixerElement == NULL)
    628     {
    629         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    630                      "  no avaliable output mixer element exists");
    631         return -1;
    632     }
    633 
    634     available = LATE(snd_mixer_selem_has_playback_switch)(_outputMixerElement);
    635 
    636     return 0;
    637 }
    638 
    639 int32_t AudioMixerManagerLinuxALSA::SetSpeakerMute(bool enable)
    640 {
    641     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    642                  "AudioMixerManagerLinuxALSA::SetSpeakerMute(enable=%u)",
    643                  enable);
    644 
    645     CriticalSectionScoped lock(&_critSect);
    646 
    647     if (_outputMixerElement == NULL)
    648     {
    649         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    650                      "  no avaliable output mixer element exists");
    651         return -1;
    652     }
    653 
    654     // Ensure that the selected speaker destination has a valid mute control.
    655     bool available(false);
    656     SpeakerMuteIsAvailable(available);
    657     if (!available)
    658     {
    659         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    660                      "  it is not possible to mute the speaker");
    661         return -1;
    662     }
    663 
    664     // Note value = 0 (off) means muted
    665     int errVal =
    666         LATE(snd_mixer_selem_set_playback_switch_all)(_outputMixerElement,
    667                                                       !enable);
    668     if (errVal < 0)
    669     {
    670         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    671                      "     Error setting playback switch: %s",
    672                      LATE(snd_strerror)(errVal));
    673         return -1;
    674     }
    675 
    676     return (0);
    677 }
    678 
    679 int32_t AudioMixerManagerLinuxALSA::SpeakerMute(bool& enabled) const
    680 {
    681 
    682     if (_outputMixerElement == NULL)
    683     {
    684         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    685                      "  no avaliable output mixer exists");
    686         return -1;
    687     }
    688 
    689     // Ensure that the selected speaker destination has a valid mute control.
    690     bool available =
    691         LATE(snd_mixer_selem_has_playback_switch)(_outputMixerElement);
    692     if (!available)
    693     {
    694         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    695                      "  it is not possible to mute the speaker");
    696         return -1;
    697     }
    698 
    699     int value(false);
    700 
    701     // Retrieve one boolean control value for a specified mute-control
    702     //
    703     int
    704         errVal = LATE(snd_mixer_selem_get_playback_switch)(
    705             _outputMixerElement,
    706             (snd_mixer_selem_channel_id_t) 0,
    707             &value);
    708     if (errVal < 0)
    709     {
    710         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    711                      "     Error getting playback switch: %s",
    712                      LATE(snd_strerror)(errVal));
    713         return -1;
    714     }
    715 
    716     // Note value = 0 (off) means muted
    717     enabled = (bool) !value;
    718 
    719     return 0;
    720 }
    721 
    722 int32_t AudioMixerManagerLinuxALSA::MicrophoneMuteIsAvailable(
    723     bool& available)
    724 {
    725     if (_inputMixerElement == NULL)
    726     {
    727         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    728                      "  no avaliable input mixer element exists");
    729         return -1;
    730     }
    731 
    732     available = LATE(snd_mixer_selem_has_capture_switch)(_inputMixerElement);
    733     return 0;
    734 }
    735 
    736 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneMute(bool enable)
    737 {
    738     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    739                  "AudioMixerManagerLinuxALSA::SetMicrophoneMute(enable=%u)",
    740                  enable);
    741 
    742     CriticalSectionScoped lock(&_critSect);
    743 
    744     if (_inputMixerElement == NULL)
    745     {
    746         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    747                      "  no avaliable input mixer element exists");
    748         return -1;
    749     }
    750 
    751     // Ensure that the selected microphone destination has a valid mute control.
    752     bool available(false);
    753     MicrophoneMuteIsAvailable(available);
    754     if (!available)
    755     {
    756         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    757                      "  it is not possible to mute the microphone");
    758         return -1;
    759     }
    760 
    761     // Note value = 0 (off) means muted
    762     int errVal =
    763         LATE(snd_mixer_selem_set_capture_switch_all)(_inputMixerElement,
    764                                                      !enable);
    765     if (errVal < 0)
    766     {
    767         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    768                      "     Error setting capture switch: %s",
    769                      LATE(snd_strerror)(errVal));
    770         return -1;
    771     }
    772 
    773     return (0);
    774 }
    775 
    776 int32_t AudioMixerManagerLinuxALSA::MicrophoneMute(bool& enabled) const
    777 {
    778 
    779     if (_inputMixerElement == NULL)
    780     {
    781         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    782                      "  no avaliable input mixer exists");
    783         return -1;
    784     }
    785 
    786     // Ensure that the selected microphone destination has a valid mute control.
    787     bool available =
    788         LATE(snd_mixer_selem_has_capture_switch)(_inputMixerElement);
    789     if (!available)
    790     {
    791         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    792                      "  it is not possible to mute the microphone");
    793         return -1;
    794     }
    795 
    796     int value(false);
    797 
    798     // Retrieve one boolean control value for a specified mute-control
    799     //
    800     int
    801         errVal = LATE(snd_mixer_selem_get_capture_switch)(
    802             _inputMixerElement,
    803             (snd_mixer_selem_channel_id_t) 0,
    804             &value);
    805     if (errVal < 0)
    806     {
    807         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    808                      "     Error getting capture switch: %s",
    809                      LATE(snd_strerror)(errVal));
    810         return -1;
    811     }
    812 
    813     // Note value = 0 (off) means muted
    814     enabled = (bool) !value;
    815 
    816     return 0;
    817 }
    818 
    819 int32_t AudioMixerManagerLinuxALSA::MicrophoneBoostIsAvailable(
    820     bool& available)
    821 {
    822     if (_inputMixerHandle == NULL)
    823     {
    824         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    825                      "  no avaliable input mixer exists");
    826         return -1;
    827     }
    828 
    829     // Microphone boost cannot be enabled through ALSA Simple Mixer Interface
    830     available = false;
    831 
    832     return 0;
    833 }
    834 
    835 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneBoost(bool enable)
    836 {
    837     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    838                  "AudioMixerManagerLinuxALSA::SetMicrophoneBoost(enable=%u)",
    839                  enable);
    840 
    841     CriticalSectionScoped lock(&_critSect);
    842 
    843     if (_inputMixerHandle == NULL)
    844     {
    845         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    846                      "  no avaliable input mixer exists");
    847         return -1;
    848     }
    849 
    850     // Ensure that the selected microphone destination has a valid mute control.
    851     bool available(false);
    852     MicrophoneMuteIsAvailable(available);
    853     if (!available)
    854     {
    855         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    856                      "  it is not possible to enable microphone boost");
    857         return -1;
    858     }
    859 
    860     // It is assumed that the call above fails!
    861 
    862     return (0);
    863 }
    864 
    865 int32_t AudioMixerManagerLinuxALSA::MicrophoneBoost(bool& enabled) const
    866 {
    867 
    868     if (_inputMixerHandle == NULL)
    869     {
    870         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    871                      "  no avaliable input mixer exists");
    872         return -1;
    873     }
    874 
    875     // Microphone boost cannot be enabled on this platform!
    876     enabled = false;
    877 
    878     return 0;
    879 }
    880 
    881 int32_t AudioMixerManagerLinuxALSA::MicrophoneVolumeIsAvailable(
    882     bool& available)
    883 {
    884     if (_inputMixerElement == NULL)
    885     {
    886         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    887                      "  no avaliable input mixer element exists");
    888         return -1;
    889     }
    890 
    891     available = LATE(snd_mixer_selem_has_capture_volume)(_inputMixerElement);
    892 
    893     return 0;
    894 }
    895 
    896 int32_t AudioMixerManagerLinuxALSA::SetMicrophoneVolume(
    897     uint32_t volume)
    898 {
    899     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    900                  "AudioMixerManagerLinuxALSA::SetMicrophoneVolume(volume=%u)",
    901                  volume);
    902 
    903     CriticalSectionScoped lock(&_critSect);
    904 
    905     if (_inputMixerElement == NULL)
    906     {
    907         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    908                      "  no avaliable input mixer element exists");
    909         return -1;
    910     }
    911 
    912     int
    913         errVal =
    914             LATE(snd_mixer_selem_set_capture_volume_all)(_inputMixerElement,
    915                                                          volume);
    916     if (errVal < 0)
    917     {
    918         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    919                      "     Error changing microphone volume: %s",
    920                      LATE(snd_strerror)(errVal));
    921         return -1;
    922     }
    923 
    924     return (0);
    925 }
    926 
    927 // TL: Have done testnig with these but they don't seem reliable and
    928 // they were therefore not added
    929 /*
    930  // ----------------------------------------------------------------------------
    931  //    SetMaxMicrophoneVolume
    932  // ----------------------------------------------------------------------------
    933 
    934  int32_t AudioMixerManagerLinuxALSA::SetMaxMicrophoneVolume(
    935      uint32_t maxVolume)
    936  {
    937 
    938  if (_inputMixerElement == NULL)
    939  {
    940  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    941   "  no avaliable output mixer element exists");
    942  return -1;
    943  }
    944 
    945  long int minVol(0);
    946  long int maxVol(0);
    947 
    948  int errVal = snd_mixer_selem_get_capture_volume_range(_inputMixerElement,
    949   &minVol, &maxVol);
    950  if ((maxVol <= minVol) || (errVal != 0))
    951  {
    952  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    953   "     Error getting capture volume range: %s", snd_strerror(errVal));
    954  }
    955 
    956  maxVol = (long int)maxVolume;
    957  printf("min %d max %d", minVol, maxVol);
    958  errVal = snd_mixer_selem_set_capture_volume_range(_inputMixerElement, minVol, maxVol);
    959  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
    960  "     Capture hardware volume range, min: %d, max: %d", minVol, maxVol);
    961  if (errVal != 0)
    962  {
    963  WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
    964   "     Error setting capture volume range: %s", snd_strerror(errVal));
    965  return -1;
    966  }
    967 
    968  return 0;
    969  }
    970 
    971  // ----------------------------------------------------------------------------
    972  //    SetMinMicrophoneVolume
    973  // ----------------------------------------------------------------------------
    974 
    975  int32_t AudioMixerManagerLinuxALSA::SetMinMicrophoneVolume(
    976  uint32_t minVolume)
    977  {
    978 
    979  if (_inputMixerElement == NULL)
    980  {
    981  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    982   "  no avaliable output mixer element exists");
    983  return -1;
    984  }
    985 
    986  long int minVol(0);
    987  long int maxVol(0);
    988 
    989  int errVal = snd_mixer_selem_get_capture_volume_range(
    990  _inputMixerElement, &minVol, &maxVol);
    991  if (maxVol <= minVol)
    992  {
    993  //maxVol = 255;
    994  WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
    995   "     Error getting capture volume range: %s", snd_strerror(errVal));
    996  }
    997 
    998  printf("min %d max %d", minVol, maxVol);
    999  minVol = (long int)minVolume;
   1000  errVal = snd_mixer_selem_set_capture_volume_range(
   1001  _inputMixerElement, minVol, maxVol);
   1002  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1003   "     Capture hardware volume range, min: %d, max: %d", minVol, maxVol);
   1004  if (errVal != 0)
   1005  {
   1006  WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1007   "     Error setting capture volume range: %s", snd_strerror(errVal));
   1008  return -1;
   1009  }
   1010 
   1011  return 0;
   1012  }
   1013  */
   1014 
   1015 int32_t AudioMixerManagerLinuxALSA::MicrophoneVolume(
   1016     uint32_t& volume) const
   1017 {
   1018 
   1019     if (_inputMixerElement == NULL)
   1020     {
   1021         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
   1022                      "  no avaliable input mixer element exists");
   1023         return -1;
   1024     }
   1025 
   1026     long int vol(0);
   1027 
   1028     int
   1029         errVal =
   1030             LATE(snd_mixer_selem_get_capture_volume)(
   1031                 _inputMixerElement,
   1032                 (snd_mixer_selem_channel_id_t) 0,
   1033                 &vol);
   1034     if (errVal < 0)
   1035     {
   1036         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1037                      "Error getting inputvolume: %s",
   1038                      LATE(snd_strerror)(errVal));
   1039         return -1;
   1040     }
   1041     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1042                  "     AudioMixerManagerLinuxALSA::MicrophoneVolume() => vol=%i",
   1043                  vol);
   1044 
   1045     volume = static_cast<uint32_t> (vol);
   1046 
   1047     return 0;
   1048 }
   1049 
   1050 int32_t AudioMixerManagerLinuxALSA::MaxMicrophoneVolume(
   1051     uint32_t& maxVolume) const
   1052 {
   1053 
   1054     if (_inputMixerElement == NULL)
   1055     {
   1056         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
   1057                      "  no avaliable input mixer element exists");
   1058         return -1;
   1059     }
   1060 
   1061     long int minVol(0);
   1062     long int maxVol(0);
   1063 
   1064     // check if we have mic volume at all
   1065     if (!LATE(snd_mixer_selem_has_capture_volume)(_inputMixerElement))
   1066     {
   1067         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1068                      "     No microphone volume available");
   1069         return -1;
   1070     }
   1071 
   1072     int errVal =
   1073         LATE(snd_mixer_selem_get_capture_volume_range)(_inputMixerElement,
   1074                                                        &minVol, &maxVol);
   1075 
   1076     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1077                  "     Microphone hardware volume range, min: %d, max: %d",
   1078                  minVol, maxVol);
   1079     if (maxVol <= minVol)
   1080     {
   1081         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1082                      "     Error getting microphone volume range: %s",
   1083                      LATE(snd_strerror)(errVal));
   1084     }
   1085 
   1086     maxVolume = static_cast<uint32_t> (maxVol);
   1087 
   1088     return 0;
   1089 }
   1090 
   1091 int32_t AudioMixerManagerLinuxALSA::MinMicrophoneVolume(
   1092     uint32_t& minVolume) const
   1093 {
   1094 
   1095     if (_inputMixerElement == NULL)
   1096     {
   1097         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
   1098                      "  no avaliable input mixer element exists");
   1099         return -1;
   1100     }
   1101 
   1102     long int minVol(0);
   1103     long int maxVol(0);
   1104 
   1105     int errVal =
   1106         LATE(snd_mixer_selem_get_capture_volume_range)(_inputMixerElement,
   1107                                                        &minVol, &maxVol);
   1108 
   1109     WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1110                  "     Microphone hardware volume range, min: %d, max: %d",
   1111                  minVol, maxVol);
   1112     if (maxVol <= minVol)
   1113     {
   1114         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1115                      "     Error getting microphone volume range: %s",
   1116                      LATE(snd_strerror)(errVal));
   1117     }
   1118 
   1119     minVolume = static_cast<uint32_t> (minVol);
   1120 
   1121     return 0;
   1122 }
   1123 
   1124 int32_t AudioMixerManagerLinuxALSA::MicrophoneVolumeStepSize(
   1125     uint16_t& stepSize) const
   1126 {
   1127 
   1128     if (_inputMixerHandle == NULL)
   1129     {
   1130         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
   1131                      "  no avaliable input mixer exists");
   1132         return -1;
   1133     }
   1134 
   1135     // The step size is always 1 for ALSA
   1136     stepSize = 1;
   1137 
   1138     return 0;
   1139 }
   1140 
   1141 // ============================================================================
   1142 //                                 Private Methods
   1143 // ============================================================================
   1144 
   1145 int32_t AudioMixerManagerLinuxALSA::LoadMicMixerElement() const
   1146 {
   1147     int errVal = LATE(snd_mixer_load)(_inputMixerHandle);
   1148     if (errVal < 0)
   1149     {
   1150         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1151                      "snd_mixer_load(_inputMixerHandle), error: %s",
   1152                      LATE(snd_strerror)(errVal));
   1153         _inputMixerHandle = NULL;
   1154         return -1;
   1155     }
   1156 
   1157     snd_mixer_elem_t *elem = NULL;
   1158     snd_mixer_elem_t *micElem = NULL;
   1159     unsigned mixerIdx = 0;
   1160     const char *selemName = NULL;
   1161 
   1162     // Find and store handles to the right mixer elements
   1163     for (elem = LATE(snd_mixer_first_elem)(_inputMixerHandle); elem; elem
   1164         = LATE(snd_mixer_elem_next)(elem), mixerIdx++)
   1165     {
   1166         if (LATE(snd_mixer_selem_is_active)(elem))
   1167         {
   1168             selemName = LATE(snd_mixer_selem_get_name)(elem);
   1169             if (strcmp(selemName, "Capture") == 0) // "Capture", "Mic"
   1170             {
   1171                 _inputMixerElement = elem;
   1172                 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice,
   1173                              _id, "     Capture element set");
   1174             } else if (strcmp(selemName, "Mic") == 0)
   1175             {
   1176                 micElem = elem;
   1177                 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice,
   1178                              _id, "     Mic element found");
   1179             }
   1180         }
   1181 
   1182         if (_inputMixerElement)
   1183         {
   1184             // Use the first Capture element that is found
   1185             // The second one may not work
   1186             break;
   1187         }
   1188     }
   1189 
   1190     if (_inputMixerElement == NULL)
   1191     {
   1192         // We didn't find a Capture handle, use Mic.
   1193         if (micElem != NULL)
   1194         {
   1195             _inputMixerElement = micElem;
   1196             WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1197                          "     Using Mic as capture volume.");
   1198         } else
   1199         {
   1200             _inputMixerElement = NULL;
   1201             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1202                          "Could not find capture volume on the mixer.");
   1203 
   1204             return -1;
   1205         }
   1206     }
   1207 
   1208     return 0;
   1209 }
   1210 
   1211 int32_t AudioMixerManagerLinuxALSA::LoadSpeakerMixerElement() const
   1212 {
   1213     int errVal = LATE(snd_mixer_load)(_outputMixerHandle);
   1214     if (errVal < 0)
   1215     {
   1216         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1217                      "     snd_mixer_load(_outputMixerHandle), error: %s",
   1218                      LATE(snd_strerror)(errVal));
   1219         _outputMixerHandle = NULL;
   1220         return -1;
   1221     }
   1222 
   1223     snd_mixer_elem_t *elem = NULL;
   1224     snd_mixer_elem_t *masterElem = NULL;
   1225     snd_mixer_elem_t *speakerElem = NULL;
   1226     unsigned mixerIdx = 0;
   1227     const char *selemName = NULL;
   1228 
   1229     // Find and store handles to the right mixer elements
   1230     for (elem = LATE(snd_mixer_first_elem)(_outputMixerHandle); elem; elem
   1231         = LATE(snd_mixer_elem_next)(elem), mixerIdx++)
   1232     {
   1233         if (LATE(snd_mixer_selem_is_active)(elem))
   1234         {
   1235             selemName = LATE(snd_mixer_selem_get_name)(elem);
   1236             WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1237                          "snd_mixer_selem_get_name %d: %s =%x", mixerIdx,
   1238                          selemName, elem);
   1239 
   1240             // "Master", "PCM", "Wave", "Master Mono", "PC Speaker", "PCM", "Wave"
   1241             if (strcmp(selemName, "PCM") == 0)
   1242             {
   1243                 _outputMixerElement = elem;
   1244                 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice,
   1245                              _id, "     PCM element set");
   1246             } else if (strcmp(selemName, "Master") == 0)
   1247             {
   1248                 masterElem = elem;
   1249                 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice,
   1250                              _id, "     Master element found");
   1251             } else if (strcmp(selemName, "Speaker") == 0)
   1252             {
   1253                 speakerElem = elem;
   1254                 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice,
   1255                              _id, "     Speaker element found");
   1256             }
   1257         }
   1258 
   1259         if (_outputMixerElement)
   1260         {
   1261             // We have found the element we want
   1262             break;
   1263         }
   1264     }
   1265 
   1266     // If we didn't find a PCM Handle, use Master or Speaker
   1267     if (_outputMixerElement == NULL)
   1268     {
   1269         if (masterElem != NULL)
   1270         {
   1271             _outputMixerElement = masterElem;
   1272             WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1273                          "     Using Master as output volume.");
   1274         } else if (speakerElem != NULL)
   1275         {
   1276             _outputMixerElement = speakerElem;
   1277             WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
   1278                          "     Using Speaker as output volume.");
   1279         } else
   1280         {
   1281             _outputMixerElement = NULL;
   1282             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
   1283                          "Could not find output volume in the mixer.");
   1284             return -1;
   1285         }
   1286     }
   1287 
   1288     return 0;
   1289 }
   1290 
   1291 void AudioMixerManagerLinuxALSA::GetControlName(char* controlName,
   1292                                                 char* deviceName) const
   1293 {
   1294     // Example
   1295     // deviceName: "front:CARD=Intel,DEV=0"
   1296     // controlName: "hw:CARD=Intel"
   1297     char* pos1 = strchr(deviceName, ':');
   1298     char* pos2 = strchr(deviceName, ',');
   1299     if (!pos2)
   1300     {
   1301         // Can also be default:CARD=Intel
   1302         pos2 = &deviceName[strlen(deviceName)];
   1303     }
   1304     if (pos1 && pos2)
   1305     {
   1306         strcpy(controlName, "hw");
   1307         int nChar = (int) (pos2 - pos1);
   1308         strncpy(&controlName[2], pos1, nChar);
   1309         controlName[2 + nChar] = '\0';
   1310     } else
   1311     {
   1312         strcpy(controlName, deviceName);
   1313     }
   1314 
   1315 }
   1316 
   1317 }
   1318