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 *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 50static 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 69static 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 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 *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 116static 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 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 *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 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 *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 179static 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 207static 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 232static 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 255static 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 277static 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 296static 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 311void 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