1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "SoundPoolThread"
19#include "utils/Log.h"
20
21#include "SoundPoolThread.h"
22
23namespace android {
24
25void SoundPoolThread::write(SoundPoolMsg msg) {
26    Mutex::Autolock lock(&mLock);
27    while (mMsgQueue.size() >= maxMessages) {
28        mCondition.wait(mLock);
29    }
30
31    // if thread is quitting, don't add to queue
32    if (mRunning) {
33        mMsgQueue.push(msg);
34        mCondition.signal();
35    }
36}
37
38const SoundPoolMsg SoundPoolThread::read() {
39    Mutex::Autolock lock(&mLock);
40    while (mMsgQueue.size() == 0) {
41        mCondition.wait(mLock);
42    }
43    SoundPoolMsg msg = mMsgQueue[0];
44    mMsgQueue.removeAt(0);
45    mCondition.signal();
46    return msg;
47}
48
49void SoundPoolThread::quit() {
50    Mutex::Autolock lock(&mLock);
51    if (mRunning) {
52        mRunning = false;
53        mMsgQueue.clear();
54        mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
55        mCondition.signal();
56        mCondition.wait(mLock);
57    }
58    ALOGV("return from quit");
59}
60
61SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
62    mSoundPool(soundPool)
63{
64    mMsgQueue.setCapacity(maxMessages);
65    if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
66        mRunning = true;
67    }
68}
69
70SoundPoolThread::~SoundPoolThread()
71{
72    quit();
73}
74
75int SoundPoolThread::beginThread(void* arg) {
76    ALOGV("beginThread");
77    SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
78    return soundPoolThread->run();
79}
80
81int SoundPoolThread::run() {
82    ALOGV("run");
83    for (;;) {
84        SoundPoolMsg msg = read();
85        ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
86        switch (msg.mMessageType) {
87        case SoundPoolMsg::KILL:
88            ALOGV("goodbye");
89            return NO_ERROR;
90        case SoundPoolMsg::LOAD_SAMPLE:
91            doLoadSample(msg.mData);
92            break;
93        default:
94            ALOGW("run: Unrecognized message %d\n",
95                    msg.mMessageType);
96            break;
97        }
98    }
99}
100
101void SoundPoolThread::loadSample(int sampleID) {
102    write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
103}
104
105void SoundPoolThread::doLoadSample(int sampleID) {
106    sp <Sample> sample = mSoundPool->findSample(sampleID);
107    status_t status = -1;
108    if (sample != 0) {
109        status = sample->doLoad();
110    }
111    mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
112}
113
114} // end namespace android
115