blob: a4ffff5a8c5759e56f1441631a20d41218b6b5fe [file] [log] [blame]
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/audio/ios/audio_manager_ios.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#include "base/sys_info.h"
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/mac/audio_input_mac.h"
#include "media/base/limits.h"
namespace media {
enum { kMaxInputChannels = 2 };
// Initializes the audio session, returning a bool indicating whether
// initialization was successful. Should only be called once.
static bool InitAudioSessionInternal() {
OSStatus error = AudioSessionInitialize(NULL, NULL, NULL, NULL);
DCHECK(error != kAudioSessionAlreadyInitialized);
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
BOOL result = [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord
error:nil];
DCHECK(result);
UInt32 allowMixing = true;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers,
sizeof(allowMixing), &allowMixing);
return error == kAudioSessionNoError;
}
AudioManagerIOS::AudioManagerIOS() {
}
AudioManagerIOS::~AudioManagerIOS() {
Shutdown();
}
bool AudioManagerIOS::HasAudioOutputDevices() {
return false;
}
bool AudioManagerIOS::HasAudioInputDevices() {
if (!InitAudioSession())
return false;
// Note that the |kAudioSessionProperty_AudioInputAvailable| property is a
// 32-bit integer, not a boolean.
UInt32 property_size;
OSStatus error =
AudioSessionGetPropertySize(kAudioSessionProperty_AudioInputAvailable,
&property_size);
if (error != kAudioSessionNoError)
return false;
UInt32 audio_input_is_available = false;
DCHECK(property_size == sizeof(audio_input_is_available));
error = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable,
&property_size,
&audio_input_is_available);
return error == kAudioSessionNoError ? audio_input_is_available : false;
}
AudioOutputStream* AudioManagerIOS::MakeAudioOutputStream(
const AudioParameters& params) {
NOTIMPLEMENTED(); // Only input is supported on iOS.
return NULL;
}
AudioInputStream* AudioManagerIOS::MakeAudioInputStream(
const AudioParameters& params, const std::string& device_id) {
// Current line of iOS devices has only one audio input.
// Ignore the device_id (unittest uses a test value in it).
if (!params.IsValid() || (params.channels() > kMaxInputChannels))
return NULL;
if (params.format() == AudioParameters::AUDIO_FAKE)
return FakeAudioInputStream::MakeFakeStream(this, params);
else if (params.format() == AudioParameters::AUDIO_PCM_LINEAR)
return new PCMQueueInAudioInputStream(this, params);
return NULL;
}
AudioOutputStream* AudioManagerIOS::MakeLinearOutputStream(
const AudioParameters& params) {
NOTIMPLEMENTED(); // Only input is supported on iOS.
return NULL;
}
AudioOutputStream* AudioManagerIOS::MakeLowLatencyOutputStream(
const AudioParameters& params) {
NOTIMPLEMENTED(); // Only input is supported on iOS.
return NULL;
}
AudioInputStream* AudioManagerIOS::MakeLinearInputStream(
const AudioParameters& params, const std::string& device_id) {
return MakeAudioInputStream(params, device_id);
}
AudioInputStream* AudioManagerIOS::MakeLowLatencyInputStream(
const AudioParameters& params, const std::string& device_id) {
NOTIMPLEMENTED(); // Only linear audio input is supported on iOS.
return MakeAudioInputStream(params, device_id);
}
// Called by the stream when it has been released by calling Close().
void AudioManagerIOS::ReleaseOutputStream(AudioOutputStream* stream) {
NOTIMPLEMENTED(); // Only input is supported on iOS.
}
// Called by the stream when it has been released by calling Close().
void AudioManagerIOS::ReleaseInputStream(AudioInputStream* stream) {
delete stream;
}
bool AudioManagerIOS::InitAudioSession() {
static const bool kSessionInitialized = InitAudioSessionInternal();
return kSessionInitialized;
}
// static
AudioManager* CreateAudioManager() {
return new AudioManagerIOS();
}
} // namespace media