diff options
Diffstat (limited to 'cmds/bootanimation/AudioPlayer.cpp')
-rw-r--r-- | cmds/bootanimation/AudioPlayer.cpp | 317 |
1 files changed, 0 insertions, 317 deletions
diff --git a/cmds/bootanimation/AudioPlayer.cpp b/cmds/bootanimation/AudioPlayer.cpp deleted file mode 100644 index f5acac485c81..000000000000 --- a/cmds/bootanimation/AudioPlayer.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2014 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. - */ - -#define LOG_NDEBUG 0 -#define LOG_TAG "BootAnim_AudioPlayer" - -#include "AudioPlayer.h" - -#include <androidfw/ZipFileRO.h> -#include <tinyalsa/asoundlib.h> -#include <utils/Log.h> -#include <utils/String8.h> -#include <media/AudioSystem.h> - -#define ID_RIFF 0x46464952 -#define ID_WAVE 0x45564157 -#define ID_FMT 0x20746d66 -#define ID_DATA 0x61746164 - -// Maximum line length for audio_conf.txt -// We only accept lines less than this length to avoid overflows using sscanf() -#define MAX_LINE_LENGTH 1024 - -struct riff_wave_header { - uint32_t riff_id; - uint32_t riff_sz; - uint32_t wave_id; -}; - -struct chunk_header { - uint32_t id; - uint32_t sz; -}; - -struct chunk_fmt { - uint16_t audio_format; - uint16_t num_channels; - uint32_t sample_rate; - uint32_t byte_rate; - uint16_t block_align; - uint16_t bits_per_sample; -}; - - -namespace android { - -AudioPlayer::AudioPlayer() - : mCard(-1), - mDevice(-1), - mPeriodSize(0), - mPeriodCount(0), - mCurrentFile(NULL) -{ -} - -AudioPlayer::~AudioPlayer() { -} - -static bool setMixerValue(struct mixer* mixer, const char* name, const char* values) -{ - if (!mixer) { - ALOGE("no mixer in setMixerValue"); - return false; - } - struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, name); - if (!ctl) { - ALOGE("mixer_get_ctl_by_name failed for %s", name); - return false; - } - - enum mixer_ctl_type type = mixer_ctl_get_type(ctl); - int numValues = mixer_ctl_get_num_values(ctl); - int intValue; - char stringValue[MAX_LINE_LENGTH]; - - for (int i = 0; i < numValues && values; i++) { - // strip leading space - while (*values == ' ') values++; - if (*values == 0) break; - - switch (type) { - case MIXER_CTL_TYPE_BOOL: - case MIXER_CTL_TYPE_INT: - if (sscanf(values, "%d", &intValue) == 1) { - if (mixer_ctl_set_value(ctl, i, intValue) != 0) { - ALOGE("mixer_ctl_set_value failed for %s %d", name, intValue); - } - } else { - ALOGE("Could not parse %s as int for %s", values, name); - } - break; - case MIXER_CTL_TYPE_ENUM: - if (sscanf(values, "%s", stringValue) == 1) { - if (mixer_ctl_set_enum_by_string(ctl, stringValue) != 0) { - ALOGE("mixer_ctl_set_enum_by_string failed for %s %s", name, stringValue); - } - } else { - ALOGE("Could not parse %s as enum for %s", values, name); - } - break; - default: - ALOGE("unsupported mixer type %d for %s", type, name); - break; - } - - values = strchr(values, ' '); - } - - return true; -} - - -/* - * Parse the audio configuration file. - * The file is named audio_conf.txt and must begin with the following header: - * - * card=<ALSA card number> - * device=<ALSA device number> - * period_size=<period size> - * period_count=<period count> - * - * This header is followed by zero or more mixer settings, each with the format: - * mixer "<name>" = <value list> - * Since mixer names can contain spaces, the name must be enclosed in double quotes. - * The values in the value list can be integers, booleans (represented by 0 or 1) - * or strings for enum values. - */ -bool AudioPlayer::init(const char* config) -{ - int tempInt; - struct mixer* mixer = NULL; - char name[MAX_LINE_LENGTH]; - - // Fake call to wait for audio HAL initialization completion - AudioSystem::getParameters(String8("")); - - for (;;) { - const char* endl = strstr(config, "\n"); - if (!endl) break; - String8 line(config, endl - config); - if (line.length() >= MAX_LINE_LENGTH) { - ALOGE("Line too long in audio_conf.txt"); - return false; - } - const char* l = line.string(); - - if (sscanf(l, "card=%d", &tempInt) == 1) { - ALOGD("card=%d", tempInt); - mCard = tempInt; - - mixer = mixer_open(mCard); - if (!mixer) { - ALOGE("could not open mixer for card %d", mCard); - return false; - } - } else if (sscanf(l, "device=%d", &tempInt) == 1) { - ALOGD("device=%d", tempInt); - mDevice = tempInt; - } else if (sscanf(l, "period_size=%d", &tempInt) == 1) { - ALOGD("period_size=%d", tempInt); - mPeriodSize = tempInt; - } else if (sscanf(l, "period_count=%d", &tempInt) == 1) { - ALOGD("period_count=%d", tempInt); - mPeriodCount = tempInt; - } else if (sscanf(l, "mixer \"%[0-9a-zA-Z _]s\"", name) == 1) { - const char* values = strchr(l, '='); - if (values) { - values++; // skip '=' - ALOGD("name: \"%s\" = %s", name, values); - setMixerValue(mixer, name, values); - } else { - ALOGE("values missing for name: \"%s\"", name); - } - } - config = ++endl; - } - - mixer_close(mixer); - - if (mCard >= 0 && mDevice >= 0) { - return true; - } - - return false; -} - -void AudioPlayer::playFile(FileMap* fileMap) { - // stop any currently playing sound - requestExitAndWait(); - - mCurrentFile = fileMap; - run("bootanim audio", PRIORITY_URGENT_AUDIO); -} - -bool AudioPlayer::threadLoop() -{ - struct pcm_config config; - struct pcm *pcm = NULL; - bool moreChunks = true; - const struct chunk_fmt* chunkFmt = NULL; - int bufferSize; - const uint8_t* wavData; - size_t wavLength; - const struct riff_wave_header* wavHeader; - - if (mCurrentFile == NULL) { - ALOGE("mCurrentFile is NULL"); - return false; - } - - wavData = (const uint8_t *)mCurrentFile->getDataPtr(); - if (!wavData) { - ALOGE("Could not access WAV file data"); - goto exit; - } - wavLength = mCurrentFile->getDataLength(); - - wavHeader = (const struct riff_wave_header *)wavData; - if (wavLength < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || - (wavHeader->wave_id != ID_WAVE)) { - ALOGE("Error: audio file is not a riff/wave file\n"); - goto exit; - } - wavData += sizeof(*wavHeader); - wavLength -= sizeof(*wavHeader); - - do { - const struct chunk_header* chunkHeader = (const struct chunk_header*)wavData; - if (wavLength < sizeof(*chunkHeader)) { - ALOGE("EOF reading chunk headers"); - goto exit; - } - - wavData += sizeof(*chunkHeader); - wavLength -= sizeof(*chunkHeader); - - switch (chunkHeader->id) { - case ID_FMT: - chunkFmt = (const struct chunk_fmt *)wavData; - wavData += chunkHeader->sz; - wavLength -= chunkHeader->sz; - break; - case ID_DATA: - /* Stop looking for chunks */ - moreChunks = 0; - break; - default: - /* Unknown chunk, skip bytes */ - wavData += chunkHeader->sz; - wavLength -= chunkHeader->sz; - } - } while (moreChunks); - - if (!chunkFmt) { - ALOGE("format not found in WAV file"); - goto exit; - } - - - memset(&config, 0, sizeof(config)); - config.channels = chunkFmt->num_channels; - config.rate = chunkFmt->sample_rate; - config.period_size = mPeriodSize; - config.period_count = mPeriodCount; - config.start_threshold = mPeriodSize / 4; - config.stop_threshold = INT_MAX; - config.avail_min = config.start_threshold; - if (chunkFmt->bits_per_sample != 16) { - ALOGE("only 16 bit WAV files are supported"); - goto exit; - } - config.format = PCM_FORMAT_S16_LE; - - pcm = pcm_open(mCard, mDevice, PCM_OUT, &config); - if (!pcm || !pcm_is_ready(pcm)) { - ALOGE("Unable to open PCM device (%s)\n", pcm_get_error(pcm)); - goto exit; - } - - bufferSize = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); - - while (wavLength > 0) { - if (exitPending()) goto exit; - size_t count = bufferSize; - if (count > wavLength) - count = wavLength; - - if (pcm_write(pcm, wavData, count)) { - ALOGE("pcm_write failed (%s)", pcm_get_error(pcm)); - goto exit; - } - wavData += count; - wavLength -= count; - } - -exit: - if (pcm) - pcm_close(pcm); - delete mCurrentFile; - mCurrentFile = NULL; - return false; -} - -} // namespace android |