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