diff options
author | Xiaopeng Yang <xiaopeng.yang@windriver.com> | 2008-11-19 16:33:20 +0800 |
---|---|---|
committer | Xiaopeng Yang <xiaopeng.yang@windriver.com> | 2008-11-19 16:33:20 +0800 |
commit | 48e8b3bac91275743bd62d01e4d1e7a30396dad4 (patch) | |
tree | 84d0c2d3fb6db54a1e6c4897cca9cede6957fc12 | |
download | alsa_sound-48e8b3bac91275743bd62d01e4d1e7a30396dad4.tar.gz |
Template files from frameworks/base/libs/audioflinger
-rw-r--r-- | AudioHardwareInterface.cpp | 240 | ||||
-rw-r--r-- | AudioHardwareStub.cpp | 175 | ||||
-rw-r--r-- | AudioHardwareStub.h | 95 |
3 files changed, 510 insertions, 0 deletions
diff --git a/AudioHardwareInterface.cpp b/AudioHardwareInterface.cpp new file mode 100644 index 0000000..7387b3d --- /dev/null +++ b/AudioHardwareInterface.cpp @@ -0,0 +1,240 @@ +/* +** +** Copyright 2007, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include <cutils/properties.h> +#include <string.h> +#include <unistd.h> + +#define LOG_TAG "AudioHardwareInterface" +#include <utils/Log.h> +#include <utils/String8.h> + +#include "AudioHardwareStub.h" +#include "AudioHardwareGeneric.h" + +// #define DUMP_FLINGER_OUT // if defined allows recording samples in a file +#ifdef DUMP_FLINGER_OUT +#include "AudioDumpInterface.h" +#endif + + +// change to 1 to log routing calls +#define LOG_ROUTING_CALLS 0 + +namespace android { + +#if LOG_ROUTING_CALLS +static const char* routingModeStrings[] = +{ + "OUT OF RANGE", + "INVALID", + "CURRENT", + "NORMAL", + "RINGTONE", + "IN_CALL" +}; + +static const char* routeStrings[] = +{ + "EARPIECE ", + "SPEAKER ", + "BLUETOOTH ", + "HEADSET " +}; +static const char* routeNone = "NONE"; + +static const char* displayMode(int mode) +{ + if ((mode < -2) || (mode > 2)) + return routingModeStrings[0]; + return routingModeStrings[mode+3]; +} + +static const char* displayRoutes(uint32_t routes) +{ + static char routeStr[80]; + if (routes == 0) + return routeNone; + routeStr[0] = 0; + int bitMask = 1; + for (int i = 0; i < 4; ++i, bitMask <<= 1) { + if (routes & bitMask) { + strcat(routeStr, routeStrings[i]); + } + } + routeStr[strlen(routeStr)-1] = 0; + return routeStr; +} +#endif + +// ---------------------------------------------------------------------------- + +AudioHardwareInterface* AudioHardwareInterface::create() +{ + /* + * FIXME: This code needs to instantiate the correct audio device + * interface. For now - we use compile-time switches. + */ + AudioHardwareInterface* hw = 0; + char value[PROPERTY_VALUE_MAX]; + +#ifdef GENERIC_AUDIO + hw = new AudioHardwareGeneric(); +#else + // if running in emulation - use the emulator driver + if (property_get("ro.kernel.qemu", value, 0)) { + LOGD("Running in emulation - using generic audio driver"); + hw = new AudioHardwareGeneric(); + } + else { + LOGV("Creating Vendor Specific AudioHardware"); + hw = createAudioHardware(); + } +#endif + if (hw->initCheck() != NO_ERROR) { + LOGW("Using stubbed audio hardware. No sound will be produced."); + delete hw; + hw = new AudioHardwareStub(); + } + +#ifdef DUMP_FLINGER_OUT + // This code adds a record of buffers in a file to write calls made by AudioFlinger. + // It replaces the current AudioHardwareInterface object by an intermediate one which + // will record buffers in a file (after sending them to hardware) for testing purpose. + // This feature is enabled by defining symbol DUMP_FLINGER_OUT and setting environement + // "audioflinger.dump = 1". The output file is "tmp/FlingerOut.pcm". Pause are not recorded + // in the file. + + // read dump mode + property_get("audioflinger.dump", value, "0"); + switch(value[0]) { + case '1': + LOGV("Dump mode"); + hw = new AudioDumpInterface(hw); // replace interface + return hw; + break; + case '0': + default: + LOGV("No Dump mode"); + return hw; + break; + } +#endif + return hw; +} + +AudioStreamOut::~AudioStreamOut() +{ +} + +AudioStreamIn::~AudioStreamIn() {} + +AudioHardwareInterface::AudioHardwareInterface() +{ + // force a routing update on initialization + memset(&mRoutes, 0, sizeof(mRoutes)); + mMode = 0; +} + +// generics for audio routing - the real work is done in doRouting +status_t AudioHardwareInterface::setRouting(int mode, uint32_t routes) +{ +#if LOG_ROUTING_CALLS + LOGD("setRouting: mode=%s, routes=[%s]", displayMode(mode), displayRoutes(routes)); +#endif + if (mode == AudioSystem::MODE_CURRENT) + mode = mMode; + if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) + return BAD_VALUE; + uint32_t old = mRoutes[mode]; + mRoutes[mode] = routes; + if ((mode != mMode) || (old == routes)) + return NO_ERROR; +#if LOG_ROUTING_CALLS + const char* oldRouteStr = strdup(displayRoutes(old)); + LOGD("doRouting: mode=%s, old route=[%s], new route=[%s]", + displayMode(mode), oldRouteStr, displayRoutes(routes)); + delete oldRouteStr; +#endif + return doRouting(); +} + +status_t AudioHardwareInterface::getRouting(int mode, uint32_t* routes) +{ + if (mode == AudioSystem::MODE_CURRENT) + mode = mMode; + if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) + return BAD_VALUE; + *routes = mRoutes[mode]; +#if LOG_ROUTING_CALLS + LOGD("getRouting: mode=%s, routes=[%s]", + displayMode(mode), displayRoutes(*routes)); +#endif + return NO_ERROR; +} + +status_t AudioHardwareInterface::setMode(int mode) +{ +#if LOG_ROUTING_CALLS + LOGD("setMode(%s)", displayMode(mode)); +#endif + if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) + return BAD_VALUE; + if (mMode == mode) + return NO_ERROR; +#if LOG_ROUTING_CALLS + LOGD("doRouting: old mode=%s, new mode=%s route=[%s]", + displayMode(mMode), displayMode(mode), displayRoutes(mRoutes[mode])); +#endif + mMode = mode; + return doRouting(); +} + +status_t AudioHardwareInterface::getMode(int* mode) +{ + // Implement: set audio routing + *mode = mMode; + return NO_ERROR; +} + +status_t AudioHardwareInterface::setParameter(const char* key, const char* value) +{ + // default implementation is to ignore + return NO_ERROR; +} + +status_t AudioHardwareInterface::dumpState(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, SIZE, "AudioHardwareInterface::dumpState\n"); + result.append(buffer); + snprintf(buffer, SIZE, "\tmMode: %d\n", mMode); + result.append(buffer); + for (int i = 0, n = AudioSystem::NUM_MODES; i < n; ++i) { + snprintf(buffer, SIZE, "\tmRoutes[%d]: %d\n", i, mRoutes[i]); + result.append(buffer); + } + ::write(fd, result.string(), result.size()); + dump(fd, args); // Dump the state of the concrete child. + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/AudioHardwareStub.cpp b/AudioHardwareStub.cpp new file mode 100644 index 0000000..0046db8 --- /dev/null +++ b/AudioHardwareStub.cpp @@ -0,0 +1,175 @@ +/* //device/servers/AudioFlinger/AudioHardwareStub.cpp +** +** Copyright 2007, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include <stdint.h> +#include <sys/types.h> + +#include <stdlib.h> +#include <unistd.h> +#include <utils/String8.h> + +#include "AudioHardwareStub.h" + +namespace android { + +// ---------------------------------------------------------------------------- + +AudioHardwareStub::AudioHardwareStub() : mMicMute(false) +{ +} + +AudioHardwareStub::~AudioHardwareStub() +{ +} + +status_t AudioHardwareStub::initCheck() +{ + return NO_ERROR; +} + +status_t AudioHardwareStub::standby() +{ + return NO_ERROR; +} + +AudioStreamOut* AudioHardwareStub::openOutputStream( + int format, int channelCount, uint32_t sampleRate) +{ + AudioStreamOutStub* out = new AudioStreamOutStub(); + if (out->set(format, channelCount, sampleRate) == NO_ERROR) + return out; + delete out; + return 0; +} + +AudioStreamIn* AudioHardwareStub::openInputStream( + int format, int channelCount, uint32_t sampleRate) +{ + AudioStreamInStub* in = new AudioStreamInStub(); + if (in->set(format, channelCount, sampleRate) == NO_ERROR) + return in; + delete in; + return 0; +} + +status_t AudioHardwareStub::setVoiceVolume(float volume) +{ + return NO_ERROR; +} + +status_t AudioHardwareStub::setMasterVolume(float volume) +{ + return NO_ERROR; +} + +status_t AudioHardwareStub::dumpInternals(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + result.append("AudioHardwareStub::dumpInternals\n"); + snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false"); + result.append(buffer); + ::write(fd, result.string(), result.size()); + return NO_ERROR; +} + +status_t AudioHardwareStub::dump(int fd, const Vector<String16>& args) +{ + dumpInternals(fd, args); + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +status_t AudioStreamOutStub::set(int format, int channels, uint32_t rate) +{ + // fix up defaults + if (format == 0) format = AudioSystem::PCM_16_BIT; + if (channels == 0) channels = channelCount(); + if (rate == 0) rate = sampleRate(); + + if ((format == AudioSystem::PCM_16_BIT) && + (channels == channelCount()) && + (rate == sampleRate())) + return NO_ERROR; + return BAD_VALUE; +} + +ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes) +{ + // fake timing for audio output + usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate()); + return bytes; +} + +status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n"); + snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); + snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); + snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); + snprintf(buffer, SIZE, "\tformat: %d\n", format()); + result.append(buffer); + ::write(fd, result.string(), result.size()); + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +status_t AudioStreamInStub::set(int format, int channels, uint32_t rate) +{ + if ((format == AudioSystem::PCM_16_BIT) && + (channels == channelCount()) && + (rate == sampleRate())) + return NO_ERROR; + return BAD_VALUE; +} + +ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes) +{ + // fake timing for audio input + usleep(bytes * 1000000 / sizeof(int16_t) / channelCount() / sampleRate()); + memset(buffer, 0, bytes); + return bytes; +} + +status_t AudioStreamInStub::dump(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, SIZE, "AudioStreamInStub::dump\n"); + result.append(buffer); + snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate()); + result.append(buffer); + snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize()); + result.append(buffer); + snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount()); + result.append(buffer); + snprintf(buffer, SIZE, "\tformat: %d\n", format()); + result.append(buffer); + ::write(fd, result.string(), result.size()); + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/AudioHardwareStub.h b/AudioHardwareStub.h new file mode 100644 index 0000000..1a61552 --- /dev/null +++ b/AudioHardwareStub.h @@ -0,0 +1,95 @@ +/* //device/servers/AudioFlinger/AudioHardwareStub.h +** +** Copyright 2007, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_AUDIO_HARDWARE_STUB_H +#define ANDROID_AUDIO_HARDWARE_STUB_H + +#include <stdint.h> +#include <sys/types.h> + +#include <hardware/AudioHardwareInterface.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +class AudioStreamOutStub : public AudioStreamOut { +public: + virtual status_t set(int format, int channelCount, uint32_t sampleRate); + virtual uint32_t sampleRate() const { return 44100; } + virtual size_t bufferSize() const { return 4096; } + virtual int channelCount() const { return 2; } + virtual int format() const { return AudioSystem::PCM_16_BIT; } + virtual status_t setVolume(float volume) { return NO_ERROR; } + virtual ssize_t write(const void* buffer, size_t bytes); + virtual status_t dump(int fd, const Vector<String16>& args); +}; + +class AudioStreamInStub : public AudioStreamIn { +public: + virtual status_t set(int format, int channelCount, uint32_t sampleRate); + virtual uint32_t sampleRate() const { return 8000; } + virtual size_t bufferSize() const { return 320; } + virtual int channelCount() const { return 1; } + virtual int format() const { return AudioSystem::PCM_16_BIT; } + virtual status_t setGain(float gain) { return NO_ERROR; } + virtual ssize_t read(void* buffer, ssize_t bytes); + virtual status_t dump(int fd, const Vector<String16>& args); +}; + +class AudioHardwareStub : public AudioHardwareInterface +{ +public: + AudioHardwareStub(); + virtual ~AudioHardwareStub(); + virtual status_t initCheck(); + virtual status_t standby(); + virtual status_t setVoiceVolume(float volume); + virtual status_t setMasterVolume(float volume); + + // mic mute + virtual status_t setMicMute(bool state) { mMicMute = state; return NO_ERROR; } + virtual status_t getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; } + + virtual status_t setParameter(const char* key, const char* value) + { return NO_ERROR; } + + // create I/O streams + virtual AudioStreamOut* openOutputStream( + int format=0, + int channelCount=0, + uint32_t sampleRate=0); + + virtual AudioStreamIn* openInputStream( + int format, + int channelCount, + uint32_t sampleRate); + +protected: + virtual status_t doRouting() { return NO_ERROR; } + virtual status_t dump(int fd, const Vector<String16>& args); + + bool mMicMute; +private: + status_t dumpInternals(int fd, const Vector<String16>& args); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_AUDIO_HARDWARE_STUB_H |