[go: nahoru, domu]

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#ifndef SOUNDPOOL_H_
18#define SOUNDPOOL_H_
19
20#include <utils/threads.h>
21#include <utils/List.h>
22#include <utils/Vector.h>
23#include <utils/KeyedVector.h>
24#include <media/AudioTrack.h>
25#include <binder/MemoryHeapBase.h>
26#include <binder/MemoryBase.h>
27
28namespace android {
29
30static const int IDLE_PRIORITY = -1;
31
32// forward declarations
33class SoundEvent;
34class SoundPoolThread;
35class SoundPool;
36
37// for queued events
38class SoundPoolEvent {
39public:
40    SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
41        mMsg(msg), mArg1(arg1), mArg2(arg2) {}
42    int         mMsg;
43    int         mArg1;
44    int         mArg2;
45    enum MessageType { INVALID, SAMPLE_LOADED };
46};
47
48// callback function prototype
49typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
50
51// tracks samples used by application
52class Sample  : public RefBase {
53public:
54    enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
55    Sample(int sampleID, int fd, int64_t offset, int64_t length);
56    ~Sample();
57    int sampleID() { return mSampleID; }
58    int numChannels() { return mNumChannels; }
59    int sampleRate() { return mSampleRate; }
60    audio_format_t format() { return mFormat; }
61    size_t size() { return mSize; }
62    int state() { return mState; }
63    uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
64    status_t doLoad();
65    void startLoad() { mState = LOADING; }
66    sp<IMemory> getIMemory() { return mData; }
67
68private:
69    void init();
70
71    size_t              mSize;
72    volatile int32_t    mRefCount;
73    uint16_t            mSampleID;
74    uint16_t            mSampleRate;
75    uint8_t             mState;
76    uint8_t             mNumChannels;
77    audio_format_t      mFormat;
78    int                 mFd;
79    int64_t             mOffset;
80    int64_t             mLength;
81    sp<IMemory>         mData;
82    sp<MemoryHeapBase>  mHeap;
83};
84
85// stores pending events for stolen channels
86class SoundEvent
87{
88public:
89    SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
90            mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
91    void set(const sp<Sample>& sample, int channelID, float leftVolume,
92            float rightVolume, int priority, int loop, float rate);
93    sp<Sample>      sample() { return mSample; }
94    int             channelID() { return mChannelID; }
95    float           leftVolume() { return mLeftVolume; }
96    float           rightVolume() { return mRightVolume; }
97    int             priority() { return mPriority; }
98    int             loop() { return mLoop; }
99    float           rate() { return mRate; }
100    void            clear() { mChannelID = 0; mSample.clear(); }
101
102protected:
103    sp<Sample>      mSample;
104    int             mChannelID;
105    float           mLeftVolume;
106    float           mRightVolume;
107    int             mPriority;
108    int             mLoop;
109    float           mRate;
110};
111
112// for channels aka AudioTracks
113class SoundChannel : public SoundEvent {
114public:
115    enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
116    SoundChannel() : mState(IDLE), mNumChannels(1),
117            mPos(0), mToggle(0), mAutoPaused(false) {}
118    ~SoundChannel();
119    void init(SoundPool* soundPool);
120    void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
121            int priority, int loop, float rate);
122    void setVolume_l(float leftVolume, float rightVolume);
123    void setVolume(float leftVolume, float rightVolume);
124    void stop_l();
125    void stop();
126    void pause();
127    void autoPause();
128    void resume();
129    void autoResume();
130    void setRate(float rate);
131    int state() { return mState; }
132    void setPriority(int priority) { mPriority = priority; }
133    void setLoop(int loop);
134    int numChannels() { return mNumChannels; }
135    void clearNextEvent() { mNextEvent.clear(); }
136    void nextEvent();
137    int nextChannelID() { return mNextEvent.channelID(); }
138    void dump();
139    int getPrevSampleID(void) { return mPrevSampleID; }
140
141private:
142    static void callback(int event, void* user, void *info);
143    void process(int event, void *info, unsigned long toggle);
144    bool doStop_l();
145
146    SoundPool*          mSoundPool;
147    sp<AudioTrack>      mAudioTrack;
148    SoundEvent          mNextEvent;
149    Mutex               mLock;
150    int                 mState;
151    int                 mNumChannels;
152    int                 mPos;
153    int                 mAudioBufferSize;
154    unsigned long       mToggle;
155    bool                mAutoPaused;
156    int                 mPrevSampleID;
157};
158
159// application object for managing a pool of sounds
160class SoundPool {
161    friend class SoundPoolThread;
162    friend class SoundChannel;
163public:
164    SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
165    ~SoundPool();
166    int load(int fd, int64_t offset, int64_t length, int priority);
167    bool unload(int sampleID);
168    int play(int sampleID, float leftVolume, float rightVolume, int priority,
169            int loop, float rate);
170    void pause(int channelID);
171    void autoPause();
172    void resume(int channelID);
173    void autoResume();
174    void stop(int channelID);
175    void setVolume(int channelID, float leftVolume, float rightVolume);
176    void setPriority(int channelID, int priority);
177    void setLoop(int channelID, int loop);
178    void setRate(int channelID, float rate);
179    const audio_attributes_t* attributes() { return &mAttributes; }
180
181    // called from SoundPoolThread
182    void sampleLoaded(int sampleID);
183    sp<Sample> findSample(int sampleID);
184
185    // called from AudioTrack thread
186    void done_l(SoundChannel* channel);
187
188    // callback function
189    void setCallback(SoundPoolCallback* callback, void* user);
190    void* getUserData() { return mUserData; }
191
192private:
193    SoundPool() {} // no default constructor
194    bool startThreads();
195    sp<Sample> findSample_l(int sampleID);
196    SoundChannel* findChannel (int channelID);
197    SoundChannel* findNextChannel (int channelID);
198    SoundChannel* allocateChannel_l(int priority, int sampleID);
199    void moveToFront_l(SoundChannel* channel);
200    void notify(SoundPoolEvent event);
201    void dump();
202
203    // restart thread
204    void addToRestartList(SoundChannel* channel);
205    void addToStopList(SoundChannel* channel);
206    static int beginThread(void* arg);
207    int run();
208    void quit();
209
210    Mutex                   mLock;
211    Mutex                   mRestartLock;
212    Condition               mCondition;
213    SoundPoolThread*        mDecodeThread;
214    SoundChannel*           mChannelPool;
215    List<SoundChannel*>     mChannels;
216    List<SoundChannel*>     mRestart;
217    List<SoundChannel*>     mStop;
218    DefaultKeyedVector< int, sp<Sample> >   mSamples;
219    int                     mMaxChannels;
220    audio_attributes_t      mAttributes;
221    int                     mAllocated;
222    int                     mNextSampleID;
223    int                     mNextChannelID;
224    bool                    mQuit;
225
226    // callback
227    Mutex                   mCallbackLock;
228    SoundPoolCallback*      mCallback;
229    void*                   mUserData;
230};
231
232} // end namespace android
233
234#endif /*SOUNDPOOL_H_*/
235