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
IRecord_SetRecordState(SLRecordItf self,SLuint32 state)22 static 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 *thiz = (IRecord *) self;
32 interface_lock_exclusive(thiz);
33 thiz->mState = state;
34 #ifdef ANDROID
35 android_audioRecorder_setRecordState(InterfaceToCAudioRecorder(thiz), state);
36 #endif
37 interface_unlock_exclusive(thiz);
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
IRecord_GetRecordState(SLRecordItf self,SLuint32 * pState)50 static SLresult IRecord_GetRecordState(SLRecordItf self, SLuint32 *pState)
51 {
52 SL_ENTER_INTERFACE
53
54 IRecord *thiz = (IRecord *) self;
55 if (NULL == pState) {
56 result = SL_RESULT_PARAMETER_INVALID;
57 } else {
58 interface_lock_shared(thiz);
59 SLuint32 state = thiz->mState;
60 interface_unlock_shared(thiz);
61 *pState = state;
62 result = SL_RESULT_SUCCESS;
63 }
64
65 SL_LEAVE_INTERFACE
66 }
67
68
IRecord_SetDurationLimit(SLRecordItf self,SLmillisecond msec)69 static SLresult IRecord_SetDurationLimit(SLRecordItf self, SLmillisecond msec)
70 {
71 SL_ENTER_INTERFACE
72
73 IRecord *thiz = (IRecord *) self;
74 interface_lock_exclusive(thiz);
75 if (thiz->mDurationLimit != msec) {
76 thiz->mDurationLimit = msec;
77 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT);
78 } else {
79 interface_unlock_exclusive(thiz);
80 }
81 result = SL_RESULT_SUCCESS;
82
83 SL_LEAVE_INTERFACE
84 }
85
86
IRecord_GetPosition(SLRecordItf self,SLmillisecond * pMsec)87 static 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 *thiz = (IRecord *) self;
95 SLmillisecond position;
96 interface_lock_shared(thiz);
97 #ifdef ANDROID
98 // Android does not use the mPosition field for audio recorders
99 if (SL_OBJECTID_AUDIORECORDER == InterfaceToObjectID(thiz)) {
100 android_audioRecorder_getPosition(InterfaceToCAudioRecorder(thiz), &position);
101 } else {
102 position = thiz->mPosition;
103 }
104 #else
105 position = thiz->mPosition;
106 #endif
107 interface_unlock_shared(thiz);
108 *pMsec = position;
109 result = SL_RESULT_SUCCESS;
110 }
111
112 SL_LEAVE_INTERFACE
113 }
114
115
IRecord_RegisterCallback(SLRecordItf self,slRecordCallback callback,void * pContext)116 static SLresult IRecord_RegisterCallback(SLRecordItf self, slRecordCallback callback,
117 void *pContext)
118 {
119 SL_ENTER_INTERFACE
120
121 IRecord *thiz = (IRecord *) self;
122 interface_lock_exclusive(thiz);
123 thiz->mCallback = callback;
124 thiz->mContext = pContext;
125 interface_unlock_exclusive(thiz);
126 result = SL_RESULT_SUCCESS;
127
128 SL_LEAVE_INTERFACE
129 }
130
131
IRecord_SetCallbackEventsMask(SLRecordItf self,SLuint32 eventFlags)132 static 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 *thiz = (IRecord *) self;
146 interface_lock_exclusive(thiz);
147 if (thiz->mCallbackEventsMask != eventFlags) {
148 thiz->mCallbackEventsMask = eventFlags;
149 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT);
150 } else {
151 interface_unlock_exclusive(thiz);
152 }
153 result = SL_RESULT_SUCCESS;
154 }
155
156 SL_LEAVE_INTERFACE
157 }
158
159
IRecord_GetCallbackEventsMask(SLRecordItf self,SLuint32 * pEventFlags)160 static 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 *thiz = (IRecord *) self;
168 interface_lock_shared(thiz);
169 SLuint32 callbackEventsMask = thiz->mCallbackEventsMask;
170 interface_unlock_shared(thiz);
171 *pEventFlags = callbackEventsMask;
172 result = SL_RESULT_SUCCESS;
173 }
174
175 SL_LEAVE_INTERFACE
176 }
177
178
IRecord_SetMarkerPosition(SLRecordItf self,SLmillisecond mSec)179 static SLresult IRecord_SetMarkerPosition(SLRecordItf self, SLmillisecond mSec)
180 {
181 SL_ENTER_INTERFACE
182
183 if (SL_TIME_UNKNOWN == mSec) {
184 result = SL_RESULT_PARAMETER_INVALID;
185 } else {
186 IRecord *thiz = (IRecord *) self;
187 bool significant = false;
188 interface_lock_exclusive(thiz);
189 if (thiz->mMarkerPosition != mSec) {
190 thiz->mMarkerPosition = mSec;
191 if (thiz->mCallbackEventsMask & SL_PLAYEVENT_HEADATMARKER) {
192 significant = true;
193 }
194 }
195 if (significant) {
196 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT);
197 } else {
198 interface_unlock_exclusive(thiz);
199 }
200 result = SL_RESULT_SUCCESS;
201 }
202
203 SL_LEAVE_INTERFACE
204 }
205
206
IRecord_ClearMarkerPosition(SLRecordItf self)207 static SLresult IRecord_ClearMarkerPosition(SLRecordItf self)
208 {
209 SL_ENTER_INTERFACE
210
211 IRecord *thiz = (IRecord *) self;
212 bool significant = false;
213 interface_lock_exclusive(thiz);
214 // clearing the marker position is equivalent to setting the marker to SL_TIME_UNKNOWN
215 if (thiz->mMarkerPosition != SL_TIME_UNKNOWN) {
216 thiz->mMarkerPosition = SL_TIME_UNKNOWN;
217 if (thiz->mCallbackEventsMask & SL_PLAYEVENT_HEADATMARKER) {
218 significant = true;
219 }
220 }
221 if (significant) {
222 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT);
223 } else {
224 interface_unlock_exclusive(thiz);
225 }
226 result = SL_RESULT_SUCCESS;
227
228 SL_LEAVE_INTERFACE
229 }
230
231
IRecord_GetMarkerPosition(SLRecordItf self,SLmillisecond * pMsec)232 static SLresult IRecord_GetMarkerPosition(SLRecordItf self, SLmillisecond *pMsec)
233 {
234 SL_ENTER_INTERFACE
235
236 if (NULL == pMsec) {
237 result = SL_RESULT_PARAMETER_INVALID;
238 } else {
239 IRecord *thiz = (IRecord *) self;
240 interface_lock_shared(thiz);
241 SLmillisecond markerPosition = thiz->mMarkerPosition;
242 interface_unlock_shared(thiz);
243 *pMsec = markerPosition;
244 if (SL_TIME_UNKNOWN == markerPosition) {
245 result = SL_RESULT_PRECONDITIONS_VIOLATED;
246 } else {
247 result = SL_RESULT_SUCCESS;
248 }
249 }
250
251 SL_LEAVE_INTERFACE
252 }
253
254
IRecord_SetPositionUpdatePeriod(SLRecordItf self,SLmillisecond mSec)255 static SLresult IRecord_SetPositionUpdatePeriod(SLRecordItf self, SLmillisecond mSec)
256 {
257 SL_ENTER_INTERFACE
258
259 if (0 == mSec) {
260 result = SL_RESULT_PARAMETER_INVALID;
261 } else {
262 IRecord *thiz = (IRecord *) self;
263 interface_lock_exclusive(thiz);
264 if (thiz->mPositionUpdatePeriod != mSec) {
265 thiz->mPositionUpdatePeriod = mSec;
266 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT);
267 } else {
268 interface_unlock_exclusive(thiz);
269 }
270 result = SL_RESULT_SUCCESS;
271 }
272
273 SL_LEAVE_INTERFACE
274 }
275
276
IRecord_GetPositionUpdatePeriod(SLRecordItf self,SLmillisecond * pMsec)277 static SLresult IRecord_GetPositionUpdatePeriod(SLRecordItf self, SLmillisecond *pMsec)
278 {
279 SL_ENTER_INTERFACE
280
281 if (NULL == pMsec) {
282 result = SL_RESULT_PARAMETER_INVALID;
283 } else {
284 IRecord *thiz = (IRecord *) self;
285 interface_lock_shared(thiz);
286 SLmillisecond positionUpdatePeriod = thiz->mPositionUpdatePeriod;
287 interface_unlock_shared(thiz);
288 *pMsec = positionUpdatePeriod;
289 result = SL_RESULT_SUCCESS;
290 }
291
292 SL_LEAVE_INTERFACE
293 }
294
295
296 static const struct SLRecordItf_ IRecord_Itf = {
297 IRecord_SetRecordState,
298 IRecord_GetRecordState,
299 IRecord_SetDurationLimit,
300 IRecord_GetPosition,
301 IRecord_RegisterCallback,
302 IRecord_SetCallbackEventsMask,
303 IRecord_GetCallbackEventsMask,
304 IRecord_SetMarkerPosition,
305 IRecord_ClearMarkerPosition,
306 IRecord_GetMarkerPosition,
307 IRecord_SetPositionUpdatePeriod,
308 IRecord_GetPositionUpdatePeriod
309 };
310
IRecord_init(void * self)311 void IRecord_init(void *self)
312 {
313 IRecord *thiz = (IRecord *) self;
314 thiz->mItf = &IRecord_Itf;
315 thiz->mState = SL_RECORDSTATE_STOPPED;
316 thiz->mDurationLimit = 0;
317 thiz->mPosition = (SLmillisecond) 0;
318 thiz->mCallback = NULL;
319 thiz->mContext = NULL;
320 thiz->mCallbackEventsMask = 0;
321 thiz->mMarkerPosition = SL_TIME_UNKNOWN;
322 thiz->mPositionUpdatePeriod = 1000; // per spec
323 }
324