15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/openbsd/audio_manager_openbsd.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_path.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_output_dispatcher.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_parameters.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/pulse/pulse_output.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/pulse/pulse_stubs.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/channel_layout.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_switches.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using media_audio_pulse::kModulePulse; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using media_audio_pulse::InitializeStubs; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using media_audio_pulse::StubPathMap; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum number of output streams that can be open simultaneously. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxOutputStreams = 50; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default sample rate for input and output streams. 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const int kDefaultSampleRate = 48000; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kPulseLib[] = 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FILE_PATH_LITERAL("libpulse.so.0"); 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of AudioManager. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool HasAudioHardware() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *file; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((file = getenv("AUDIOCTLDEVICE")) == 0 || *file == '\0') 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file = "/dev/audioctl"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((fd = open(file, O_RDONLY)) < 0) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close(fd); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AudioManagerOpenBSD::HasAudioOutputDevices() { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HasAudioHardware(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AudioManagerOpenBSD::HasAudioInputDevices() { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HasAudioHardware(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioParameters AudioManagerOpenBSD::GetInputStreamParameters( 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& device_id) { 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kDefaultInputBufferSize = 1024; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int user_buffer_size = GetUserBufferSize(); 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int buffer_size = user_buffer_size ? 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) user_buffer_size : kDefaultInputBufferSize; 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return AudioParameters( 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kDefaultSampleRate, 16, buffer_size); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)AudioManagerOpenBSD::AudioManagerOpenBSD(AudioLogFactory* audio_log_factory) 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : AudioManagerBase(audio_log_factory), 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pulse_library_is_initialized_(false) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMaxOutputStreamsAllowed(kMaxOutputStreams); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StubPathMap paths; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if the pulse library is avialbale. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) paths[kModulePulse].push_back(kPulseLib); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!InitializeStubs(paths)) { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(WARNING) << "Failed on loading the Pulse library and symbols"; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pulse_library_is_initialized_ = true; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioManagerOpenBSD::~AudioManagerOpenBSD() { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Shutdown(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioParameters& params) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MakeOutputStream(params); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream( 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const AudioParameters& params, 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& device_id) { 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MakeOutputStream(params); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioParameters& params, const std::string& device_id) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream( 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioParameters& params, const std::string& device_id) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters( 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::string& output_device_id, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const AudioParameters& input_params) { 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // TODO(tommi): Support |output_device_id|. 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const int kDefaultOutputBufferSize = 512; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int sample_rate = kDefaultSampleRate; 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int buffer_size = kDefaultOutputBufferSize; 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bits_per_sample = 16; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (input_params.IsValid()) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sample_rate = input_params.sample_rate(); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bits_per_sample = input_params.bits_per_sample(); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) channel_layout = input_params.channel_layout(); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer_size = std::min(buffer_size, input_params.frames_per_buffer()); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int user_buffer_size = GetUserBufferSize(); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (user_buffer_size) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer_size = user_buffer_size; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return AudioParameters( 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioParameters& params) { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pulse_library_is_initialized_) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new PulseAudioOutputStream(params, this); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(xians): Merge AudioManagerOpenBSD with AudioManagerPulse; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) { 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return new AudioManagerOpenBSD(audio_log_factory); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 161