Home | History | Annotate | Download | only in cras
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/audio/cras/audio_manager_cras.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/command_line.h"
     10 #include "base/environment.h"
     11 #include "base/logging.h"
     12 #include "base/nix/xdg_util.h"
     13 #include "base/stl_util.h"
     14 #include "media/audio/cras/cras_input.h"
     15 #include "media/audio/cras/cras_unified.h"
     16 #include "media/base/channel_layout.h"
     17 
     18 // cras_util.h headers pull in min/max macros...
     19 // TODO(dgreid): Fix headers such that these aren't imported.
     20 #undef min
     21 #undef max
     22 
     23 namespace media {
     24 
     25 static void AddDefaultDevice(AudioDeviceNames* device_names) {
     26   DCHECK(device_names->empty());
     27 
     28   // Cras will route audio from a proper physical device automatically.
     29   device_names->push_back(
     30       AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
     31                       AudioManagerBase::kDefaultDeviceId));
     32 }
     33 
     34 // Maximum number of output streams that can be open simultaneously.
     35 static const int kMaxOutputStreams = 50;
     36 
     37 // Default sample rate for input and output streams.
     38 static const int kDefaultSampleRate = 48000;
     39 
     40 // Define bounds for the output buffer size.
     41 static const int kMinimumOutputBufferSize = 512;
     42 static const int kMaximumOutputBufferSize = 8192;
     43 
     44 // Default input buffer size.
     45 static const int kDefaultInputBufferSize = 1024;
     46 
     47 bool AudioManagerCras::HasAudioOutputDevices() {
     48   return true;
     49 }
     50 
     51 bool AudioManagerCras::HasAudioInputDevices() {
     52   return true;
     53 }
     54 
     55 AudioManagerCras::AudioManagerCras(AudioLogFactory* audio_log_factory)
     56     : AudioManagerBase(audio_log_factory),
     57       has_keyboard_mic_(false) {
     58   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
     59 }
     60 
     61 AudioManagerCras::~AudioManagerCras() {
     62   Shutdown();
     63 }
     64 
     65 void AudioManagerCras::ShowAudioInputSettings() {
     66   NOTIMPLEMENTED();
     67 }
     68 
     69 void AudioManagerCras::GetAudioInputDeviceNames(
     70     AudioDeviceNames* device_names) {
     71   AddDefaultDevice(device_names);
     72 }
     73 
     74 void AudioManagerCras::GetAudioOutputDeviceNames(
     75     AudioDeviceNames* device_names) {
     76   AddDefaultDevice(device_names);
     77 }
     78 
     79 AudioParameters AudioManagerCras::GetInputStreamParameters(
     80     const std::string& device_id) {
     81   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
     82 
     83   int user_buffer_size = GetUserBufferSize();
     84   int buffer_size = user_buffer_size ?
     85       user_buffer_size : kDefaultInputBufferSize;
     86   AudioParameters::PlatformEffectsMask effects =
     87       has_keyboard_mic_ ? AudioParameters::KEYBOARD_MIC
     88                         : AudioParameters::NO_EFFECTS;
     89 
     90   // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal
     91   // parameters for the loopback stream may differ from the default.
     92   return AudioParameters(
     93       AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
     94       kDefaultSampleRate, 16, buffer_size, effects);
     95 }
     96 
     97 void AudioManagerCras::SetHasKeyboardMic() {
     98   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
     99   has_keyboard_mic_ = true;
    100 }
    101 
    102 AudioOutputStream* AudioManagerCras::MakeLinearOutputStream(
    103     const AudioParameters& params) {
    104   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    105   return MakeOutputStream(params);
    106 }
    107 
    108 AudioOutputStream* AudioManagerCras::MakeLowLatencyOutputStream(
    109     const AudioParameters& params,
    110     const std::string& device_id) {
    111   DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
    112   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    113   // TODO(dgreid): Open the correct input device for unified IO.
    114   return MakeOutputStream(params);
    115 }
    116 
    117 AudioInputStream* AudioManagerCras::MakeLinearInputStream(
    118     const AudioParameters& params, const std::string& device_id) {
    119   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    120   return MakeInputStream(params, device_id);
    121 }
    122 
    123 AudioInputStream* AudioManagerCras::MakeLowLatencyInputStream(
    124     const AudioParameters& params, const std::string& device_id) {
    125   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    126   return MakeInputStream(params, device_id);
    127 }
    128 
    129 AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
    130     const std::string& output_device_id,
    131     const AudioParameters& input_params) {
    132   // TODO(tommi): Support |output_device_id|.
    133   DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
    134   ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
    135   int sample_rate = kDefaultSampleRate;
    136   int buffer_size = kMinimumOutputBufferSize;
    137   int bits_per_sample = 16;
    138   if (input_params.IsValid()) {
    139     sample_rate = input_params.sample_rate();
    140     bits_per_sample = input_params.bits_per_sample();
    141     channel_layout = input_params.channel_layout();
    142     buffer_size =
    143         std::min(kMaximumOutputBufferSize,
    144                  std::max(buffer_size, input_params.frames_per_buffer()));
    145   }
    146 
    147   int user_buffer_size = GetUserBufferSize();
    148   if (user_buffer_size)
    149     buffer_size = user_buffer_size;
    150 
    151   return AudioParameters(
    152       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
    153       sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
    154 }
    155 
    156 AudioOutputStream* AudioManagerCras::MakeOutputStream(
    157     const AudioParameters& params) {
    158   return new CrasUnifiedStream(params, this);
    159 }
    160 
    161 AudioInputStream* AudioManagerCras::MakeInputStream(
    162     const AudioParameters& params, const std::string& device_id) {
    163   return new CrasInputStream(params, this, device_id);
    164 }
    165 
    166 snd_pcm_format_t AudioManagerCras::BitsToFormat(int bits_per_sample) {
    167   switch (bits_per_sample) {
    168     case 8:
    169       return SND_PCM_FORMAT_U8;
    170     case 16:
    171       return SND_PCM_FORMAT_S16;
    172     case 24:
    173       return SND_PCM_FORMAT_S24;
    174     case 32:
    175       return SND_PCM_FORMAT_S32;
    176     default:
    177       return SND_PCM_FORMAT_UNKNOWN;
    178   }
    179 }
    180 
    181 }  // namespace media
    182