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/* Record implementation */
18
19#include "sles_allinclusive.h"
20
21
22static SLresult IRecord_SetRecordState(SLRecordItf self, SLuint32 state)
23{
24    SL_ENTER_INTERFACE
25
26    switch (state) {
27    case SL_RECORDSTATE_STOPPED:
28    case SL_RECORDSTATE_PAUSED:
29    case SL_RECORDSTATE_RECORDING:
30        {
31        IRecord *this = (IRecord *) self;
32        interface_lock_poke(this);
33        this->mState = state;
34#ifdef ANDROID
35        android_audioRecorder_setRecordState(InterfaceToCAudioRecorder(this), state);
36#endif
37        interface_unlock_poke(this);
38        result = SL_RESULT_SUCCESS;
39        }
40        break;
41    default:
42        result = SL_RESULT_PARAMETER_INVALID;
43        break;
44    }
45
46    SL_LEAVE_INTERFACE
47}
48
49
50static SLresult IRecord_GetRecordState(SLRecordItf self, SLuint32 *pState)
51{
52    SL_ENTER_INTERFACE
53
54    IRecord *this = (IRecord *) self;
55    if (NULL == pState) {
56        result = SL_RESULT_PARAMETER_INVALID;
57    } else {
58        interface_lock_peek(this);
59        SLuint32 state = this->mState;
60        interface_unlock_peek(this);
61        *pState = state;
62        result = SL_RESULT_SUCCESS;
63    }
64
65    SL_LEAVE_INTERFACE
66}
67
68
69static SLresult IRecord_SetDurationLimit(SLRecordItf self, SLmillisecond msec)
70{
71    SL_ENTER_INTERFACE
72
73    IRecord *this = (IRecord *) self;
74    interface_lock_exclusive(this);
75    if (this->mDurationLimit != msec) {
76        this->mDurationLimit = msec;
77        interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT);
78    } else {
79        interface_unlock_exclusive(this);
80    }
81    result = SL_RESULT_SUCCESS;
82
83    SL_LEAVE_INTERFACE
84}
85
86
87static SLresult IRecord_GetPosition(SLRecordItf self, SLmillisecond *pMsec)
88{
89    SL_ENTER_INTERFACE
90
91    if (NULL == pMsec) {
92        result = SL_RESULT_PARAMETER_INVALID;
93    } else {
94        IRecord *this = (IRecord *) self;
95        SLmillisecond position;
96        interface_lock_shared(this);
97#ifdef ANDROID
98        // Android does not use the mPosition field for audio recorders
99        if (SL_OBJECTID_AUDIORECORDER == InterfaceToObjectID(this)) {
100            android_audioRecorder_getPosition(InterfaceToCAudioRecorder(this), &position);
101        } else {
102            position = this->mPosition;
103        }
104#else
105        position = this->mPosition;
106#endif
107        interface_unlock_shared(this);
108        *pMsec = position;
109        result = SL_RESULT_SUCCESS;
110    }
111
112    SL_LEAVE_INTERFACE
113}
114
115
116static SLresult IRecord_RegisterCallback(SLRecordItf self, slRecordCallback callback,
117    void *pContext)
118{
119    SL_ENTER_INTERFACE
120
121    IRecord *this = (IRecord *) self;
122    interface_lock_exclusive(this);
123    this->mCallback = callback;
124    this->mContext = pContext;
125    interface_unlock_exclusive(this);
126    result = SL_RESULT_SUCCESS;
127
128    SL_LEAVE_INTERFACE
129}
130
131
132static SLresult IRecord_SetCallbackEventsMask(SLRecordItf self, SLuint32 eventFlags)
133{
134    SL_ENTER_INTERFACE
135
136    if (eventFlags & ~(
137        SL_RECORDEVENT_HEADATLIMIT  |
138        SL_RECORDEVENT_HEADATMARKER |
139        SL_RECORDEVENT_HEADATNEWPOS |
140        SL_RECORDEVENT_HEADMOVING   |
141        SL_RECORDEVENT_HEADSTALLED  |
142        SL_RECORDEVENT_BUFFER_FULL)) {
143        result = SL_RESULT_PARAMETER_INVALID;
144    } else {
145        IRecord *this = (IRecord *) self;
146        interface_lock_exclusive(this);
147        if (this->mCallbackEventsMask != eventFlags) {
148            this->mCallbackEventsMask = eventFlags;
149            interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT);
150        } else {
151            interface_unlock_exclusive(this);
152        }
153        result = SL_RESULT_SUCCESS;
154    }
155
156    SL_LEAVE_INTERFACE
157}
158
159
160static SLresult IRecord_GetCallbackEventsMask(SLRecordItf self, SLuint32 *pEventFlags)
161{
162    SL_ENTER_INTERFACE
163
164    if (NULL == pEventFlags) {
165        result = SL_RESULT_PARAMETER_INVALID;
166    } else {
167        IRecord *this = (IRecord *) self;
168        interface_lock_peek(this);
169        SLuint32 callbackEventsMask = this->mCallbackEventsMask;
170        interface_unlock_peek(this);
171        *pEventFlags = callbackEventsMask;
172        result = SL_RESULT_SUCCESS;
173    }
174
175    SL_LEAVE_INTERFACE
176}
177
178
179static SLresult IRecord_SetMarkerPosition(SLRecordItf self, SLmillisecond mSec)
180{
181    SL_ENTER_INTERFACE
182
183    IRecord *this = (IRecord *) self;
184    interface_lock_exclusive(this);
185    if (this->mMarkerPosition != mSec) {
186        this->mMarkerPosition = mSec;
187        interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT);
188    } else {
189        interface_unlock_exclusive(this);
190    }
191    result = SL_RESULT_SUCCESS;
192
193    SL_LEAVE_INTERFACE
194}
195
196
197static SLresult IRecord_ClearMarkerPosition(SLRecordItf self)
198{
199    SL_ENTER_INTERFACE
200
201    IRecord *this = (IRecord *) self;
202    interface_lock_exclusive(this);
203    if (this->mMarkerPosition != 0) {
204        this->mMarkerPosition = 0;
205        interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT);
206    } else {
207        interface_unlock_exclusive(this);
208    }
209    result = SL_RESULT_SUCCESS;
210
211    SL_LEAVE_INTERFACE
212}
213
214
215static SLresult IRecord_GetMarkerPosition(SLRecordItf self, SLmillisecond *pMsec)
216{
217    SL_ENTER_INTERFACE
218
219    if (NULL == pMsec) {
220        result = SL_RESULT_PARAMETER_INVALID;
221    } else {
222        IRecord *this = (IRecord *) self;
223        interface_lock_peek(this);
224        SLmillisecond markerPosition = this->mMarkerPosition;
225        interface_unlock_peek(this);
226        *pMsec = markerPosition;
227        result = SL_RESULT_SUCCESS;
228    }
229
230    SL_LEAVE_INTERFACE
231}
232
233
234static SLresult IRecord_SetPositionUpdatePeriod(SLRecordItf self, SLmillisecond mSec)
235{
236    SL_ENTER_INTERFACE
237
238    if (0 == mSec) {
239        result = SL_RESULT_PARAMETER_INVALID;
240    } else {
241        IRecord *this = (IRecord *) self;
242        interface_lock_exclusive(this);
243        if (this->mPositionUpdatePeriod != mSec) {
244            this->mPositionUpdatePeriod = mSec;
245            interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT);
246        } else {
247            interface_unlock_exclusive(this);
248        }
249        result = SL_RESULT_SUCCESS;
250    }
251
252    SL_LEAVE_INTERFACE
253}
254
255
256static SLresult IRecord_GetPositionUpdatePeriod(SLRecordItf self, SLmillisecond *pMsec)
257{
258    SL_ENTER_INTERFACE
259
260    if (NULL == pMsec) {
261        result = SL_RESULT_PARAMETER_INVALID;
262    } else {
263        IRecord *this = (IRecord *) self;
264        interface_lock_peek(this);
265        SLmillisecond positionUpdatePeriod = this->mPositionUpdatePeriod;
266        interface_unlock_peek(this);
267        *pMsec = positionUpdatePeriod;
268        result = SL_RESULT_SUCCESS;
269    }
270
271    SL_LEAVE_INTERFACE
272}
273
274
275static const struct SLRecordItf_ IRecord_Itf = {
276    IRecord_SetRecordState,
277    IRecord_GetRecordState,
278    IRecord_SetDurationLimit,
279    IRecord_GetPosition,
280    IRecord_RegisterCallback,
281    IRecord_SetCallbackEventsMask,
282    IRecord_GetCallbackEventsMask,
283    IRecord_SetMarkerPosition,
284    IRecord_ClearMarkerPosition,
285    IRecord_GetMarkerPosition,
286    IRecord_SetPositionUpdatePeriod,
287    IRecord_GetPositionUpdatePeriod
288};
289
290void IRecord_init(void *self)
291{
292    IRecord *this = (IRecord *) self;
293    this->mItf = &IRecord_Itf;
294    this->mState = SL_RECORDSTATE_STOPPED;
295    this->mDurationLimit = 0;
296    this->mPosition = 0;
297    this->mCallback = NULL;
298    this->mContext = NULL;
299    this->mCallbackEventsMask = 0;
300    this->mMarkerPosition = 0;
301    this->mPositionUpdatePeriod = 1000;
302}
303