IAndroidBufferQueue.c revision d158d31a6bbb06426b71c3d097b7768bc3fb79a3
1/*
2 * Copyright (C) 2010 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/* AndroidBufferQueue implementation */
18
19#include "sles_allinclusive.h"
20
21
22/** Determine the state of the audio player or audio recorder associated with a buffer queue.
23 *  Note that PLAYSTATE and RECORDSTATE values are equivalent (where PLAYING == RECORDING).
24 */
25
26static SLuint32 getAssociatedState(IAndroidBufferQueue *thiz)
27{
28    SLuint32 state;
29    switch (InterfaceToObjectID(thiz)) {
30    case XA_OBJECTID_MEDIAPLAYER:
31        state = ((CMediaPlayer *) thiz->mThis)->mPlay.mState;
32        break;
33    case SL_OBJECTID_AUDIOPLAYER:
34        state = ((CAudioPlayer *) thiz->mThis)->mPlay.mState;
35        break;
36    case SL_OBJECTID_AUDIORECORDER:
37        state = ((CAudioRecorder *) thiz->mThis)->mRecord.mState;
38        break;
39    default:
40        // unreachable, but just in case we will assume it is stopped
41        assert(SL_BOOLEAN_FALSE);
42        state = SL_PLAYSTATE_STOPPED;
43        break;
44    }
45    return state;
46}
47
48
49SLresult IAndroidBufferQueue_RegisterCallback(SLAndroidBufferQueueItf self,
50        slAndroidBufferQueueCallback callback, void *pContext)
51{
52    SL_ENTER_INTERFACE
53
54    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
55
56    interface_lock_exclusive(thiz);
57
58    // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state
59    // FIXME PRIORITY 1 check play state
60    //if (SL_PLAYSTATE_STOPPED == ((CAudioPlayer*) thiz->mThis)->mPlay.mState) {
61        thiz->mCallback = callback;
62        thiz->mContext = pContext;
63
64        switch (InterfaceToObjectID(thiz)) {
65        case SL_OBJECTID_AUDIOPLAYER:
66            result = SL_RESULT_SUCCESS;
67            android_audioPlayer_androidBufferQueue_registerCallback_l((CAudioPlayer*) thiz->mThis);
68            break;
69        case XA_OBJECTID_MEDIAPLAYER:
70            SL_LOGI("IAndroidBufferQueue_RegisterCallback()");
71            result = SL_RESULT_SUCCESS;
72            android_Player_androidBufferQueue_registerCallback_l((CMediaPlayer*) thiz->mThis);
73            break;
74        default:
75            result = SL_RESULT_PARAMETER_INVALID;
76            break;
77        }
78
79    //} else {
80    //    result = SL_RESULT_PRECONDITIONS_VIOLATED;
81    //}
82
83    interface_unlock_exclusive(thiz);
84
85    SL_LEAVE_INTERFACE
86}
87
88
89SLresult IAndroidBufferQueue_Clear(SLAndroidBufferQueueItf self)
90{
91    SL_ENTER_INTERFACE
92
93    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
94
95    interface_lock_exclusive(thiz);
96
97    // FIXME return value?
98    result = SL_RESULT_SUCCESS;
99    android_audioPlayer_androidBufferQueue_clear_l((CAudioPlayer*) thiz->mThis);
100
101    interface_unlock_exclusive(thiz);
102
103    SL_LEAVE_INTERFACE
104}
105
106
107SLresult IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self,
108        const void *pData,
109        SLuint32 dataLength,
110        const SLAndroidBufferItem *pItems,
111        SLuint32 itemsLength)
112{
113    SL_ENTER_INTERFACE
114
115    if ( ((NULL == pData) || (0 == dataLength))
116            && ((NULL == pItems) || (0 == itemsLength))) {
117        // no data and no msg
118        SL_LOGE("Enqueue failure: trying to enqueue buffer with no data and no items.");
119        result = SL_RESULT_PARAMETER_INVALID;
120    } else {
121        IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
122
123        interface_lock_exclusive(thiz);
124
125        AdvancedBufferHeader *oldRear = thiz->mRear, *newRear;
126        if ((newRear = oldRear + 1) == &thiz->mBufferArray[thiz->mNumBuffers + 1]) {
127            newRear = thiz->mBufferArray;
128        }
129        if (newRear == thiz->mFront) {
130            result = SL_RESULT_BUFFER_INSUFFICIENT;
131        } else {
132            oldRear->mDataBuffer = pData;
133            oldRear->mDataSize = dataLength;
134            oldRear->mDataSizeConsumed = 0;
135            thiz->mRear = newRear;
136            ++thiz->mState.count;
137            result = SL_RESULT_SUCCESS;
138        }
139        // set enqueue attribute if state is PLAYING and the first buffer is enqueued
140        interface_unlock_exclusive_attributes(thiz, ((SL_RESULT_SUCCESS == result) &&
141                (1 == thiz->mState.count) && (SL_PLAYSTATE_PLAYING == getAssociatedState(thiz))) ?
142                        ATTR_BQ_ENQUEUE : ATTR_NONE);
143    }
144
145    SL_LEAVE_INTERFACE
146}
147
148
149static const struct SLAndroidBufferQueueItf_ IAndroidBufferQueue_Itf = {
150    IAndroidBufferQueue_RegisterCallback,
151    IAndroidBufferQueue_Clear,
152    IAndroidBufferQueue_Enqueue
153};
154
155
156void IAndroidBufferQueue_init(void *self)
157{
158    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
159    thiz->mItf = &IAndroidBufferQueue_Itf;
160
161    thiz->mState.count = 0;
162    thiz->mState.index = 0;
163
164    thiz->mCallback = NULL;
165    thiz->mContext = NULL;
166
167    thiz->mBufferArray = NULL;
168    thiz->mFront = NULL;
169    thiz->mRear = NULL;
170}
171
172
173void IAndroidBufferQueue_deinit(void *self)
174{
175    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
176    if (NULL != thiz->mBufferArray) {
177        free(thiz->mBufferArray);
178        thiz->mBufferArray = NULL;
179    }
180}
181